Skip to content

Commit 8f0e2bd

Browse files
committed
refactor: move weighted_utxo to seperate module
1 parent 1374b87 commit 8f0e2bd

File tree

2 files changed

+94
-87
lines changed

2 files changed

+94
-87
lines changed

src/lib.rs

Lines changed: 4 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ mod branch_and_bound;
1515
mod coin_grinder;
1616
mod single_random_draw;
1717

18+
mod weighted_utxo;
19+
20+
pub use crate::weighted_utxo::WeightedUtxo;
21+
1822
/// Possible returned error types if no match is found.
1923
pub mod errors;
2024

21-
use std::cmp::Ordering;
22-
2325
use bitcoin_units::{Amount, FeeRate, SignedAmount, Weight};
2426
#[cfg(feature = "rand")]
2527
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
@@ -60,91 +62,6 @@ pub(crate) fn effective_value(
6062
Some(eff_value)
6163
}
6264

63-
#[derive(Debug, Clone, PartialEq, Eq)]
64-
/// Represents the spendable conditions of a `UTXO`.
65-
pub struct WeightedUtxo {
66-
/// The `Amount` that the output contributes towards the selection target.
67-
value: Amount,
68-
/// The estimated `Weight` (satisfaction weight + base weight) of the output.
69-
weight: Weight,
70-
/// The positive effective value `(value - fee)`. This value is stored as a `u64` for
71-
/// better performance.
72-
effective_value: u64,
73-
/// The `SignedAmount` required to spend the output at the given `fee_rate`.
74-
fee: SignedAmount,
75-
/// The `SignedAmount` required to spend the output at the given `long_term_fee_rate`.
76-
long_term_fee: SignedAmount,
77-
/// A metric for how wasteful it is to spend this `WeightedUtxo` given the current fee
78-
/// environment.
79-
waste: i64,
80-
}
81-
82-
impl WeightedUtxo {
83-
/// Creates a new `WeightedUtxo`.
84-
pub fn new(
85-
value: Amount,
86-
weight: Weight,
87-
fee_rate: FeeRate,
88-
long_term_fee_rate: FeeRate,
89-
) -> Option<WeightedUtxo> {
90-
let positive_effective_value = Self::positive_effective_value(fee_rate, weight, value);
91-
92-
if let Some(effective_value) = positive_effective_value {
93-
let fee = fee_rate.fee_wu(weight)?.to_signed();
94-
let long_term_fee: SignedAmount = long_term_fee_rate.fee_wu(weight)?.to_signed();
95-
let waste = Self::calculate_waste(fee, long_term_fee);
96-
return Some(Self { value, weight, effective_value, fee, long_term_fee, waste });
97-
}
98-
99-
None
100-
}
101-
102-
/// Calculates if the current fee environment is expensive.
103-
pub fn is_fee_expensive(&self) -> bool { self.fee > self.long_term_fee }
104-
105-
/// Returns the associated value.
106-
pub fn value(&self) -> Amount { self.value }
107-
108-
/// Returns the associated weight.
109-
pub fn weight(&self) -> Weight { self.weight }
110-
111-
/// Returns the associated waste.
112-
pub fn waste(&self) -> SignedAmount { SignedAmount::from_sat(self.waste).unwrap() }
113-
114-
/// Returns the calculated effective value.
115-
pub fn effective_value(&self) -> Amount { Amount::from_sat(self.effective_value).unwrap() }
116-
117-
/// Returns the calculated effective value using the underlying type without transformation.
118-
pub fn effective_value_raw(&self) -> u64 { self.effective_value }
119-
120-
/// Returns the calculated waste using the underlying type without transformation.
121-
pub fn waste_raw(&self) -> i64 { self.waste }
122-
123-
fn positive_effective_value(fee_rate: FeeRate, weight: Weight, value: Amount) -> Option<u64> {
124-
if let Some(eff_value) = effective_value(fee_rate, weight, value) {
125-
if let Ok(unsigned) = eff_value.to_unsigned() {
126-
return Some(unsigned.to_sat());
127-
}
128-
}
129-
130-
None
131-
}
132-
133-
fn calculate_waste(fee: SignedAmount, long_term_fee: SignedAmount) -> i64 {
134-
fee.to_sat() - long_term_fee.to_sat()
135-
}
136-
}
137-
138-
impl Ord for WeightedUtxo {
139-
fn cmp(&self, other: &Self) -> Ordering {
140-
other.effective_value.cmp(&self.effective_value).then(self.weight.cmp(&other.weight))
141-
}
142-
}
143-
144-
impl PartialOrd for WeightedUtxo {
145-
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
146-
}
147-
14865
/// Attempt a match with [`branch_and_bound`] falling back to [`single_random_draw`].
14966
///
15067
/// If [`branch_and_bound`] fails to find a changeless solution (basically, an exact match), then

