Skip to content

Commit 9c1e853

Browse files
committed
wip
1 parent cfa0928 commit 9c1e853

File tree

4 files changed

+388
-399
lines changed

4 files changed

+388
-399
lines changed

Cargo.toml

+9-9
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ readme = "README.md"
1414
rust-version = "1.63.0"
1515

1616
[dependencies]
17-
bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
17+
bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }
1818
rand = { version = "0.8.5", default-features = false, optional = true }
1919

2020
[dev-dependencies]
21-
bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f", features = ["arbitrary"] }
21+
bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75", features = ["arbitrary"] }
2222
criterion = "0.3"
2323
bitcoin-coin-selection = {path = ".", features = ["rand"]}
2424
rand = "0.8.5"
@@ -31,10 +31,10 @@ name = "coin_selection"
3131
harness = false
3232

3333
[patch.crates-io]
34-
bitcoin_hashes = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
35-
base58ck = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
36-
bitcoin-internals = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
37-
bitcoin-io = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
38-
bitcoin-primitives = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
39-
bitcoin-addresses = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
40-
bitcoin-units = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "52f9c13358c97c358543f3302b325f37ac49392f" }
34+
bitcoin_hashes = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }
35+
base58ck = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }
36+
bitcoin-internals = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }
37+
bitcoin-io = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }
38+
bitcoin-primitives = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }
39+
bitcoin-addresses = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }
40+
bitcoin-units = { git = "https://github.com/rust-bitcoin/rust-bitcoin.git", rev = "12cef1d16b3cf5577e907bcf63e8a5f55d976d75" }

src/branch_and_bound.rs

