@@ -169,29 +169,10 @@ impl<'a> CoinSelector<'a> {
169
169
/// enough value.
170
170
///
171
171
/// [`ban`]: Self::ban
172
- pub fn is_selection_possible ( & self , target : Target , drain : Drain ) -> bool {
172
+ pub fn is_selection_possible ( & self , target : Target ) -> bool {
173
173
let mut test = self . clone ( ) ;
174
174
test. select_all_effective ( target. feerate ) ;
175
- test. is_target_met ( target, drain)
176
- }
177
-
178
- /// Is meeting the target *plausible* with this `change_policy`.
179
- /// Note this will respect [`ban`]ned candidates.
180
- ///
181
- /// This is very similar to [`is_selection_possible`] except that you pass in a change policy.
182
- /// This method will give the right answer as long as `change_policy` is monotone but otherwise
183
- /// can it can give false negatives.
184
- ///
185
- /// [`ban`]: Self::ban
186
- /// [`is_selection_possible`]: Self::is_selection_possible
187
- pub fn is_selection_plausible_with_change_policy (
188
- & self ,
189
- target : Target ,
190
- change_policy : & impl Fn ( & CoinSelector < ' a > , Target ) -> Drain ,
191
- ) -> bool {
192
- let mut test = self . clone ( ) ;
193
- test. select_all_effective ( target. feerate ) ;
194
- test. is_target_met ( target, change_policy ( & test, target) )
175
+ test. is_target_met ( target)
195
176
}
196
177
197
178
/// Returns true if no candidates have been selected.
@@ -283,6 +264,14 @@ impl<'a> CoinSelector<'a> {
283
264
( self . weight ( drain_weight) as f32 * feerate. spwu ( ) ) . ceil ( ) as u64
284
265
}
285
266
267
+ /// The actual fee the selection would pay if it was used in a transaction that had
268
+ /// `target_value` value for outputs and change output of `drain_value`.
269
+ ///
270
+ /// This can be negative when the selection is invalid (outputs are greater than inputs).
271
+ pub fn fee ( & self , target_value : u64 , drain_value : u64 ) -> i64 {
272
+ self . selected_value ( ) as i64 - target_value as i64 - drain_value as i64
273
+ }
274
+
286
275
/// The value of the current selected inputs minus the fee needed to pay for the selected inputs
287
276
pub fn effective_value ( & self , feerate : FeeRate ) -> i64 {
288
277
self . selected_value ( ) as i64 - ( self . input_weight ( ) as f32 * feerate. spwu ( ) ) . ceil ( ) as i64
@@ -330,7 +319,9 @@ impl<'a> CoinSelector<'a> {
330
319
331
320
/// Sorts the candidates by descending value per weight unit, tie-breaking with value.
332
321
pub fn sort_candidates_by_descending_value_pwu ( & mut self ) {
333
- self . sort_candidates_by_key ( |( _, wv) | core:: cmp:: Reverse ( ( wv. value_pwu ( ) , wv. value ) ) ) ;
322
+ self . sort_candidates_by_key ( |( _, wv) | {
323
+ core:: cmp:: Reverse ( ( Ordf32 ( wv. value_pwu ( ) ) , wv. value ) )
324
+ } ) ;
334
325
}
335
326
336
327
/// The waste created by the current selection as measured by the [waste metric].
@@ -405,19 +396,30 @@ impl<'a> CoinSelector<'a> {
405
396
self . unselected_indices ( ) . next ( ) . is_none ( )
406
397
}
407
398
408
- /// Whether the constraints of `Target` have been met if we include the `drain` ouput.
409
- pub fn is_target_met ( & self , target : Target , drain : Drain ) -> bool {
399
+ /// Whether the constraints of `Target` have been met if we include a specific `drain` ouput.
400
+ ///
401
+ /// Note if [`is_target_met`] is true and the `drain` is produced from the [`drain`] method then
402
+ /// this method will also always be true.
403
+ ///
404
+ /// [`is_target_met`]: Self::is_target_met
405
+ /// [`drain`]: Self::drain
406
+ pub fn is_target_met_with_drain ( & self , target : Target , drain : Drain ) -> bool {
410
407
self . excess ( target, drain) >= 0
411
408
}
412
409
410
+ /// Whether the constraints of `Target` have been met.
411
+ pub fn is_target_met ( & self , target : Target ) -> bool {
412
+ self . is_target_met_with_drain ( target, Drain :: none ( ) )
413
+ }
414
+
413
415
/// Whether the constrains of `Target` have been met if we include the drain (change) output
414
416
/// when `change_policy` decides it should be present.
415
417
pub fn is_target_met_with_change_policy (
416
418
& self ,
417
419
target : Target ,
418
420
change_policy : ChangePolicy ,
419
421
) -> bool {
420
- self . is_target_met ( target, self . drain ( target, change_policy) )
422
+ self . is_target_met_with_drain ( target, self . drain ( target, change_policy) )
421
423
}
422
424
423
425
/// Select all unselected candidates
@@ -442,17 +444,34 @@ impl<'a> CoinSelector<'a> {
442
444
} ,
443
445
) ;
444
446
if excess > change_policy. min_value as i64 {
447
+ debug_assert_eq ! (
448
+ self . is_target_met( target) ,
449
+ self . is_target_met_with_drain(
450
+ target,
451
+ Drain {
452
+ weights: change_policy. drain_weights,
453
+ value: excess as u64
454
+ }
455
+ ) ,
456
+ "if the target is met without a drain it must be met after adding the drain"
457
+ ) ;
445
458
Some ( excess as u64 )
446
459
} else {
447
460
None
448
461
}
449
462
}
450
463
451
- /// Convienince method that calls [`drain_value`] and converts the result into `Drain` by using
452
- /// the provided `DrainWeights`. Note carefully that the `change_policy` should have been
453
- /// calculated with the same `DrainWeights`.
464
+ /// Figures out whether the current selection should have a change output given the
465
+ /// `change_policy`. If it shouldn't then it will return a `Drain` where [`Drain::is_none`] is
466
+ /// true. The value of the `Drain` will be the same as [`drain_value`].
467
+ ///
468
+ /// If [`is_target_met`] returns true for this selection then [`is_target_met_with_drain`] will
469
+ /// also be true if you pass in the drain returned from this method.
454
470
///
455
471
/// [`drain_value`]: Self::drain_value
472
+ /// [`is_target_met_with_drain`]: Self::is_target_met_with_drain
473
+ /// [`is_target_met`]: Self::is_target_met
474
+ #[ must_use]
456
475
pub fn drain ( & self , target : Target , change_policy : ChangePolicy ) -> Drain {
457
476
match self . drain_value ( target, change_policy) {
458
477
Some ( value) => Drain {
@@ -470,7 +489,7 @@ impl<'a> CoinSelector<'a> {
470
489
for cand_index in self . candidate_order . iter ( ) {
471
490
if self . selected . contains ( cand_index)
472
491
|| self . banned . contains ( cand_index)
473
- || self . candidates [ * cand_index] . effective_value ( feerate) <= Ordf32 ( 0.0 )
492
+ || self . candidates [ * cand_index] . effective_value ( feerate) <= 0.0
474
493
{
475
494
continue ;
476
495
}
@@ -486,7 +505,7 @@ impl<'a> CoinSelector<'a> {
486
505
target : Target ,
487
506
drain : Drain ,
488
507
) -> Result < ( ) , InsufficientFunds > {
489
- self . select_until ( |cs| cs. is_target_met ( target, drain) )
508
+ self . select_until ( |cs| cs. is_target_met_with_drain ( target, drain) )
490
509
. ok_or_else ( || InsufficientFunds {
491
510
missing : self . excess ( target, drain) . unsigned_abs ( ) ,
492
511
} )
@@ -615,13 +634,13 @@ impl Candidate {
615
634
}
616
635
617
636
/// Effective value of this input candidate: `actual_value - input_weight * feerate (sats/wu)`.
618
- pub fn effective_value ( & self , feerate : FeeRate ) -> Ordf32 {
619
- Ordf32 ( self . value as f32 - ( self . weight as f32 * feerate. spwu ( ) ) )
637
+ pub fn effective_value ( & self , feerate : FeeRate ) -> f32 {
638
+ self . value as f32 - ( self . weight as f32 * feerate. spwu ( ) )
620
639
}
621
640
622
641
/// Value per weight unit
623
- pub fn value_pwu ( & self ) -> Ordf32 {
624
- Ordf32 ( self . value as f32 / self . weight as f32 )
642
+ pub fn value_pwu ( & self ) -> f32 {
643
+ self . value as f32 / self . weight as f32
625
644
}
626
645
}
627
646
@@ -647,11 +666,17 @@ impl DrainWeights {
647
666
+ self . spend_weight as f32 * long_term_feerate. spwu ( )
648
667
}
649
668
650
- /// Create [`DrainWeights`] that represents a drain output with a taproot keyspend.
669
+ /// The fee you will pay to spend these change output(s) in the future.
670
+ pub fn spend_fee ( & self , long_term_feerate : FeeRate ) -> u64 {
671
+ ( self . spend_weight as f32 * long_term_feerate. spwu ( ) ) . ceil ( ) as u64
672
+ }
673
+
674
+ /// Create [`DrainWeights`] that represents a drain output that will be spent with a taproot
675
+ /// keyspend
651
676
pub fn new_tr_keyspend ( ) -> Self {
652
677
Self {
653
678
output_weight : TXOUT_BASE_WEIGHT + TR_SPK_WEIGHT ,
654
- spend_weight : TXIN_BASE_WEIGHT + TR_KEYSPEND_SATISFACTION_WEIGHT ,
679
+ spend_weight : TR_KEYSPEND_TXIN_WEIGHT ,
655
680
}
656
681
}
657
682
}
0 commit comments