From: github-actions Date: Wed, 3 Aug 2022 18:17:32 +0000 (+0000) Subject: Publish autogenerated nightly docs X-Git-Url: http://internal-gitweb-vhost/script/%22https:/database/scripts/enum.Wildcard.html?a=commitdiff_plain;h=2f43f94c00c120649cabc8ad055cec68d4d27730;p=bitcoindevkit.org Publish autogenerated nightly docs --- diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html index a558f29beb..b217046f05 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html @@ -6,7 +6,7 @@ logo

Module coin_selection

logo
Expand description

Coin selection

+

Module bdk::wallet::coin_selection

source · []
Expand description

Coin selection

This module provides the trait CoinSelectionAlgorithm that can be implemented to define custom coin selection algorithms.

You can specify a custom coin selection algorithm through the coin_selection method on diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html index f637808b80..ef15844bea 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html @@ -9,7 +9,7 @@

Struct bdk::wallet::coin_selection::BranchAndBoundCoinSelection

source · []
pub struct BranchAndBoundCoinSelection { /* private fields */ }
Expand description

Branch and bound coin selection

Code adapted from Bitcoin Core’s implementation and from Mark Erhardt Master’s Thesis: http://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf

Implementations

Create new instance with target size for change output

-

Trait Implementations

Perform the coin selection Read more

+

Trait Implementations

Perform the coin selection Read more

Formats the value using the given formatter. Read more

Returns the “default value” for a type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html index 81f4a9e4f8..16ffdf5158 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html @@ -25,5 +25,5 @@ weight cost accumulated from added outputs and transaction’s header.
  • drain_script: the script to use in case of change
  • -

    Implementors

    +

    Implementors

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html index 586d3c4267..6099714dd2 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html @@ -1495,6 +1495,112 @@ 1488 1489 1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -1935,10 +2041,12 @@
                 .map(|u| OutputGroup::new(u, fee_rate))
                 .collect();
     
    -        // Mapping every (UTXO, usize) to an output group.
    +        // Mapping every (UTXO, usize) to an output group, filtering UTXOs with a negative
    +        // effective value
             let optional_utxos: Vec<OutputGroup> = optional_utxos
                 .into_iter()
                 .map(|u| OutputGroup::new(u, fee_rate))
    +            .filter(|u| u.effective_value.is_positive())
                 .collect();
     
             let curr_value = required_utxos
    @@ -1951,17 +2059,39 @@
     
             let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb();
     
    -        let expected = (curr_available_value + curr_value)
    -            .try_into()
    -            .map_err(|_| {
    -                Error::Generic("Sum of UTXO spendable values does not fit into u64".to_string())
    -            })?;
    -
    -        if expected < target_amount {
    -            return Err(Error::InsufficientFunds {
    -                needed: target_amount,
    -                available: expected,
    -            });
    +        // `curr_value` and `curr_available_value` are both the sum of *effective_values* of
    +        // the UTXOs. For the optional UTXOs (curr_available_value) we filter out UTXOs with
    +        // negative effective value, so it will always be positive.
    +        //
    +        // Since we are required to spend the required UTXOs (curr_value) we have to consider
    +        // all their effective values, even when negative, which means that curr_value could
    +        // be negative as well.
    +        //
    +        // If the sum of curr_value and curr_available_value is negative or lower than our target,
    +        // we can immediately exit with an error, as it's guaranteed we will never find a solution
    +        // if we actually run the BnB.
    +        let total_value: Result<u64, _> = (curr_available_value + curr_value).try_into();
    +        match total_value {
    +            Ok(v) if v >= target_amount => {}
    +            _ => {
    +                // Assume we spend all the UTXOs we can (all the required + all the optional with
    +                // positive effective value), sum their value and their fee cost.
    +                let (utxo_fees, utxo_value) = required_utxos
    +                    .iter()
    +                    .chain(optional_utxos.iter())
    +                    .fold((0, 0), |(mut fees, mut value), utxo| {
    +                        fees += utxo.fee;
    +                        value += utxo.weighted_utxo.utxo.txout().value;
    +
    +                        (fees, value)
    +                    });
    +
    +                // Add to the target the fee cost of the UTXOs
    +                return Err(Error::InsufficientFunds {
    +                    needed: target_amount + utxo_fees,
    +                    available: utxo_value,
    +                });
    +            }
             }
     
             let target_amount = target_amount
    @@ -2691,9 +2821,9 @@
                 )
                 .unwrap();
     
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300010);
    -        assert_eq!(result.fee_amount, 204);
    +        assert_eq!(result.selected.len(), 2);
    +        assert_eq!(result.selected_amount(), 300000);
    +        assert_eq!(result.fee_amount, 136);
         }
     
         #[test]
    @@ -2725,9 +2855,9 @@
                 )
                 .unwrap();
     
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300_010);
    -        assert!((result.fee_amount as f32 - 204.0).abs() < f32::EPSILON);
    +        assert_eq!(result.selected.len(), 2);
    +        assert_eq!(result.selected_amount(), 300_000);
    +        assert_eq!(result.fee_amount, 136);
         }
     
         #[test]
    @@ -2984,6 +3114,88 @@
             assert!(result.selected_amount() > target_amount);
             assert_eq!(result.fee_amount, (result.selected.len() * 68) as u64);
         }
    +
    +    #[test]
    +    fn test_bnb_exclude_negative_effective_value() {
    +        let utxos = get_test_utxos();
    +        let database = MemoryDatabase::default();
    +        let drain_script = Script::default();
    +
    +        let err = BranchAndBoundCoinSelection::default()
    +            .coin_select(
    +                &database,
    +                vec![],
    +                utxos,
    +                FeeRate::from_sat_per_vb(10.0),
    +                500_000,
    +                &drain_script,
    +            )
    +            .unwrap_err();
    +
    +        assert!(matches!(
    +            err,
    +            Error::InsufficientFunds {
    +                available: 300_000,
    +                ..
    +            }
    +        ));
    +    }
    +
    +    #[test]
    +    fn test_bnb_include_negative_effective_value_when_required() {
    +        let utxos = get_test_utxos();
    +        let database = MemoryDatabase::default();
    +        let drain_script = Script::default();
    +
    +        let (required, optional) = utxos
    +            .into_iter()
    +            .partition(|u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value < 1000));
    +
    +        let err = BranchAndBoundCoinSelection::default()
    +            .coin_select(
    +                &database,
    +                required,
    +                optional,
    +                FeeRate::from_sat_per_vb(10.0),
    +                500_000,
    +                &drain_script,
    +            )
    +            .unwrap_err();
    +
    +        assert!(matches!(
    +            err,
    +            Error::InsufficientFunds {
    +                available: 300_010,
    +                ..
    +            }
    +        ));
    +    }
    +
    +    #[test]
    +    fn test_bnb_sum_of_effective_value_negative() {
    +        let utxos = get_test_utxos();
    +        let database = MemoryDatabase::default();
    +        let drain_script = Script::default();
    +
    +        let err = BranchAndBoundCoinSelection::default()
    +            .coin_select(
    +                &database,
    +                utxos,
    +                vec![],
    +                FeeRate::from_sat_per_vb(10_000.0),
    +                500_000,
    +                &drain_script,
    +            )
    +            .unwrap_err();
    +
    +        assert!(matches!(
    +            err,
    +            Error::InsufficientFunds {
    +                available: 300_010,
    +                ..
    +            }
    +        ));
    +    }
     }