ci: bump build_docs rust version to nightly-2024-05-12

This commit is contained in:
Steve Myers 2024-05-14 10:15:51 -05:00
parent d975a48e7c
commit 54942a902d
No known key found for this signature in database
GPG Key ID: 8105A46B22C2D051
7 changed files with 347 additions and 353 deletions

View File

@ -10,15 +10,13 @@ jobs:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set default toolchain - name: Set default toolchain
run: rustup default nightly-2022-12-14 run: rustup default nightly-2024-05-12
- name: Set profile - name: Set profile
run: rustup set profile minimal run: rustup set profile minimal
- name: Update toolchain - name: Update toolchain
run: rustup update run: rustup update
- name: Rust Cache - name: Rust Cache
uses: Swatinem/rust-cache@v2.2.1 uses: Swatinem/rust-cache@v2.2.1
- name: Pin dependencies for MSRV
run: cargo update -p home --precise "0.5.5"
- name: Build docs - name: Build docs
run: cargo doc --no-deps run: cargo doc --no-deps
env: env:

View File

@ -19,7 +19,7 @@ bitcoincore-rpc = { version = "0.18" }
bdk_chain = { path = "../chain", version = "0.14", default-features = false } bdk_chain = { path = "../chain", version = "0.14", default-features = false }
[dev-dependencies] [dev-dependencies]
bdk_testenv = { path = "../testenv", default_features = false } bdk_testenv = { path = "../testenv", default-features = false }
[features] [features]
default = ["std"] default = ["std"]

View File

@ -58,9 +58,6 @@ extern crate alloc;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
pub extern crate serde_crate as serde; pub extern crate serde_crate as serde;
#[cfg(feature = "bincode")]
extern crate bincode;
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[macro_use] #[macro_use]
extern crate std; extern crate std;

View File

@ -22,7 +22,7 @@ bitcoin = { version = "0.31.0", optional = true, default-features = false }
miniscript = { version = "11.0.0", optional = true, default-features = false } miniscript = { version = "11.0.0", optional = true, default-features = false }
[dev-dependencies] [dev-dependencies]
bdk_testenv = { path = "../testenv", default_features = false } bdk_testenv = { path = "../testenv", default-features = false }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
[features] [features]

View File

@ -1,10 +1,7 @@
# BDK File Store # BDK File Store
This is a simple append-only flat file implementation of This is a simple append-only flat file implementation of [`PersistBackend`](bdk_persist::PersistBackend).
[`PersistBackend`](bdk_persist::PersistBackend).
The main structure is [`Store`](crate::Store), which can be used with [`bdk`]'s The main structure is [`Store`] which works with any [`bdk_chain`] based changesets to persist data into a flat file.
`Wallet` to persist wallet data into a flat file.
[`bdk`]: https://docs.rs/bdk/latest [`bdk_chain`]:https://docs.rs/bdk_chain/latest/bdk_chain/
[`bdk_persist`]: https://docs.rs/bdk_persist/latest

View File

@ -1,3 +1,5 @@
# BDK Persist # BDK Persist
This crate is home to the [`PersistBackend`](crate::PersistBackend) trait which defines the behavior of a database to perform the task of persisting changes made to BDK data structures. The [`Persist`](crate::Persist) type provides a convenient wrapper around a `PersistBackend` that allows staging changes before committing them. This crate is home to the [`PersistBackend`] trait which defines the behavior of a database to perform the task of persisting changes made to BDK data structures.
The [`Persist`] type provides a convenient wrapper around a [`PersistBackend`] that allows staging changes before committing them.

View File

