11use  bdk_coin_select:: { 
22    ChangePolicy ,  DrainWeights ,  InsufficientFunds ,  Replace ,  Target ,  TargetFee ,  TargetOutputs , 
33} ; 
4- use  bitcoin:: { Amount ,  FeeRate ,  ScriptBuf ,   Transaction ,  TxOut ,  Weight } ; 
4+ use  bitcoin:: { Amount ,  FeeRate ,  Transaction ,  TxOut ,  Weight } ; 
55use  miniscript:: bitcoin; 
66
7- use  crate :: { cs_feerate,  DefiniteDescriptor ,   InputCandidates ,  InputGroup ,  Output ,  Selection } ; 
7+ use  crate :: { cs_feerate,  InputCandidates ,  InputGroup ,  Output ,   ScriptSource ,  Selection } ; 
88use  alloc:: vec:: Vec ; 
99use  core:: fmt; 
1010
@@ -15,51 +15,10 @@ pub struct Selector<'c> {
1515    target_outputs :  Vec < Output > , 
1616    target :  Target , 
1717    change_policy :  bdk_coin_select:: ChangePolicy , 
18-     change_descriptor :   ChangeDescriptor , 
18+     change_source :   ScriptSource , 
1919    inner :  bdk_coin_select:: CoinSelector < ' c > , 
2020} 
2121
22- /// Data source to create a change output if needed 
23- #[ derive( Debug ,  Clone ) ]  
24- pub  enum  ChangeDescriptor  { 
25-     /// Build change output from descriptor 
26- Definite ( DefiniteDescriptor ) , 
27-     /// Build change output without descriptor 
28- Manual  { 
29-         /// The final script pubkey the change output should have 
30- script_pubkey :  ScriptBuf , 
31-         /// The maximum weight to satisfy the script pubkey 
32- max_weight_to_satisfy_wu :  u64 , 
33-     } , 
34- } 
35- 
36- /// Wrapper methods to unify interface for change outputs 
37- impl  ChangeDescriptor  { 
38-     /// Get the maximum weight to satisfy the script pubkey of the resultant output 
39- pub  fn  get_max_weight_to_satisfy_wu ( & self )  -> Result < u64 ,  miniscript:: Error >  { 
40-         use  ChangeDescriptor :: * ; 
41- 
42-         match  self  { 
43-             Definite ( definite_descriptor)  => definite_descriptor
44-                 . max_weight_to_satisfy ( ) 
45-                 . map ( |weight| weight. to_wu ( ) ) , 
46-             Manual  { 
47-                 max_weight_to_satisfy_wu, 
48-                 ..
49-             }  => Ok ( * max_weight_to_satisfy_wu) , 
50-         } 
51-     } 
52- 
53-     /// Get the script pubkey the change output should have 
54- pub  fn  get_script_pubkey ( & self )  -> ScriptBuf  { 
55-         use  ChangeDescriptor :: * ; 
56-         match  self  { 
57-             Definite ( definite_descriptor)  => definite_descriptor. script_pubkey ( ) , 
58-             Manual  {  script_pubkey,  .. }  => script_pubkey. clone ( ) , 
59-         } 
60-     } 
61- } 
62- 
6322/// Parameters for creating tx. 
6423/// 
6524/// TODO: Create a builder interface on this that does checks. I.e. 
@@ -83,7 +42,7 @@ pub struct SelectorParams {
8342    /// To derive change output. 
8443/// 
8544/// Will error if this is unsatisfiable descriptor. 
86- pub  change_descriptor :   ChangeDescriptor , 
45+ pub  change_source :   ScriptSource , 
8746
8847    /// The policy to determine whether we create a change output. 
8948pub  change_policy :  ChangePolicyType , 
@@ -181,11 +140,11 @@ impl SelectorParams {
181140pub  fn  new ( 
182141        target_feerate :  bitcoin:: FeeRate , 
183142        target_outputs :  Vec < Output > , 
184-         change_descriptor :   ChangeDescriptor , 
143+         change_source :   ScriptSource , 
185144        change_policy :  ChangePolicyType , 
186145    )  -> Self  { 
187146        Self  { 
188-             change_descriptor , 
147+             change_source , 
189148            change_policy, 
190149            target_feerate, 
191150            target_outputs, 
@@ -216,32 +175,49 @@ impl SelectorParams {
216175/// 
217176/// # Error 
218177/// 
219- /// Fails if `change_descriptor` cannot be satisfied. 
220- pub  fn  to_cs_change_weights ( & self )  -> Result < bdk_coin_select:: DrainWeights ,  miniscript:: Error >  { 
221-         Ok ( DrainWeights  { 
178+ /// Fails if `change_source` cannot be satisfied. 
179+ pub  fn  to_cs_change_weights ( & self )  -> Result < bdk_coin_select:: DrainWeights ,  SelectorError >  { 
180+         let  ( script_pubkey,  spend_weight)  = match  & self . change_source  { 
181+             ScriptSource :: Script  { 
182+                 script_pubkey, 
183+                 max_weight_to_satisfy, 
184+             }  => { 
185+                 if  let  Some ( weight)  = max_weight_to_satisfy { 
186+                     ( script_pubkey. clone ( ) ,  weight. to_wu ( ) ) 
187+                 }  else  { 
188+                     return  Err ( SelectorError :: MissingChangeSatisfactionWeight ) ; 
189+                 } 
190+             } 
191+             ScriptSource :: Descriptor ( definite_descriptor)  => { 
192+                 let  script_pubkey = definite_descriptor. script_pubkey ( ) ; 
193+                 let  weight = definite_descriptor
194+                     . max_weight_to_satisfy ( ) 
195+                     . map ( |weight| weight. to_wu ( ) ) 
196+                     . map_err ( SelectorError :: Miniscript ) ?; 
197+                 ( script_pubkey,  weight) 
198+             } 
199+         } ; 
200+         let  drain_weight = DrainWeights  { 
222201            output_weight :  ( TxOut  { 
223-                 script_pubkey :   self . change_descriptor . get_script_pubkey ( ) , 
202+                 script_pubkey, 
224203                value :  Amount :: ZERO , 
225204            } ) 
226205            . weight ( ) 
227206            . to_wu ( ) , 
228-             spend_weight :   self . change_descriptor . get_max_weight_to_satisfy_wu ( ) ? , 
207+             spend_weight, 
229208            n_outputs :  1 , 
230-         } ) 
209+         } ; 
210+         Ok ( drain_weight) 
231211    } 
232212
233213    /// To change policy. 
234214/// 
235215/// # Error 
236216/// 
237- /// Fails if `change_descriptor ` cannot be satisfied. 
238- pub  fn  to_cs_change_policy ( & self )  -> Result < bdk_coin_select:: ChangePolicy ,  miniscript :: Error >  { 
217+ /// Fails if `change_source ` cannot be satisfied. 
218+ pub  fn  to_cs_change_policy ( & self )  -> Result < bdk_coin_select:: ChangePolicy ,  SelectorError >  { 
239219        let  change_weights = self . to_cs_change_weights ( ) ?; 
240-         let  dust_value = self 
241-             . change_descriptor 
242-             . get_script_pubkey ( ) 
243-             . minimal_non_dust ( ) 
244-             . to_sat ( ) ; 
220+         let  dust_value = self . change_source . script ( ) . minimal_non_dust ( ) . to_sat ( ) ; 
245221        Ok ( match  self . change_policy  { 
246222            ChangePolicyType :: NoDust  => ChangePolicy :: min_value ( change_weights,  dust_value) , 
247223            ChangePolicyType :: NoDustAndLeastWaste  {  longterm_feerate }  => { 
@@ -311,11 +287,9 @@ impl<'c> Selector<'c> {
311287        params :  SelectorParams , 
312288    )  -> Result < Self ,  SelectorError >  { 
313289        let  target = params. to_cs_target ( ) ; 
314-         let  change_policy = params
315-             . to_cs_change_policy ( ) 
316-             . map_err ( SelectorError :: Miniscript ) ?; 
290+         let  change_policy = params. to_cs_change_policy ( ) ?; 
317291        let  target_outputs = params. target_outputs ; 
318-         let  change_descriptor  = params. change_descriptor ; 
292+         let  change_source  = params. change_source ; 
319293        if  target. value ( )  > candidates. groups ( ) . map ( |grp| grp. value ( ) . to_sat ( ) ) . sum ( )  { 
320294            return  Err ( SelectorError :: CannotMeetTarget ( CannotMeetTarget ) ) ; 
321295        } 
@@ -328,7 +302,7 @@ impl<'c> Selector<'c> {
328302            target, 
329303            target_outputs, 
330304            change_policy, 
331-             change_descriptor , 
305+             change_source , 
332306            inner, 
333307        } ) 
334308    } 
@@ -405,10 +379,16 @@ impl<'c> Selector<'c> {
405379            outputs :  { 
406380                let  mut  outputs = self . target_outputs . clone ( ) ; 
407381                if  maybe_change. is_some ( )  { 
408-                     outputs. push ( Output :: with_script ( 
409-                         self . change_descriptor . get_script_pubkey ( ) , 
410-                         Amount :: from_sat ( maybe_change. value ) , 
411-                     ) ) ; 
382+                     let  change_amount = Amount :: from_sat ( maybe_change. value ) ; 
383+                     let  change_output = match  & self . change_source  { 
384+                         ScriptSource :: Descriptor ( definite_descriptor)  => { 
385+                             Output :: with_descriptor ( * definite_descriptor. clone ( ) ,  change_amount) 
386+                         } 
387+                         ScriptSource :: Script  {  script_pubkey,  .. }  => { 
388+                             Output :: with_script ( script_pubkey. clone ( ) ,  change_amount) 
389+                         } 
390+                     } ; 
391+                     outputs. push ( change_output) ; 
412392                } 
413393                outputs
414394            } , 
0 commit comments