#[allow(unused)] use crate::float::FloatExt;
use crate::{varint_size, FeeRate, TR_KEYSPEND_TXIN_WEIGHT, TR_SPK_WEIGHT, TXOUT_BASE_WEIGHT};
#[derive(Default, Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct DrainWeights {
pub output_weight: u64,
pub spend_weight: u64,
pub n_outputs: usize,
}
impl DrainWeights {
pub const TR_KEYSPEND: Self = Self {
output_weight: TXOUT_BASE_WEIGHT + TR_SPK_WEIGHT,
spend_weight: TR_KEYSPEND_TXIN_WEIGHT,
n_outputs: 1,
};
pub const NONE: Self = Self {
output_weight: 0,
spend_weight: 0,
n_outputs: 0,
};
pub fn waste(
&self,
feerate: FeeRate,
long_term_feerate: FeeRate,
n_target_outputs: usize,
) -> f32 {
let extra_varint_weight =
(varint_size(n_target_outputs + self.n_outputs) - varint_size(n_target_outputs)) * 4;
let extra_output_weight = self.output_weight + extra_varint_weight;
extra_output_weight as f32 * feerate.spwu()
+ self.spend_weight as f32 * long_term_feerate.spwu()
}
pub fn spend_fee(&self, long_term_feerate: FeeRate) -> u64 {
(self.spend_weight as f32 * long_term_feerate.spwu()).ceil() as u64
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub struct Drain {
pub weights: DrainWeights,
pub value: u64,
}
impl Drain {
pub const NONE: Self = Drain {
weights: DrainWeights::NONE,
value: 0,
};
pub fn is_none(&self) -> bool {
self == &Drain::NONE
}
pub fn is_some(&self) -> bool {
!self.is_none()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ChangePolicy {
pub min_value: u64,
pub drain_weights: DrainWeights,
}
impl ChangePolicy {
pub fn min_value(drain_weights: DrainWeights, min_value: u64) -> Self {
Self {
drain_weights,
min_value,
}
}
pub fn min_value_and_waste(
drain_weights: DrainWeights,
min_value: u64,
target_feerate: FeeRate,
long_term_feerate: FeeRate,
) -> Self {
let waste_with_change = drain_weights
.waste(
target_feerate,
long_term_feerate,
0,
)
.ceil() as u64;
Self {
drain_weights,
min_value: waste_with_change.max(min_value),
}
}
}