BDK Coin Selection
bdk_coin_select is a tool to help you select inputs for making Bitcoin (ticker: BTC) transactions.
It's got zero dependencies so you can paste it into your project without concern.
Constructing the CoinSelector
The main structure is CoinSelector. To construct it, we specify a list of
candidate UTXOs and a transaction base_weight. The base_weight includes the recipient outputs
and mandatory inputs (if any).
use FromStr;
use ;
use ;
// You should use miniscript to figure out the satisfaction weight for your coins!
const TR_INPUT_WEIGHT: u32 = TXIN_BASE_WEIGHT + TR_KEYSPEND_SATISFACTION_WEIGHT;
// The address where we want to send our coins.
let recipient_addr =
from_str
.expect
.require_network
.expect;
let candidates = vec!;
let base_tx = Transaction ;
let base_weight = base_tx.weight.to_wu as u32;
println!;
// You can now select coins!
let mut coin_selector = new;
coin_selector.select;
Change Policy
A change policy determines whether the drain output(s) should be in the final solution. A change
policy is represented by a closure of signature Fn(&CoinSelector, Target) -> Drain. We provide 3
built-in change policies; min_value, min_waste and min_value_and_waste (refer to the
module-level docs for more).
Typically, to construct a change policy, the [DrainWeights] need to be provided. DrainWeights
includes two weights. One is the weight of the drain output(s). The other is the weight of spending
the drain output later on (the input weight).
# use FromStr;
# use ;
# use ;
use min_value;
# const TR_SATISFACTION_WEIGHT: u32 = 66;
# const TR_INPUT_WEIGHT: u32 = TXIN_BASE_WEIGHT + TR_SATISFACTION_WEIGHT;
# let base_tx = Transaction ;
# let base_weight = base_tx.weight.to_wu as u32;
// The change output that may or may not be included in the final transaction.
let drain_addr =
from_str
.expect
.require_network
.expect;
// The drain output(s) may or may not be included in the final tx. We calculate
// the drain weight to include the output length varint weight changes from
// including the drain output(s).
let drain_output_weight = ;
println!;
let drain_weights = DrainWeights ;
// This constructs a change policy that creates change when the change value is
// greater than or equal to the dust limit.
let change_policy = min_value;
Branch and Bound
You can use methods such as [CoinSelector::select] to manually select coins, or methods such as
[CoinSelector::select_until_target_met] for a rudimentary automatic selection. However, if you
wish to automatically select coins to optimize for a given metric, [CoinSelector::run_bnb] can be
used.
Built-in metrics are provided in the [metrics] submodule. Currently, only the
LowestFee metric is considered stable.
use ;
use LowestFee;
use min_value_and_waste;
# let candidates = ;
# let base_weight = 0;
# let drain_weights = default;
# let dust_limit = 0;
# let long_term_feerate = default_min_relay_fee;
let mut coin_selector = new;
let target = Target ;
// We use a change policy that introduces a change output if doing so reduces
// the "waste" and that the change output's value is at least that of the
// `dust_limit`.
let change_policy = min_value_and_waste;
// This metric minimizes transaction fees paid over time. The
// `long_term_feerate` is used to calculate the additional fee from spending
// the change output in the future.
let metric = LowestFee ;
// We run the branch and bound algorithm with a max round limit of 100,000.
match coin_selector.run_bnb ;
Finalizing a Selection
is_target_metchecks whether the current state ofCoinSelectormeets theTarget.apply_selectionapplies the selection to the original list of candidateTxOuts.
use ;
use min_value;
use ;
# let base_weight = 0_u32;
# let drain_weights = new_tr_keyspend;
// A random target, as an example.
let target = Target ;
// A random drain policy, as an example.
let drain_policy = min_value;
// This is a list of candidate txouts for coin selection. If a txout is picked,
// our transaction's input will spend it.
let candidate_txouts = vec!;
// We transform the candidate txouts into something `CoinSelector` can
// understand.
let candidates = candidate_txouts
.iter
.map
.;
let mut selector = new;
let _result = selector
.select_until_target_met;
// Determine what the drain output will be, based on our selection.
let drain = drain_policy;
// Check that selection is finished!
assert!;
// Get a list of coins that are selected.
let selected_coins = selector
.apply_selection
.;
assert_eq!;
Minimum Supported Rust Version (MSRV)
This library should compile with Rust 1.54.0.
To build with the MSRV, you will need to pin the following dependencies:
# tempfile 3.7.0 has MSRV 1.63.0+
cargo update -p tempfile --precise "3.6.0"