@@ -1554,67 +1554,55 @@ fn tx_outpoint_range(txid: Txid) -> RangeInclusive<OutPoint> {
1554
1554
OutPoint :: new ( txid, u32:: MIN ) ..=OutPoint :: new ( txid, u32:: MAX )
1555
1555
}
1556
1556
1557
- /// Bench
1558
- #[ allow( unused) ]
1559
- #[ allow( missing_docs) ]
1560
1557
#[ cfg( bdk_bench) ]
1561
- pub mod bench {
1562
- use std:: str:: FromStr ;
1563
-
1558
+ mod bench_util {
1564
1559
use bdk_core:: { CheckPoint , ConfirmationBlockTime } ;
1565
- use bitcoin:: absolute;
1566
- use bitcoin:: hashes:: Hash ;
1567
- use bitcoin:: transaction;
1568
- use bitcoin:: { Address , BlockHash , Network , TxIn } ;
1569
- use criterion:: Criterion ;
1570
- use miniscript:: Descriptor ;
1571
- use miniscript:: DescriptorPublicKey ;
1560
+ use bitcoin:: {
1561
+ absolute, constants, hashes:: Hash , secp256k1:: Secp256k1 , transaction, BlockHash , Network ,
1562
+ TxIn ,
1563
+ } ;
1564
+ use miniscript:: { Descriptor , DescriptorPublicKey } ;
1572
1565
1573
1566
use super :: * ;
1574
1567
use crate :: keychain_txout:: KeychainTxOutIndex ;
1575
1568
use crate :: local_chain:: LocalChain ;
1576
1569
use crate :: IndexedTxGraph ;
1577
1570
1578
1571
#[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
1579
- enum Keychain {
1572
+ pub enum Keychain {
1580
1573
External ,
1581
1574
}
1582
1575
1583
1576
const EXTERNAL : & str = "tr([ab28dc00/86h/1h/0h]tpubDCdDtzAMZZrkwKBxwNcGCqe4FRydeD9rfMisoi7qLdraG79YohRfPW4YgdKQhpgASdvh612xXNY5xYzoqnyCgPbkpK4LSVcH5Xv4cK7johH/0/*)" ;
1584
1577
1585
- fn get_params ( ) -> (
1586
- IndexedTxGraph < ConfirmationBlockTime , KeychainTxOutIndex < Keychain > > ,
1587
- LocalChain ,
1588
- ) {
1589
- let genesis = bitcoin:: constants:: genesis_block ( Network :: Regtest ) . block_hash ( ) ;
1578
+ type KeychainTxGraph = IndexedTxGraph < ConfirmationBlockTime , KeychainTxOutIndex < Keychain > > ;
1579
+
1580
+ pub fn init_graph_chain ( ) -> ( KeychainTxGraph , LocalChain ) {
1581
+ let genesis = constants:: genesis_block ( Network :: Regtest ) . block_hash ( ) ;
1590
1582
let block_0 = BlockId {
1591
1583
height : 0 ,
1592
1584
hash : genesis,
1593
1585
} ;
1586
+ // chain tip 100
1594
1587
let mut cp = CheckPoint :: new ( block_0) ;
1595
- let block_100 = BlockId {
1588
+ let chain_tip = BlockId {
1596
1589
height : 100 ,
1597
1590
hash : BlockHash :: all_zeros ( ) ,
1598
1591
} ;
1599
- cp = cp. push ( block_100 ) . unwrap ( ) ;
1592
+ cp = cp. push ( chain_tip ) . unwrap ( ) ;
1600
1593
let chain = LocalChain :: from_tip ( cp) . unwrap ( ) ;
1601
1594
1602
- let mut graph = IndexedTxGraph :: new ( {
1603
- let mut index = KeychainTxOutIndex :: new ( 10 ) ;
1604
- index
1605
- . insert_descriptor ( Keychain :: External , parse_descriptor ( EXTERNAL ) )
1606
- . unwrap ( ) ;
1607
- index
1608
- } ) ;
1595
+ let desc = parse_descriptor ( EXTERNAL ) ;
1596
+ let spk_0 = desc. at_derivation_index ( 0 ) . unwrap ( ) . script_pubkey ( ) ;
1597
+ let mut index = KeychainTxOutIndex :: new ( 10 ) ;
1598
+ index. insert_descriptor ( Keychain :: External , desc) . unwrap ( ) ;
1599
+ let mut graph = IndexedTxGraph :: new ( index) ;
1609
1600
1610
- // insert funding tx (coinbase)
1611
- let addr_0 =
1612
- Address :: from_str ( "bcrt1plhmjhj75nut38qwwm5w7xqysy25xhd4ckuv7zu5tey3nkmcwh3cqvan5mz" )
1613
- . unwrap ( )
1614
- . assume_checked ( ) ;
1601
+ // insert funding tx (coinbase) confirmed at chain tip
1615
1602
let tx_0 = Transaction {
1603
+ input : vec ! [ TxIn :: default ( ) ] ,
1616
1604
output : vec ! [ TxOut {
1617
- script_pubkey: addr_0 . script_pubkey ( ) ,
1605
+ script_pubkey: spk_0 . clone ( ) ,
1618
1606
value: Amount :: ONE_BTC ,
1619
1607
} ] ,
1620
1608
..new_tx ( 0 )
@@ -1624,43 +1612,140 @@ pub mod bench {
1624
1612
let _ = graph. insert_anchor (
1625
1613
txid_0,
1626
1614
ConfirmationBlockTime {
1627
- block_id : block_100 ,
1615
+ block_id : chain_tip ,
1628
1616
confirmation_time : 100 ,
1629
1617
} ,
1630
1618
) ;
1631
1619
1632
1620
( graph, chain)
1633
1621
}
1634
1622
1635
- fn parse_descriptor ( s : & str ) -> miniscript:: Descriptor < DescriptorPublicKey > {
1636
- <Descriptor < DescriptorPublicKey > >:: parse_descriptor (
1637
- & bitcoin:: secp256k1:: Secp256k1 :: new ( ) ,
1638
- s,
1639
- )
1640
- . unwrap ( )
1641
- . 0
1623
+ /// Add `n` conflicts to `graph` that spend the given `previous_output`, incrementing
1624
+ /// the tx last-seen on each iteration.
1625
+ pub fn add_conflicts ( n : u32 , graph : & mut KeychainTxGraph , previous_output : OutPoint ) {
1626
+ let spk_1 = parse_descriptor ( EXTERNAL )
1627
+ . at_derivation_index ( 1 )
1628
+ . unwrap ( )
1629
+ . script_pubkey ( ) ;
1630
+ for i in 1 ..n + 1 {
1631
+ let value = Amount :: ONE_BTC - Amount :: from_sat ( i as u64 * 10 ) ;
1632
+ let tx = Transaction {
1633
+ input : vec ! [ TxIn {
1634
+ previous_output,
1635
+ ..Default :: default ( )
1636
+ } ] ,
1637
+ output : vec ! [ TxOut {
1638
+ value,
1639
+ script_pubkey: spk_1. clone( ) ,
1640
+ } ] ,
1641
+ ..new_tx ( i)
1642
+ } ;
1643
+ let txid = tx. compute_txid ( ) ;
1644
+ let _ = graph. insert_tx ( tx) ;
1645
+ let _ = graph. insert_seen_at ( txid, i as u64 ) ;
1646
+ }
1642
1647
}
1643
1648
1644
- fn new_tx ( lt : u32 ) -> Transaction {
1649
+ /// Apply a chain of `n` unconfirmed txs where each subsequent
1650
+ /// tx spends the output of the previous one.
1651
+ pub fn chain_unconfirmed ( n : u32 , graph : & mut KeychainTxGraph ) {
1652
+ let ( mut previous_output, txout) = graph
1653
+ . graph ( )
1654
+ . all_txouts ( )
1655
+ . find ( |( _, txout) | txout. value == Amount :: ONE_BTC )
1656
+ . expect ( "initial graph should have txout" ) ;
1657
+ let init_amount = txout. value ;
1658
+ let fee = Amount :: from_sat ( 1000 ) ;
1659
+
1660
+ let desc = graph. index . get_descriptor ( Keychain :: External ) . unwrap ( ) ;
1661
+ let spks: Vec < _ > = ( 0 ..n)
1662
+ . map ( |i| desc. at_derivation_index ( i) . unwrap ( ) . script_pubkey ( ) )
1663
+ . collect ( ) ;
1664
+
1665
+ for i in 0 ..n {
1666
+ // create tx
1667
+ let tx = Transaction {
1668
+ input : vec ! [ TxIn {
1669
+ previous_output,
1670
+ ..Default :: default ( )
1671
+ } ] ,
1672
+ output : vec ! [ TxOut {
1673
+ value: init_amount - ( fee * ( i as u64 + 1 ) ) ,
1674
+ script_pubkey: spks[ i as usize ] . clone( ) ,
1675
+ } ] ,
1676
+ ..new_tx ( i)
1677
+ } ;
1678
+ let txid = tx. compute_txid ( ) ;
1679
+ let update = TxUpdate {
1680
+ txs : vec ! [ Arc :: new( tx) ] ,
1681
+ ..Default :: default ( )
1682
+ } ;
1683
+ let _ = graph. apply_update_at ( update, Some ( 21 ) ) ;
1684
+ // store the next prevout
1685
+ previous_output = OutPoint :: new ( txid, 0 ) ;
1686
+ }
1687
+ }
1688
+
1689
+ pub fn parse_descriptor ( s : & str ) -> Descriptor < DescriptorPublicKey > {
1690
+ <Descriptor < DescriptorPublicKey > >:: parse_descriptor ( & Secp256k1 :: new ( ) , s)
1691
+ . unwrap ( )
1692
+ . 0
1693
+ }
1694
+
1695
+ pub fn new_tx ( lt : u32 ) -> Transaction {
1645
1696
Transaction {
1646
1697
version : transaction:: Version :: TWO ,
1647
1698
lock_time : absolute:: LockTime :: from_consensus ( lt) ,
1648
1699
input : vec ! [ ] ,
1649
1700
output : vec ! [ ] ,
1650
1701
}
1651
1702
}
1703
+ }
1652
1704
1705
+ /// Bench
1706
+ #[ cfg( bdk_bench) ]
1707
+ #[ allow( missing_docs) ]
1708
+ pub mod bench {
1709
+ use std:: hint:: black_box;
1710
+
1711
+ use criterion:: Criterion ;
1712
+
1713
+ use super :: * ;
1714
+ use crate :: tx_graph:: bench_util:: * ;
1715
+
1716
+ #[ inline( never) ]
1653
1717
pub fn filter_chain_unspents ( bench : & mut Criterion ) {
1654
- let ( graph, chain) = get_params ( ) ;
1655
- // TODO: insert conflicts
1718
+ let ( mut graph, chain) = black_box ( init_graph_chain ( ) ) ;
1719
+ let txouts: Vec < _ > = graph. graph ( ) . all_txouts ( ) . collect ( ) ;
1720
+ assert_eq ! ( txouts. len( ) , 1 ) ;
1721
+ let prevout = txouts. iter ( ) . next ( ) . unwrap ( ) . 0 ;
1722
+ black_box ( add_conflicts ( 1000 , & mut graph, prevout) ) ;
1723
+
1656
1724
bench. bench_function ( "filter_chain_unspents" , |b| {
1657
1725
b. iter ( || {
1658
- TxGraph :: filter_chain_unspents (
1726
+ let unspent = TxGraph :: filter_chain_unspents (
1659
1727
graph. graph ( ) ,
1660
1728
& chain,
1661
1729
chain. tip ( ) . block_id ( ) ,
1662
1730
graph. index . outpoints ( ) . clone ( ) ,
1663
- )
1731
+ ) ;
1732
+ assert_eq ! ( unspent. count( ) , 1 ) ;
1733
+ } )
1734
+ } ) ;
1735
+ }
1736
+
1737
+ #[ inline( never) ]
1738
+ pub fn list_canonical_txs ( bench : & mut Criterion ) {
1739
+ let ( mut graph, chain) = black_box ( init_graph_chain ( ) ) ;
1740
+ assert_eq ! ( graph. graph( ) . txs. len( ) , 1 ) ;
1741
+ black_box ( chain_unconfirmed ( 100 , & mut graph) ) ;
1742
+
1743
+ bench. bench_function ( "list_canonical_txs" , |b| {
1744
+ b. iter ( || {
1745
+ let txs = graph
1746
+ . graph ( )
1747
+ . list_canonical_txs ( & chain, chain. tip ( ) . block_id ( ) ) ;
1748
+ assert_eq ! ( txs. count( ) , 100 + 1 ) ;
1664
1749
} )
1665
1750
} ) ;
1666
1751
}
0 commit comments