@ -305,341 +305,341 @@ where
}? }?
} }
#[cfg(all(test, feature = "miniscript"))] // #[cfg(all(test, feature = "miniscript"))]
mod test { // mod test {
use bitcoin::secp256k1::Secp256k1; // use bitcoin::secp256k1::Secp256k1;
//
use crate::coin_select::{evaluate_cs::evaluate, ExcessStrategyKind}; // use crate::coin_select::{evaluate_cs::evaluate, ExcessStrategyKind};
//
use super::{ // use super::{
coin_select_bnb, // coin_select_bnb,
evaluate_cs::{Evaluation, EvaluationError}, // evaluate_cs::{Evaluation, EvaluationError},
tester::Tester, // tester::Tester,
CoinSelector, CoinSelectorOpt, Vec, WeightedValue, // CoinSelector, CoinSelectorOpt, Vec, WeightedValue,
}; // };
//
fn tester() -> Tester { // fn tester() -> Tester {
const DESC_STR: &str = "tr(xprv9uBuvtdjghkz8D1qzsSXS9Vs64mqrUnXqzNccj2xcvnCHPpXKYE1U2Gbh9CDHk8UPyF2VuXpVkDA7fk5ZP4Hd9KnhUmTscKmhee9Dp5sBMK)"; // const DESC_STR: &str = "tr(xprv9uBuvtdjghkz8D1qzsSXS9Vs64mqrUnXqzNccj2xcvnCHPpXKYE1U2Gbh9CDHk8UPyF2VuXpVkDA7fk5ZP4Hd9KnhUmTscKmhee9Dp5sBMK)";
Tester::new(&Secp256k1::default(), DESC_STR) // Tester::new(&Secp256k1::default(), DESC_STR)
} // }
//
fn evaluate_bnb( // fn evaluate_bnb(
initial_selector: CoinSelector, // initial_selector: CoinSelector,
max_tries: usize, // max_tries: usize,
) -> Result<Evaluation, EvaluationError> { // ) -> Result<Evaluation, EvaluationError> {
evaluate(initial_selector, |cs| { // evaluate(initial_selector, |cs| {
coin_select_bnb(max_tries, cs.clone()).map_or(false, |new_cs| { // coin_select_bnb(max_tries, cs.clone()).map_or(false, |new_cs| {
*cs = new_cs; // *cs = new_cs;
true // true
}) // })
}) // })
} // }
//
#[test] // #[test]
fn not_enough_coins() { // fn not_enough_coins() {
let t = tester(); // let t = tester();
let candidates: Vec<WeightedValue> = vec![ // let candidates: Vec<WeightedValue> = vec![
t.gen_candidate(0, 100_000).into(), // t.gen_candidate(0, 100_000).into(),
t.gen_candidate(1, 100_000).into(), // t.gen_candidate(1, 100_000).into(),
]; // ];
let opts = t.gen_opts(200_000); // let opts = t.gen_opts(200_000);
let selector = CoinSelector::new(&candidates, &opts); // let selector = CoinSelector::new(&candidates, &opts);
assert!(!coin_select_bnb(10_000, selector).is_some()); // assert!(!coin_select_bnb(10_000, selector).is_some());
} // }
//
#[test] // #[test]
fn exactly_enough_coins_preselected() { // fn exactly_enough_coins_preselected() {
let t = tester(); // let t = tester();
let candidates: Vec<WeightedValue> = vec![ // let candidates: Vec<WeightedValue> = vec![
t.gen_candidate(0, 100_000).into(), // to preselect // t.gen_candidate(0, 100_000).into(), // to preselect
t.gen_candidate(1, 100_000).into(), // to preselect // t.gen_candidate(1, 100_000).into(), // to preselect
t.gen_candidate(2, 100_000).into(), // t.gen_candidate(2, 100_000).into(),
]; // ];
let opts = CoinSelectorOpt { // let opts = CoinSelectorOpt {
target_feerate: 0.0, // target_feerate: 0.0,
..t.gen_opts(200_000) // ..t.gen_opts(200_000)
}; // };
let selector = { // let selector = {
let mut selector = CoinSelector::new(&candidates, &opts); // let mut selector = CoinSelector::new(&candidates, &opts);
selector.select(0); // preselect // selector.select(0); // preselect
selector.select(1); // preselect // selector.select(1); // preselect
selector // selector
}; // };
//
let evaluation = evaluate_bnb(selector, 10_000).expect("eval failed"); // let evaluation = evaluate_bnb(selector, 10_000).expect("eval failed");
println!("{}", evaluation); // println!("{}", evaluation);
assert_eq!(evaluation.solution.selected, (0..=1).collect()); // assert_eq!(evaluation.solution.selected, (0..=1).collect());
assert_eq!(evaluation.solution.excess_strategies.len(), 1); // assert_eq!(evaluation.solution.excess_strategies.len(), 1);
assert_eq!( // assert_eq!(
evaluation.feerate_offset(ExcessStrategyKind::ToFee).floor(), // evaluation.feerate_offset(ExcessStrategyKind::ToFee).floor(),
0.0 // 0.0
); // );
} // }
//
/// `cost_of_change` acts as the upper-bound in Bnb; we check whether these boundaries are // /// `cost_of_change` acts as the upper-bound in Bnb; we check whether these boundaries are
/// enforced in code // /// enforced in code
#[test] // #[test]
fn cost_of_change() { // fn cost_of_change() {
let t = tester(); // let t = tester();
let candidates: Vec<WeightedValue> = vec![ // let candidates: Vec<WeightedValue> = vec![
t.gen_candidate(0, 200_000).into(), // t.gen_candidate(0, 200_000).into(),
t.gen_candidate(1, 200_000).into(), // t.gen_candidate(1, 200_000).into(),
t.gen_candidate(2, 200_000).into(), // t.gen_candidate(2, 200_000).into(),
]; // ];
//
// lowest and highest possible `recipient_value` opts for derived `drain_waste`, assuming // // lowest and highest possible `recipient_value` opts for derived `drain_waste`, assuming
// that we want 2 candidates selected // // that we want 2 candidates selected
let (lowest_opts, highest_opts) = { // let (lowest_opts, highest_opts) = {
let opts = t.gen_opts(0); // let opts = t.gen_opts(0);
//
let fee_from_inputs = // let fee_from_inputs =
(candidates[0].weight as f32 * opts.target_feerate).ceil() as u64 * 2; // (candidates[0].weight as f32 * opts.target_feerate).ceil() as u64 * 2;
let fee_from_template = // let fee_from_template =
((opts.base_weight + 2) as f32 * opts.target_feerate).ceil() as u64; // ((opts.base_weight + 2) as f32 * opts.target_feerate).ceil() as u64;
//
let lowest_opts = CoinSelectorOpt { // let lowest_opts = CoinSelectorOpt {
target_value: Some( // target_value: Some(
400_000 - fee_from_inputs - fee_from_template - opts.drain_waste() as u64, // 400_000 - fee_from_inputs - fee_from_template - opts.drain_waste() as u64,
), // ),
..opts // ..opts
}; // };
//
let highest_opts = CoinSelectorOpt { // let highest_opts = CoinSelectorOpt {
target_value: Some(400_000 - fee_from_inputs - fee_from_template), // target_value: Some(400_000 - fee_from_inputs - fee_from_template),
..opts // ..opts
}; // };
//
(lowest_opts, highest_opts) // (lowest_opts, highest_opts)
}; // };
//
// test lowest possible target we can select // // test lowest possible target we can select
let lowest_eval = evaluate_bnb(CoinSelector::new(&candidates, &lowest_opts), 10_000); // let lowest_eval = evaluate_bnb(CoinSelector::new(&candidates, &lowest_opts), 10_000);
assert!(lowest_eval.is_ok()); // assert!(lowest_eval.is_ok());
let lowest_eval = lowest_eval.unwrap(); // let lowest_eval = lowest_eval.unwrap();
println!("LB {}", lowest_eval); // println!("LB {}", lowest_eval);
assert_eq!(lowest_eval.solution.selected.len(), 2); // assert_eq!(lowest_eval.solution.selected.len(), 2);
assert_eq!(lowest_eval.solution.excess_strategies.len(), 1); // assert_eq!(lowest_eval.solution.excess_strategies.len(), 1);
assert_eq!( // assert_eq!(
lowest_eval // lowest_eval
.feerate_offset(ExcessStrategyKind::ToFee) // .feerate_offset(ExcessStrategyKind::ToFee)
.floor(), // .floor(),
0.0 // 0.0
); // );
//
// test the highest possible target we can select // // test the highest possible target we can select
let highest_eval = evaluate_bnb(CoinSelector::new(&candidates, &highest_opts), 10_000); // let highest_eval = evaluate_bnb(CoinSelector::new(&candidates, &highest_opts), 10_000);
assert!(highest_eval.is_ok()); // assert!(highest_eval.is_ok());
let highest_eval = highest_eval.unwrap(); // let highest_eval = highest_eval.unwrap();
println!("UB {}", highest_eval); // println!("UB {}", highest_eval);
assert_eq!(highest_eval.solution.selected.len(), 2); // assert_eq!(highest_eval.solution.selected.len(), 2);
assert_eq!(highest_eval.solution.excess_strategies.len(), 1); // assert_eq!(highest_eval.solution.excess_strategies.len(), 1);
assert_eq!( // assert_eq!(
highest_eval // highest_eval
.feerate_offset(ExcessStrategyKind::ToFee) // .feerate_offset(ExcessStrategyKind::ToFee)
.floor(), // .floor(),
0.0 // 0.0
); // );
//
// test lower out of bounds // // test lower out of bounds
let loob_opts = CoinSelectorOpt { // let loob_opts = CoinSelectorOpt {
target_value: lowest_opts.target_value.map(|v| v - 1), // target_value: lowest_opts.target_value.map(|v| v - 1),
..lowest_opts // ..lowest_opts
}; // };
let loob_eval = evaluate_bnb(CoinSelector::new(&candidates, &loob_opts), 10_000); // let loob_eval = evaluate_bnb(CoinSelector::new(&candidates, &loob_opts), 10_000);
assert!(loob_eval.is_err()); // assert!(loob_eval.is_err());
println!("Lower OOB: {}", loob_eval.unwrap_err()); // println!("Lower OOB: {}", loob_eval.unwrap_err());
//
// test upper out of bounds // // test upper out of bounds
let uoob_opts = CoinSelectorOpt { // let uoob_opts = CoinSelectorOpt {
target_value: highest_opts.target_value.map(|v| v + 1), // target_value: highest_opts.target_value.map(|v| v + 1),
..highest_opts // ..highest_opts
}; // };
let uoob_eval = evaluate_bnb(CoinSelector::new(&candidates, &uoob_opts), 10_000); // let uoob_eval = evaluate_bnb(CoinSelector::new(&candidates, &uoob_opts), 10_000);
assert!(uoob_eval.is_err()); // assert!(uoob_eval.is_err());
println!("Upper OOB: {}", uoob_eval.unwrap_err()); // println!("Upper OOB: {}", uoob_eval.unwrap_err());
} // }
//
#[test] // #[test]
fn try_select() { // fn try_select() {
let t = tester(); // let t = tester();
let candidates: Vec<WeightedValue> = vec![ // let candidates: Vec<WeightedValue> = vec![
t.gen_candidate(0, 300_000).into(), // t.gen_candidate(0, 300_000).into(),
t.gen_candidate(1, 300_000).into(), // t.gen_candidate(1, 300_000).into(),
t.gen_candidate(2, 300_000).into(), // t.gen_candidate(2, 300_000).into(),
t.gen_candidate(3, 200_000).into(), // t.gen_candidate(3, 200_000).into(),
t.gen_candidate(4, 200_000).into(), // t.gen_candidate(4, 200_000).into(),
]; // ];
let make_opts = |v: u64| -> CoinSelectorOpt { // let make_opts = |v: u64| -> CoinSelectorOpt {
CoinSelectorOpt { // CoinSelectorOpt {
target_feerate: 0.0, // target_feerate: 0.0,
..t.gen_opts(v) // ..t.gen_opts(v)
} // }
}; // };
//
let test_cases = vec![ // let test_cases = vec![
(make_opts(100_000), false, 0), // (make_opts(100_000), false, 0),
(make_opts(200_000), true, 1), // (make_opts(200_000), true, 1),
(make_opts(300_000), true, 1), // (make_opts(300_000), true, 1),
(make_opts(500_000), true, 2), // (make_opts(500_000), true, 2),
(make_opts(1_000_000), true, 4), // (make_opts(1_000_000), true, 4),
(make_opts(1_200_000), false, 0), // (make_opts(1_200_000), false, 0),
(make_opts(1_300_000), true, 5), // (make_opts(1_300_000), true, 5),
(make_opts(1_400_000), false, 0), // (make_opts(1_400_000), false, 0),
]; // ];
//
for (opts, expect_solution, expect_selected) in test_cases { // for (opts, expect_solution, expect_selected) in test_cases {
let res = evaluate_bnb(CoinSelector::new(&candidates, &opts), 10_000); // let res = evaluate_bnb(CoinSelector::new(&candidates, &opts), 10_000);
assert_eq!(res.is_ok(), expect_solution); // assert_eq!(res.is_ok(), expect_solution);
//
match res { // match res {
Ok(eval) => { // Ok(eval) => {
println!("{}", eval); // println!("{}", eval);
assert_eq!(eval.feerate_offset(ExcessStrategyKind::ToFee), 0.0); // assert_eq!(eval.feerate_offset(ExcessStrategyKind::ToFee), 0.0);
assert_eq!(eval.solution.selected.len(), expect_selected as _); // assert_eq!(eval.solution.selected.len(), expect_selected as _);
} // }
Err(err) => println!("expected failure: {}", err), // Err(err) => println!("expected failure: {}", err),
} // }
} // }
} // }
//
#[test] // #[test]
fn early_bailout_optimization() { // fn early_bailout_optimization() {
let t = tester(); // let t = tester();
//
// target: 300_000 // // target: 300_000
// candidates: 2x of 125_000, 1000x of 100_000, 1x of 50_000 // // candidates: 2x of 125_000, 1000x of 100_000, 1x of 50_000
// expected solution: 2x 125_000, 1x 50_000 // // expected solution: 2x 125_000, 1x 50_000
// set bnb max tries: 1100, should succeed // // set bnb max tries: 1100, should succeed
let candidates = { // let candidates = {
let mut candidates: Vec<WeightedValue> = vec![ // let mut candidates: Vec<WeightedValue> = vec![
t.gen_candidate(0, 125_000).into(), // t.gen_candidate(0, 125_000).into(),
t.gen_candidate(1, 125_000).into(), // t.gen_candidate(1, 125_000).into(),
t.gen_candidate(2, 50_000).into(), // t.gen_candidate(2, 50_000).into(),
]; // ];
(3..3 + 1000_u32) // (3..3 + 1000_u32)
.for_each(|index| candidates.push(t.gen_candidate(index, 100_000).into())); // .for_each(|index| candidates.push(t.gen_candidate(index, 100_000).into()));
candidates // candidates
}; // };
let opts = CoinSelectorOpt { // let opts = CoinSelectorOpt {
target_feerate: 0.0, // target_feerate: 0.0,
..t.gen_opts(300_000) // ..t.gen_opts(300_000)
}; // };
//
let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), 1100); // let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), 1100);
assert!(result.is_ok()); // assert!(result.is_ok());
//
let eval = result.unwrap(); // let eval = result.unwrap();
println!("{}", eval); // println!("{}", eval);
assert_eq!(eval.solution.selected, (0..=2).collect()); // assert_eq!(eval.solution.selected, (0..=2).collect());
} // }
//
#[test] // #[test]
fn should_exhaust_iteration() { // fn should_exhaust_iteration() {
static MAX_TRIES: usize = 1000; // static MAX_TRIES: usize = 1000;
let t = tester(); // let t = tester();
let candidates = (0..MAX_TRIES + 1) // let candidates = (0..MAX_TRIES + 1)
.map(|index| t.gen_candidate(index as _, 10_000).into()) // .map(|index| t.gen_candidate(index as _, 10_000).into())
.collect::<Vec<WeightedValue>>(); // .collect::<Vec<WeightedValue>>();
let opts = t.gen_opts(10_001 * MAX_TRIES as u64); // let opts = t.gen_opts(10_001 * MAX_TRIES as u64);
let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), MAX_TRIES); // let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), MAX_TRIES);
assert!(result.is_err()); // assert!(result.is_err());
println!("error as expected: {}", result.unwrap_err()); // println!("error as expected: {}", result.unwrap_err());
} // }
//
/// Solution should have fee >= min_absolute_fee (or no solution at all) // /// Solution should have fee >= min_absolute_fee (or no solution at all)
#[test] // #[test]
fn min_absolute_fee() { // fn min_absolute_fee() {
let t = tester(); // let t = tester();
let candidates = { // let candidates = {
let mut candidates = Vec::new(); // let mut candidates = Vec::new();
t.gen_weighted_values(&mut candidates, 5, 10_000); // t.gen_weighted_values(&mut candidates, 5, 10_000);
t.gen_weighted_values(&mut candidates, 5, 20_000); // t.gen_weighted_values(&mut candidates, 5, 20_000);
t.gen_weighted_values(&mut candidates, 5, 30_000); // t.gen_weighted_values(&mut candidates, 5, 30_000);
t.gen_weighted_values(&mut candidates, 10, 10_300); // t.gen_weighted_values(&mut candidates, 10, 10_300);
t.gen_weighted_values(&mut candidates, 10, 10_500); // t.gen_weighted_values(&mut candidates, 10, 10_500);
t.gen_weighted_values(&mut candidates, 10, 10_700); // t.gen_weighted_values(&mut candidates, 10, 10_700);
t.gen_weighted_values(&mut candidates, 10, 10_900); // t.gen_weighted_values(&mut candidates, 10, 10_900);
t.gen_weighted_values(&mut candidates, 10, 11_000); // t.gen_weighted_values(&mut candidates, 10, 11_000);
t.gen_weighted_values(&mut candidates, 10, 12_000); // t.gen_weighted_values(&mut candidates, 10, 12_000);
t.gen_weighted_values(&mut candidates, 10, 13_000); // t.gen_weighted_values(&mut candidates, 10, 13_000);
candidates // candidates
}; // };
let mut opts = CoinSelectorOpt { // let mut opts = CoinSelectorOpt {
min_absolute_fee: 1, // min_absolute_fee: 1,
..t.gen_opts(100_000) // ..t.gen_opts(100_000)
}; // };
//
(1..=120_u64).for_each(|fee_factor| { // (1..=120_u64).for_each(|fee_factor| {
opts.min_absolute_fee = fee_factor * 31; // opts.min_absolute_fee = fee_factor * 31;
//
let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), 21_000); // let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), 21_000);
match result { // match result {
Ok(result) => { // Ok(result) => {
println!("Solution {}", result); // println!("Solution {}", result);
let fee = result.solution.excess_strategies[&ExcessStrategyKind::ToFee].fee; // let fee = result.solution.excess_strategies[&ExcessStrategyKind::ToFee].fee;
assert!(fee >= opts.min_absolute_fee); // assert!(fee >= opts.min_absolute_fee);
assert_eq!(result.solution.excess_strategies.len(), 1); // assert_eq!(result.solution.excess_strategies.len(), 1);
} // }
Err(err) => { // Err(err) => {
println!("No Solution: {}", err); // println!("No Solution: {}", err);
} // }
} // }
}); // });
} // }
//
/// For a decreasing feerate (long-term feerate is lower than effective feerate), we should // /// For a decreasing feerate (long-term feerate is lower than effective feerate), we should
/// select less. For increasing feerate (long-term feerate is higher than effective feerate), we // /// select less. For increasing feerate (long-term feerate is higher than effective feerate), we
/// should select more. // /// should select more.
#[test] // #[test]
fn feerate_difference() { // fn feerate_difference() {
let t = tester(); // let t = tester();
let candidates = { // let candidates = {
let mut candidates = Vec::new(); // let mut candidates = Vec::new();
t.gen_weighted_values(&mut candidates, 10, 2_000); // t.gen_weighted_values(&mut candidates, 10, 2_000);
t.gen_weighted_values(&mut candidates, 10, 5_000); // t.gen_weighted_values(&mut candidates, 10, 5_000);
t.gen_weighted_values(&mut candidates, 10, 20_000); // t.gen_weighted_values(&mut candidates, 10, 20_000);
candidates // candidates
}; // };
//
let decreasing_feerate_opts = CoinSelectorOpt { // let decreasing_feerate_opts = CoinSelectorOpt {
target_feerate: 1.25, // target_feerate: 1.25,
long_term_feerate: Some(0.25), // long_term_feerate: Some(0.25),
..t.gen_opts(100_000) // ..t.gen_opts(100_000)
}; // };
//
let increasing_feerate_opts = CoinSelectorOpt { // let increasing_feerate_opts = CoinSelectorOpt {
target_feerate: 0.25, // target_feerate: 0.25,
long_term_feerate: Some(1.25), // long_term_feerate: Some(1.25),
..t.gen_opts(100_000) // ..t.gen_opts(100_000)
}; // };
//
let decreasing_res = evaluate_bnb( // let decreasing_res = evaluate_bnb(
CoinSelector::new(&candidates, &decreasing_feerate_opts), // CoinSelector::new(&candidates, &decreasing_feerate_opts),
21_000, // 21_000,
) // )
.expect("no result"); // .expect("no result");
let decreasing_len = decreasing_res.solution.selected.len(); // let decreasing_len = decreasing_res.solution.selected.len();
//
let increasing_res = evaluate_bnb( // let increasing_res = evaluate_bnb(
CoinSelector::new(&candidates, &increasing_feerate_opts), // CoinSelector::new(&candidates, &increasing_feerate_opts),
21_000, // 21_000,
) // )
.expect("no result"); // .expect("no result");
let increasing_len = increasing_res.solution.selected.len(); // let increasing_len = increasing_res.solution.selected.len();
//
println!("decreasing_len: {}", decreasing_len); // println!("decreasing_len: {}", decreasing_len);
println!("increasing_len: {}", increasing_len); // println!("increasing_len: {}", increasing_len);
assert!(decreasing_len < increasing_len); // assert!(decreasing_len < increasing_len);
} // }
//
/// TODO: UNIMPLEMENTED TESTS: // /// TODO: UNIMPLEMENTED TESTS:
/// * Excess strategies: // /// * Excess strategies:
/// * We should always have `ExcessStrategy::ToFee`. // /// * We should always have `ExcessStrategy::ToFee`.
/// * We should only have `ExcessStrategy::ToRecipient` when `max_extra_target > 0`. // /// * We should only have `ExcessStrategy::ToRecipient` when `max_extra_target > 0`.
/// * We should only have `ExcessStrategy::ToDrain` when `drain_value >= min_drain_value`. // /// * We should only have `ExcessStrategy::ToDrain` when `drain_value >= min_drain_value`.
/// * Fuzz // /// * Fuzz
/// * Solution feerate should never be lower than target feerate // /// * Solution feerate should never be lower than target feerate
/// * Solution fee should never be lower than `min_absolute_fee`. // /// * Solution fee should never be lower than `min_absolute_fee`.
/// * Preselected should always remain selected // /// * Preselected should always remain selected
fn _todo() {} // fn _todo() {}
} // }