src/weighted_utxo.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use std::cmp::Ordering;
2+
3+
use bitcoin_units::{Amount, FeeRate, SignedAmount, Weight};
4+
5+
use crate::effective_value;
6+
7+
#[derive(Debug, Clone, PartialEq, Eq)]
8+
/// Represents the spendable conditions of a `UTXO`.
9+
pub struct WeightedUtxo {
10+
/// The `Amount` that the output contributes towards the selection target.
11+
value: Amount,
12+
/// The estimated `Weight` (satisfaction weight + base weight) of the output.
13+
weight: Weight,
14+
/// The positive effective value `(value - fee)`. This value is stored as a `u64` for
15+
/// better performance.
16+
effective_value: u64,
17+
/// The `SignedAmount` required to spend the output at the given `fee_rate`.
18+
fee: SignedAmount,
19+
/// The `SignedAmount` required to spend the output at the given `long_term_fee_rate`.
20+
long_term_fee: SignedAmount,
21+
/// A metric for how wasteful it is to spend this `WeightedUtxo` given the current fee
22+
/// environment.
23+
waste: i64,
24+
}
25+
26+
impl WeightedUtxo {
27+
/// Creates a new `WeightedUtxo`.
28+
pub fn new(
29+
value: Amount,
30+
weight: Weight,
31+
fee_rate: FeeRate,
32+
long_term_fee_rate: FeeRate,
33+
) -> Option<WeightedUtxo> {
34+
let positive_effective_value = Self::positive_effective_value(fee_rate, weight, value);
35+
36+
if let Some(effective_value) = positive_effective_value {
37+
let fee = fee_rate.fee_wu(weight)?.to_signed();
38+
let long_term_fee: SignedAmount = long_term_fee_rate.fee_wu(weight)?.to_signed();
39+
let waste = Self::calculate_waste(fee, long_term_fee);
40+
return Some(Self { value, weight, effective_value, fee, long_term_fee, waste });
41+
}
42+
43+
None
44+
}
45+
46+
/// Calculates if the current fee environment is expensive.
47+
pub fn is_fee_expensive(&self) -> bool { self.fee > self.long_term_fee }
48+
49+
/// Returns the associated value.
50+
pub fn value(&self) -> Amount { self.value }
51+
52+
/// Returns the associated weight.
53+
pub fn weight(&self) -> Weight { self.weight }
54+
55+
/// Returns the associated waste.
56+
pub fn waste(&self) -> SignedAmount { SignedAmount::from_sat(self.waste).unwrap() }
57+
58+
/// Returns the calculated effective value.
59+
pub fn effective_value(&self) -> Amount { Amount::from_sat(self.effective_value).unwrap() }
60+
61+
/// Returns the calculated effective value using the underlying type without transformation.
62+
pub fn effective_value_raw(&self) -> u64 { self.effective_value }
63+
64+
/// Returns the calculated waste using the underlying type without transformation.
65+
pub fn waste_raw(&self) -> i64 { self.waste }
66+
67+
fn positive_effective_value(fee_rate: FeeRate, weight: Weight, value: Amount) -> Option<u64> {
68+
if let Some(eff_value) = effective_value(fee_rate, weight, value) {
69+
if let Ok(unsigned) = eff_value.to_unsigned() {
70+
return Some(unsigned.to_sat());
71+
}
72+
}
73+
74+
None
75+
}
76+
77+
fn calculate_waste(fee: SignedAmount, long_term_fee: SignedAmount) -> i64 {
78+
fee.to_sat() - long_term_fee.to_sat()
79+
}
80+
}
81+
82+
impl Ord for WeightedUtxo {
83+
fn cmp(&self, other: &Self) -> Ordering {
84+
other.effective_value.cmp(&self.effective_value).then(self.weight.cmp(&other.weight))
85+
}
86+
}
87+
88+
impl PartialOrd for WeightedUtxo {
89+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
90+
}

0 commit comments

Comments
 (0)