Skip to main content

rust_coinselect/
types.rs

1/// Represents an input candidate for Coinselection, either as a single UTXO or a group of UTXOs.
2///
3/// A [`OutputGroup`] can be a single UTXO or a group that should be spent together.
4/// Grouping UTXOs belonging to a single address is privacy preserving than grouping UTXOs belonging to different addresses.
5/// In the UTXO model the output of a transaction is used as the input for the new transaction and hence the name [`OutputGroup`]
6/// The library user must craft this structure correctly, as incorrect representation can lead to incorrect selection results.
7#[derive(Debug, Clone)]
8pub struct OutputGroup {
9    /// Total value of the UTXO(s) that this `WeightedValue` represents.
10    pub value: u64,
11    /// Total weight of including these UTXO(s) in the transaction.
12    ///
13    /// The `txin` fields: `prevout`, `nSequence`, `scriptSigLen`, `scriptSig`, `scriptWitnessLen`,
14    /// and `scriptWitness` should all be included.
15    pub weight: u64,
16    /// The total number of inputs
17    pub input_count: usize,
18    /// Specifies the relative creation sequence for this group, used only for FIFO selection.
19    ///
20    /// Set to `None` if FIFO selection is not required. Sequence numbers are arbitrary indices that denote the relative age of a UTXO group among a set of groups.
21    /// To denote the oldest UTXO group, assign it a sequence number of `Some(0)`.
22    pub creation_sequence: Option<u32>,
23}
24
25#[cfg(test)]
26pub(crate) fn basic_output_group(value: u64, weight: u64) -> OutputGroup {
27    OutputGroup {
28        value,
29        weight,
30        input_count: 1,
31        creation_sequence: None,
32    }
33}
34
35/// Options required to compute fees and waste metric.
36#[derive(Debug, Clone)]
37pub struct CoinSelectionOpt {
38    /// The value we need to select.
39    pub target_value: u64,
40
41    /// The target feerate we should try and achieve in sats per weight unit.
42    pub target_feerate: f32,
43
44    /// The long term fee-rate is an estimate of the future transaction fee rate that a wallet might need to pay to spend its UTXOs.
45    /// If the current fee rates are less than the long term fee rate, it is optimal to consolidate UTXOs to make the spend.
46    /// It affects how the [`WasteMetric`] is computed.
47    pub long_term_feerate: Option<f32>,
48
49    /// Lowest possible transaction fee required to get a transaction included in a block
50    pub min_absolute_fee: u64,
51
52    /// Weights of data in transaction other than the list of inputs that would be selected.
53    ///
54    /// This includes weight of the header, total weight out outputs, weight of fields used
55    /// to represent number number of inputs and number outputs, witness etc.,
56    pub base_weight: u64,
57
58    /// Additional weigh added to a transaction when a change output is created.
59    /// Used in weight metric computation.
60    pub change_weight: u64,
61
62    /// Total cost associated with creating and later spending a change output in a transaction.
63    /// This includes the transaction fees for both the current transaction (where the change is created) and the future transaction (where the change is spent)
64    pub change_cost: u64,
65
66    /// The smallest amount of change that is considered acceptable in a transaction given the dust limit
67    pub min_change_value: u64,
68
69    /// Strategy to use the excess value other than fee and target
70    pub excess_strategy: ExcessStrategy,
71}
72
73/// Strategy to decide what to do with the excess amount.
74#[derive(Clone, Debug, PartialEq, Eq)]
75pub enum ExcessStrategy {
76    /// Adds the excess amount to the transaction fee. This increases the fee rate
77    /// and may lead to faster confirmation, but wastes the excess amount.
78    ToFee,
79
80    /// Adds the excess amount to the recipient's output. This avoids creating a change
81    /// output and reduces transaction size, but may reveal information about the
82    /// wallet's available UTXOs.
83    ToRecipient,
84
85    /// Creates a change output with the excess amount. This preserves privacy and
86    /// allows reuse of the excess amount in future transactions, but increases
87    /// transaction size and creates dust UTXOs if the amount is too small.
88    ToChange,
89}
90
91/// Error Describing failure of a selection attempt, on any subset of inputs.
92#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
93pub enum SelectionError {
94    /// The available UTXOs cannot cover the target and fees for spending the supplied inputs.
95    InsufficientFunds {
96        available: u64,
97        required: u64,
98    },
99    NoSolutionFound,
100    NonPositiveTarget,
101    NonPositiveFeeRate,
102    AbnormallyHighFeeRate,
103}
104
105/// Measures the efficiency of input selection in satoshis, helping evaluate algorithms based on current and long-term fee rates
106///
107/// WasteMetric strikes a balance between minimizing current transaction fees and overall fees during the wallet's lifetime.
108/// In high fee rate environments, selecting fewer inputs reduces transaction fees.
109/// In low fee rate environments, selecting more inputs reduces overall fees.
110/// It compares various selection algorithms to find the most optimized solution, represented by the lowest [WasteMetric] value.
111#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
112pub struct WasteMetric(pub i64);
113
114/// Identifies which selection algorithm produced a given [`SelectionOutput`].
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
116pub enum SelectionAlgorithm {
117    BranchAndBound,
118    CoinGrinder,
119    Fifo,
120    LowestLarger,
121}
122
123/// The result of selection algorithm.
124#[derive(Debug)]
125pub struct SelectionOutput {
126    /// The selected input indices, refers to the indices of the inputs Slice Reference.
127    pub selected_inputs: Vec<usize>,
128    /// The waste amount, for the above inputs.
129    pub waste: WasteMetric,
130    /// The transaction fee (in satoshis) for the above inputs.
131    pub fee: u64,
132}
133
134/// EffectiveValue type alias
135pub type EffectiveValue = u64;
136
137/// Weight type alias
138pub type Weight = u64;
139
140/// Upper bound on explored nodes,the bounded-search policy used by BnB and Coingrinder.
141pub const TOTAL_TRIES: u32 = 100_000;