Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
yancyribbens committed Oct 15, 2024
1 parent 1da2132 commit 4cce555
Showing 1 changed file with 84 additions and 73 deletions.
157 changes: 84 additions & 73 deletions src/branch_and_bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ pub fn select_coins_bnb<Utxo: WeightedUtxo>(
weighted_utxos: &[Utxo],
) -> Option<std::vec::IntoIter<&Utxo>> {

println!("start bnb");

// Total_Tries in Core:
// https://github.com/bitcoin/bitcoin/blob/1d9da8da309d1dbf9aef15eb8dc43b4a2dc3d309/src/wallet/coinselection.cpp#L74
const ITERATION_LIMIT: i32 = 100_000;
Expand Down Expand Up @@ -196,12 +198,15 @@ pub fn select_coins_bnb<Utxo: WeightedUtxo>(
w_utxos.sort_by_key(|u| u.0);
w_utxos.reverse();

println!("sum avail values");
let mut available_value = w_utxos.clone().into_iter().map(|(ev, _, _)| ev).checked_sum()?;
println!("done");

if available_value < target || target == Amount::ZERO {
return None;
}

println!("start loop");
while iteration < ITERATION_LIMIT {
backtrack = false;

Expand Down Expand Up @@ -430,10 +435,14 @@ mod tests {
FeeRate::from_sat_per_kwu(u)
}

fn calculate_max_fee_rate(amount: Amount, weight: Weight) -> FeeRate {
let amt = Amount::from_sat(18446744073709551);
fn calculate_max_fee_rate(amount: Amount, weight: Weight) -> Option<FeeRate> {
let weight = weight + Weight::from_wu(TX_IN_BASE_WEIGHT);
amt.checked_div_by_weight(weight).unwrap() - FeeRate::from_sat_per_kwu(1)

if let Some(fee_rate) = amount.checked_div_by_weight(weight) {
Some(fee_rate)
} else {
None
}
}

#[test]
Expand Down Expand Up @@ -718,81 +727,83 @@ mod tests {
assert_eq!(list.next().unwrap().value(), Amount::from_sat(target));
}

//#[test]
//fn select_one_of_one_idealized_proptest() {
//let minimal_non_dust: u64 = 1;
//let effective_value_max: u64 = SignedAmount::MAX.to_sat() as u64;

//arbtest(|u| {
//let amount = arb_amount_in_range(u, minimal_non_dust..=effective_value_max);
//let utxo = build_utxo(amount, Weight::ZERO);
//let pool: Vec<Utxo> = vec![utxo.clone()];

//let coins: Vec<Utxo> = select_coins_bnb(
//utxo.value(),
//Amount::ZERO,
//FeeRate::ZERO,
//FeeRate::ZERO,
//&pool,
//)
//.unwrap()
//.cloned()
//.collect();

//assert_eq!(coins, pool);

//Ok(())
//});
//}
#[test]
fn select_one_of_one_idealized_proptest() {
let minimal_non_dust: u64 = 1;
let effective_value_max: u64 = SignedAmount::MAX.to_sat() as u64;

arbtest(|u| {
let amount = arb_amount_in_range(u, minimal_non_dust..=effective_value_max);
let utxo = build_utxo(amount, Weight::ZERO);
let pool: Vec<Utxo> = vec![utxo.clone()];

let coins: Vec<Utxo> = select_coins_bnb(
utxo.value(),
Amount::ZERO,
FeeRate::ZERO,
FeeRate::ZERO,
&pool,
)
.unwrap()
.cloned()
.collect();

//#[test]
//fn select_one_of_many_proptest() {
//arbtest(|u| {
//let pool = UtxoPool::arbitrary(u)?;
//let utxo = u.choose(&pool.utxos)?;
assert_eq!(coins, pool);

//let max_fee_rate = calculate_max_fee_rate(utxo.value(), utxo.satisfaction_weight());
//let fee_rate = arb_fee_rate_in_range(u, 1..=max_fee_rate.to_sat_per_kwu());
Ok(())
}).seed(0xd9c264a200000020);
}

//let target_effective_value = effective_value(
//fee_rate,
//utxo.satisfaction_weight(),
//utxo.value(),
//);
#[test]
fn select_one_of_many_proptest() {
arbtest(|u| {
let pool = UtxoPool::arbitrary(u)?;
let utxos = pool.utxos.clone();

let utxo = u.choose(&utxos)?;

let max_fee_rate = calculate_max_fee_rate(utxo.value(), utxo.satisfaction_weight());
if let Some(f) = max_fee_rate {
let fee_rate = arb_fee_rate_in_range(u, 1..=f.to_sat_per_kwu());

let target_effective_value = effective_value(
fee_rate,
utxo.satisfaction_weight(),
utxo.value(),
).unwrap();

if let Ok(target) = target_effective_value.to_unsigned() {
let result = select_coins_bnb(
target,
Amount::ZERO,
fee_rate,
fee_rate,
&utxos,
);

if let Some(r) = result {
let sum: SignedAmount = r.map(|u| {
effective_value(
fee_rate,
u.satisfaction_weight(),
u.value()
).unwrap()
}).sum();
let amount_sum = sum.to_unsigned().unwrap();
assert_eq!(amount_sum, target);
} else {
// if result was none, then assert that fail happened because overflow when
// ssumming pool. In the future, assert specific error when added.
let available_value = utxos.into_iter().map(|u| u.value()).checked_sum();
assert!(available_value.is_none());
}

// if the effective_value was greater than i64 max, then don't use as a target.
//if let Some(positive_signed) = target_effective_value {
// If the effective_value was negative it can't be used as a target.
//if let Ok(target) = positive_signed.to_unsigned() {
//let coins = select_coins_bnb(
//target,
//Amount::ZERO,
//fee_rate,
//fee_rate,
//&pool.utxos,
//);

// If results are some then check the results
// else verify the error.
//if let Some(c) = coins {
//let result: SignedAmount = c.map(|u| {
//effective_value(
//fee_rate,
//u.satisfaction_weight(),
//u.value()
//).unwrap()
//}).sum();
//assert_eq!(result.to_unsigned().unwrap(), target);
//} else {
//let pool_sum = pool.utxos.iter().cloned().map(|u| u.value()).checked_sum();
//assert!(pool_sum.is_none()); // assert error when added.
//}
//}
//}
}
}

//Ok(())
//});
//}
Ok(())
});
}

//#[test]
//fn select_many_of_many_proptest() {
Expand Down

0 comments on commit 4cce555

Please sign in to comment.