+135-134
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ pub fn select_coins_bnb<Utxo: WeightedUtxo>(
199199
let target = target.to_sat();
200200

201201
// descending sort by effective_value using satisfaction weight as tie breaker.
202-
w_utxos.sort_by(|a, b| b.0.cmp(&a.0).then(b.2.weight().cmp(&a.2.weight())));
202+
w_utxos.sort_by(|a, b| b.0.cmp(&a.0).then(b.2.predict_weight().total_weight().cmp(&a.2.predict_weight().total_weight())));
203203

204204
while iteration < ITERATION_LIMIT {
205205
backtrack = false;
@@ -335,7 +335,8 @@ mod tests {
335335
use bitcoin::{Amount, SignedAmount, Weight};
336336

337337
use super::*;
338-
use crate::tests::{assert_proptest_bnb, assert_ref_eq, parse_fee_rate, Utxo, UtxoPool};
338+
//use crate::tests::{assert_proptest_bnb, assert_ref_eq, parse_fee_rate, Utxo, UtxoPool};
339+
use crate::tests::{assert_ref_eq, parse_fee_rate, Utxo, UtxoPool};
339340
use crate::{effective_value, WeightedUtxo};
340341

341342
#[derive(Debug)]
@@ -792,7 +793,7 @@ mod tests {
792793
.map(|a| Amount::from_sat(a as u64).unwrap())
793794
.collect();
794795

795-
let pool: Vec<_> = amts.into_iter().map(|a| Utxo::new(a, Weight::ZERO)).collect();
796+
let pool: Vec<_> = amts.into_iter().map(|a| Utxo::new(a, Weight::from_wu(272))).collect();
796797

797798
let list = select_coins_bnb(target, Amount::ONE_SAT, FeeRate::ZERO, FeeRate::ZERO, &pool);
798799

@@ -811,7 +812,7 @@ mod tests {
811812
});
812813

813814
let amts: Vec<_> = vals.map(|v| Amount::from_sat(v).unwrap()).collect();
814-
let pool: Vec<_> = amts.into_iter().map(|a| Utxo::new(a, Weight::ZERO)).collect();
815+
let pool: Vec<_> = amts.into_iter().map(|a| Utxo::new(a, Weight::from_wu(272))).collect();
815816

816817
let list = select_coins_bnb(
817818
Amount::from_sat(target).unwrap(),
@@ -840,7 +841,7 @@ mod tests {
840841

841842
// Add a value that will match the target before iteration exhaustion occurs.
842843
amts.push(Amount::from_sat(target).unwrap());
843-
let pool: Vec<_> = amts.into_iter().map(|a| Utxo::new(a, Weight::ZERO)).collect();
844+
let pool: Vec<_> = amts.into_iter().map(|a| Utxo::new(a, Weight::from_wu(272))).collect();
844845

845846
let (iterations, utxos) = select_coins_bnb(
846847
Amount::from_sat(target).unwrap(),
@@ -863,7 +864,7 @@ mod tests {
863864

864865
arbtest(|u| {
865866
let amount = arb_amount_in_range(u, minimal_non_dust..=effective_value_max);
866-
let utxo = Utxo::new(amount, Weight::ZERO);
867+
let utxo = Utxo::new(amount, Weight::from_wu(272));
867868
let pool: Vec<Utxo> = vec![utxo.clone()];
868869

869870
let (_i, utxos) =
@@ -876,155 +877,155 @@ mod tests {
876877
});
877878
}
878879

879-
#[test]
880-
fn select_one_of_many_proptest() {
881-
arbtest(|u| {
882-
let pool = UtxoPool::arbitrary(u)?;
883-
let utxos = pool.utxos.clone();
880+
//#[test]
881+
//fn select_one_of_many_proptest() {
882+
//arbtest(|u| {
883+
//let pool = UtxoPool::arbitrary(u)?;
884+
//let utxos = pool.utxos.clone();
884885

885-
let utxo = u.choose(&utxos)?;
886+
//let utxo = u.choose(&utxos)?;
886887

887-
let max_fee_rate = calculate_max_fee_rate(utxo.value(), utxo.weight());
888-
if let Some(f) = max_fee_rate {
889-
let fee_rate = arb_fee_rate_in_range(u, 1..=f.to_sat_per_kwu());
888+
//let max_fee_rate = calculate_max_fee_rate(utxo.value(), utxo.weight());
889+
//if let Some(f) = max_fee_rate {
890+
//let fee_rate = arb_fee_rate_in_range(u, 1..=f.to_sat_per_kwu());
890891

891892
// TODO update eff value interface
892-
let target_effective_value =
893-
effective_value(fee_rate, utxo.weight(), utxo.value()).unwrap();
894-
895-
if let Ok(target) = target_effective_value.to_unsigned() {
896-
let result = select_coins_bnb(target, Amount::ZERO, fee_rate, fee_rate, &utxos);
897-
898-
if let Some((_i, utxos)) = result {
899-
let sum: SignedAmount = utxos
900-
.clone()
901-
.into_iter()
902-
.map(|u| effective_value(fee_rate, u.weight(), u.value()).unwrap())
903-
.checked_sum()
904-
.unwrap();
905-
let amount_sum = sum.to_unsigned().unwrap();
906-
assert_eq!(amount_sum, target);
893+
//let target_effective_value =
894+
//effective_value(fee_rate, utxo.weight(), utxo.value()).unwrap();
895+
896+
//if let Ok(target) = target_effective_value.to_unsigned() {
897+
//let result = select_coins_bnb(target, Amount::ZERO, fee_rate, fee_rate, &utxos);
898+
899+
//if let Some((_i, utxos)) = result {
900+
//let sum: SignedAmount = utxos
901+
//.clone()
902+
//.into_iter()
903+
//.map(|u| effective_value(fee_rate, u.weight(), u.value()).unwrap())
904+
//.checked_sum()
905+
//.unwrap();
906+
//let amount_sum = sum.to_unsigned().unwrap();
907+
//assert_eq!(amount_sum, target);
907908

908909
// TODO add checked_sum to Weight
909-
let weight_sum = utxos
910-
.iter()
911-
.try_fold(Weight::ZERO, |acc, itm| acc.checked_add(itm.weight()));
910+
//let weight_sum = utxos
911+
//.iter()
912+
//.try_fold(Weight::ZERO, |acc, itm| acc.checked_add(itm.weight()));
912913

913-
assert!(weight_sum.unwrap() <= utxo.weight());
914-
} else {
914+
//assert!(weight_sum.unwrap() <= utxo.weight());
915+
//} else {
915916
// if result was none, then assert that fail happened because overflow when
916917
// summing pool. In the future, assert specific error when added.
917-
let available_value = utxos.into_iter().map(|u| u.value()).checked_sum();
918-
assert!(available_value.is_none());
919-
}
920-
}
921-
}
922-
923-
Ok(())
924-
});
925-
}
926-
927-
#[test]
928-
fn select_many_of_many_proptest() {
929-
arbtest(|u| {
930-
let pool = UtxoPool::arbitrary(u)?;
931-
let utxos = pool.utxos.clone();
918+
//let available_value = utxos.into_iter().map(|u| u.value()).checked_sum();
919+
//assert!(available_value.is_none());
920+
//}
921+
//}
922+
//}
923+
924+
//Ok(())
925+
//});
926+
//}
927+
928+
//#[test]
929+
//fn select_many_of_many_proptest() {
930+
//arbtest(|u| {
931+
//let pool = UtxoPool::arbitrary(u)?;
932+
//let utxos = pool.utxos.clone();
932933

933934
// generate all the possible utxos subsets
934-
let mut gen = exhaustigen::Gen::new();
935-
let mut subsets: Vec<Vec<&Utxo>> = Vec::new();
936-
while !gen.done() {
937-
let s = gen.gen_subset(&pool.utxos).collect::<Vec<_>>();
938-
subsets.push(s);
939-
}
935+
//let mut gen = exhaustigen::Gen::new();
936+
//let mut subsets: Vec<Vec<&Utxo>> = Vec::new();
937+
//while !gen.done() {
938+
//let s = gen.gen_subset(&pool.utxos).collect::<Vec<_>>();
939+
//subsets.push(s);
940+
//}
940941

941942
// choose a set at random to be the target
942-
let target_selection: &Vec<&Utxo> = u.choose(&subsets).unwrap();
943+
//let target_selection: &Vec<&Utxo> = u.choose(&subsets).unwrap();
943944

944945
// find the minmum fee_rate that will result in all utxos having a posiive
945946
// effective_value
946-
let mut fee_rates: Vec<FeeRate> = target_selection
947-
.iter()
948-
.map(|u| calculate_max_fee_rate(u.value(), u.weight()).unwrap_or(FeeRate::ZERO))
949-
.collect();
950-
fee_rates.sort();
947+
//let mut fee_rates: Vec<FeeRate> = target_selection
948+
//.iter()
949+
//.map(|u| calculate_max_fee_rate(u.value(), u.weight()).unwrap_or(FeeRate::ZERO))
950+
//.collect();
951+
//fee_rates.sort();
951952

952-
let min_fee_rate = fee_rates.first().unwrap_or(&FeeRate::ZERO).to_sat_per_kwu();
953-
let fee_rate = arb_fee_rate_in_range(u, 0..=min_fee_rate);
953+
//let min_fee_rate = fee_rates.first().unwrap_or(&FeeRate::ZERO).to_sat_per_kwu();
954+
//let fee_rate = arb_fee_rate_in_range(u, 0..=min_fee_rate);
954955

955-
let effective_values: Vec<SignedAmount> = target_selection
956-
.iter()
957-
.map(|u| {
958-
let e = effective_value(fee_rate, u.weight(), u.value());
959-
e.unwrap_or(SignedAmount::ZERO)
960-
})
961-
.collect();
956+
//let effective_values: Vec<SignedAmount> = target_selection
957+
//.iter()
958+
//.map(|u| {
959+
//let e = effective_value(fee_rate, u.weight(), u.value());
960+
//e.unwrap_or(SignedAmount::ZERO)
961+
//})
962+
//.collect();
962963

963-
let eff_values_sum = effective_values.into_iter().checked_sum();
964+
//let eff_values_sum = effective_values.into_iter().checked_sum();
964965

965966
// if None, then this random subset is an invalid target (skip)
966-
if let Some(s) = eff_values_sum {
967-
if let Ok(target) = s.to_unsigned() {
968-
let result = select_coins_bnb(target, Amount::ZERO, fee_rate, fee_rate, &utxos);
969-
970-
if let Some((_i, utxos)) = result {
971-
let effective_value_sum: Amount = utxos
972-
.clone()
973-
.into_iter()
974-
.map(|u| {
975-
effective_value(fee_rate, u.weight(), u.value())
976-
.unwrap()
977-
.to_unsigned()
978-
.unwrap()
979-
})
980-
.checked_sum()
981-
.unwrap();
982-
assert_eq!(effective_value_sum, target);
967+
//if let Some(s) = eff_values_sum {
968+
//if let Ok(target) = s.to_unsigned() {
969+
//let result = select_coins_bnb(target, Amount::ZERO, fee_rate, fee_rate, &utxos);
970+
971+
//if let Some((_i, utxos)) = result {
972+
//let effective_value_sum: Amount = utxos
973+
//.clone()
974+
//.into_iter()
975+
//.map(|u| {
976+
//effective_value(fee_rate, u.weight(), u.value())
977+
//.unwrap()
978+
//.to_unsigned()
979+
//.unwrap()
980+
//})
981+
//.checked_sum()
982+
//.unwrap();
983+
//assert_eq!(effective_value_sum, target);
983984

984985
// TODO checked_add not available in Weight
985-
let result_sum = utxos
986-
.iter()
987-
.try_fold(Weight::ZERO, |acc, item| acc.checked_add(item.weight()));
988-
989-
let target_sum = target_selection
990-
.iter()
991-
.try_fold(Weight::ZERO, |acc, item| acc.checked_add(item.weight()));
992-
993-
if let Some(s) = target_sum {
994-
assert!(result_sum.unwrap() <= s);
995-
}
996-
} else {
997-
let available_value = utxos.into_iter().map(|u| u.value()).checked_sum();
998-
assert!(
999-
available_value.is_none()
1000-
|| target_selection.is_empty()
1001-
|| target == Amount::ZERO
1002-
);
1003-
}
1004-
}
1005-
}
1006-
1007-
Ok(())
1008-
});
1009-
}
1010-
1011-
#[test]
1012-
fn select_bnb_proptest() {
1013-
arbtest(|u| {
1014-
let pool = UtxoPool::arbitrary(u)?;
1015-
let target = Amount::arbitrary(u)?;
1016-
let cost_of_change = Amount::arbitrary(u)?;
1017-
let fee_rate = FeeRate::arbitrary(u)?;
1018-
let lt_fee_rate = FeeRate::arbitrary(u)?;
1019-
1020-
let utxos = pool.utxos.clone();
1021-
1022-
let result = select_coins_bnb(target, cost_of_change, fee_rate, lt_fee_rate, &utxos);
1023-
1024-
assert_proptest_bnb(target, cost_of_change, fee_rate, lt_fee_rate, pool, result);
1025-
1026-
Ok(())
1027-
})
1028-
.seed(0xcde68a8900000060);
1029-
}
986+
//let result_sum = utxos
987+
//.iter()
988+
//.try_fold(Weight::ZERO, |acc, item| acc.checked_add(item.weight()));
989+
990+
//let target_sum = target_selection
991+
//.iter()
992+
//.try_fold(Weight::ZERO, |acc, item| acc.checked_add(item.weight()));
993+
994+
//if let Some(s) = target_sum {
995+
//assert!(result_sum.unwrap() <= s);
996+
//}
997+
//} else {
998+
//let available_value = utxos.into_iter().map(|u| u.value()).checked_sum();
999+
//assert!(
1000+
//available_value.is_none()
1001+
//|| target_selection.is_empty()
1002+
//|| target == Amount::ZERO
1003+
//);
1004+
//}
1005+
//}
1006+
//}
1007+
1008+
//Ok(())
1009+
//});
1010+
//}
1011+
1012+
//#[test]
1013+
//fn select_bnb_proptest() {
1014+
//arbtest(|u| {
1015+
//let pool = UtxoPool::arbitrary(u)?;
1016+
//let target = Amount::arbitrary(u)?;
1017+
//let cost_of_change = Amount::arbitrary(u)?;
1018+
//let fee_rate = FeeRate::arbitrary(u)?;
1019+
//let lt_fee_rate = FeeRate::arbitrary(u)?;
1020+
1021+
//let utxos = pool.utxos.clone();
1022+
1023+
//let result = select_coins_bnb(target, cost_of_change, fee_rate, lt_fee_rate, &utxos);
1024+
1025+
//assert_proptest_bnb(target, cost_of_change, fee_rate, lt_fee_rate, pool, result);
1026+
1027+
//Ok(())
1028+
//})
1029+
//.seed(0xcde68a8900000060);
1030+
//}
10301031
}

0 commit comments

Comments
 (0)