@@ -6,7 +6,6 @@ use bdk::wallet::coin_selection::LargestFirstCoinSelection;
66use bdk:: wallet:: AddressIndex :: * ;
77use bdk:: wallet:: { AddressIndex , AddressInfo , Balance , Wallet } ;
88use bdk:: { Error , FeeRate , KeychainKind } ;
9- use bdk_chain:: tx_graph:: CalculateFeeError ;
109use bdk_chain:: COINBASE_MATURITY ;
1110use bdk_chain:: { BlockId , ConfirmationTime } ;
1211use bitcoin:: hashes:: Hash ;
@@ -84,63 +83,60 @@ fn test_descriptor_checksum() {
8483#[ test]
8584fn test_get_funded_wallet_balance ( ) {
8685 let ( wallet, _) = get_funded_wallet ( get_test_wpkh ( ) ) ;
87- assert_eq ! ( wallet. get_balance( ) . confirmed, 50000 ) ;
86+
87+ // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
88+ // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
89+ // sats are the transaction fee.
90+ assert_eq ! ( wallet. get_balance( ) . confirmed, 50_000 ) ;
8891}
8992
9093#[ test]
9194fn test_get_funded_wallet_sent_and_received ( ) {
92- let ( wallet, _ ) = get_funded_wallet ( get_test_wpkh ( ) ) ;
93- assert_eq ! ( wallet . get_balance ( ) . confirmed , 50000 ) ;
95+ let ( wallet, txid ) = get_funded_wallet ( get_test_wpkh ( ) ) ;
96+
9497 let mut tx_amounts: Vec < ( Txid , ( u64 , u64 ) ) > = wallet
9598 . transactions ( )
96- . map ( |ct| ( ct. node . txid , wallet. sent_and_received ( ct. node . tx ) ) )
99+ . map ( |ct| ( ct. tx_node . txid , wallet. sent_and_received ( ct. tx_node . tx ) ) )
97100 . collect ( ) ;
98101 tx_amounts. sort_by ( |a1, a2| a1. 0 . cmp ( & a2. 0 ) ) ;
99102
100- assert_eq ! ( tx_amounts. len( ) , 2 ) ;
101- assert_matches ! ( tx_amounts. get( 0 ) , Some ( ( _, ( 76_000 , 50_000 ) ) ) )
103+ let tx = wallet. get_tx ( txid) . expect ( "transaction" ) . tx_node . tx ;
104+ let ( sent, received) = wallet. sent_and_received ( tx) ;
105+
106+ // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
107+ // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
108+ // sats are the transaction fee.
109+ assert_eq ! ( sent, 76_000 ) ;
110+ assert_eq ! ( received, 50_000 ) ;
102111}
103112
104113#[ test]
105114fn test_get_funded_wallet_tx_fees ( ) {
106- let ( wallet, _) = get_funded_wallet ( get_test_wpkh ( ) ) ;
107- assert_eq ! ( wallet. get_balance( ) . confirmed, 50000 ) ;
108- let mut tx_fee_amounts: Vec < ( Txid , Result < u64 , CalculateFeeError > ) > = wallet
109- . transactions ( )
110- . map ( |ct| {
111- let fee = wallet. calculate_fee ( ct. node . tx ) ;
112- ( ct. node . txid , fee)
113- } )
114- . collect ( ) ;
115- tx_fee_amounts. sort_by ( |a1, a2| a1. 0 . cmp ( & a2. 0 ) ) ;
115+ let ( wallet, txid) = get_funded_wallet ( get_test_wpkh ( ) ) ;
116116
117- assert_eq ! ( tx_fee_amounts. len( ) , 2 ) ;
118- assert_matches ! (
119- tx_fee_amounts. get( 1 ) ,
120- Some ( ( _, Err ( CalculateFeeError :: MissingTxOut ( _) ) ) )
121- ) ;
122- assert_matches ! ( tx_fee_amounts. get( 0 ) , Some ( ( _, Ok ( 1000 ) ) ) )
117+ let tx = wallet. get_tx ( txid) . expect ( "transaction" ) . tx_node . tx ;
118+ let tx_fee = wallet. calculate_fee ( tx) . expect ( "transaction fee" ) ;
119+
120+ // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
121+ // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
122+ // sats are the transaction fee.
123+ assert_eq ! ( tx_fee, 1000 )
123124}
124125
125126#[ test]
126127fn test_get_funded_wallet_tx_fee_rate ( ) {
127- let ( wallet, _) = get_funded_wallet ( get_test_wpkh ( ) ) ;
128- assert_eq ! ( wallet. get_balance( ) . confirmed, 50000 ) ;
129- let mut tx_fee_rates: Vec < ( Txid , Result < FeeRate , CalculateFeeError > ) > = wallet
130- . transactions ( )
131- . map ( |ct| {
132- let fee_rate = wallet. calculate_fee_rate ( ct. node . tx ) ;
133- ( ct. node . txid , fee_rate)
134- } )
135- . collect ( ) ;
136- tx_fee_rates. sort_by ( |a1, a2| a1. 0 . cmp ( & a2. 0 ) ) ;
128+ let ( wallet, txid) = get_funded_wallet ( get_test_wpkh ( ) ) ;
137129
138- assert_eq ! ( tx_fee_rates. len( ) , 2 ) ;
139- assert_matches ! (
140- tx_fee_rates. get( 1 ) ,
141- Some ( ( _, Err ( CalculateFeeError :: MissingTxOut ( _) ) ) )
142- ) ;
143- assert_matches ! ( tx_fee_rates. get( 0 ) , Some ( ( _, Ok ( _) ) ) )
130+ let tx = wallet. get_tx ( txid) . expect ( "transaction" ) . tx_node . tx ;
131+ let tx_fee_rate = wallet. calculate_fee_rate ( tx) . expect ( "transaction fee rate" ) ;
132+
133+ // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000
134+ // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000
135+ // sats are the transaction fee.
136+
137+ // tx weight = 452 bytes, as vbytes = (452+3)/4 = 113
138+ // fee rate (sats per vbyte) = fee / vbytes = 1000 / 113 = 8.8495575221 rounded to 8.849558
139+ assert_eq ! ( tx_fee_rate. as_sat_per_vb( ) , 8.849558 ) ;
144140}
145141
146142macro_rules! assert_fee_rate {
@@ -1098,6 +1094,77 @@ fn test_add_foreign_utxo() {
10981094 assert ! ( finished, "all the inputs should have been signed now" ) ;
10991095}
11001096
1097+ #[ test]
1098+ #[ should_panic(
1099+ expected = "MissingTxOut([OutPoint { txid: 0x21d7fb1bceda00ab4069fc52d06baa13470803e9050edd16f5736e5d8c4925fd, vout: 0 }])"
1100+ ) ]
1101+ fn test_calculate_fee_with_missing_foreign_utxo ( ) {
1102+ let ( mut wallet1, _) = get_funded_wallet ( get_test_wpkh ( ) ) ;
1103+ let ( wallet2, _) =
1104+ get_funded_wallet ( "wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)" ) ;
1105+
1106+ let addr = Address :: from_str ( "2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX" )
1107+ . unwrap ( )
1108+ . assume_checked ( ) ;
1109+ let utxo = wallet2. list_unspent ( ) . next ( ) . expect ( "must take!" ) ;
1110+ #[ allow( deprecated) ]
1111+ let foreign_utxo_satisfaction = wallet2
1112+ . get_descriptor_for_keychain ( KeychainKind :: External )
1113+ . max_satisfaction_weight ( )
1114+ . unwrap ( ) ;
1115+
1116+ let psbt_input = psbt:: Input {
1117+ witness_utxo : Some ( utxo. txout . clone ( ) ) ,
1118+ ..Default :: default ( )
1119+ } ;
1120+
1121+ let mut builder = wallet1. build_tx ( ) ;
1122+ builder
1123+ . add_recipient ( addr. script_pubkey ( ) , 60_000 )
1124+ . only_witness_utxo ( )
1125+ . add_foreign_utxo ( utxo. outpoint , psbt_input, foreign_utxo_satisfaction)
1126+ . unwrap ( ) ;
1127+ let psbt = builder. finish ( ) . unwrap ( ) ;
1128+ let tx = psbt. extract_tx ( ) ;
1129+ wallet1. calculate_fee ( & tx) . unwrap ( ) ;
1130+ }
1131+
1132+ #[ test]
1133+ fn test_calculate_fee_with_inserted_foreign_utxo ( ) {
1134+ let ( mut wallet1, _) = get_funded_wallet ( get_test_wpkh ( ) ) ;
1135+ let ( wallet2, _) =
1136+ get_funded_wallet ( "wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)" ) ;
1137+
1138+ let addr = Address :: from_str ( "2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX" )
1139+ . unwrap ( )
1140+ . assume_checked ( ) ;
1141+ let utxo = wallet2. list_unspent ( ) . next ( ) . expect ( "must take!" ) ;
1142+ #[ allow( deprecated) ]
1143+ let foreign_utxo_satisfaction = wallet2
1144+ . get_descriptor_for_keychain ( KeychainKind :: External )
1145+ . max_satisfaction_weight ( )
1146+ . unwrap ( ) ;
1147+
1148+ let psbt_input = psbt:: Input {
1149+ witness_utxo : Some ( utxo. txout . clone ( ) ) ,
1150+ ..Default :: default ( )
1151+ } ;
1152+
1153+ let mut builder = wallet1. build_tx ( ) ;
1154+ builder
1155+ . add_recipient ( addr. script_pubkey ( ) , 60_000 )
1156+ . only_witness_utxo ( )
1157+ . add_foreign_utxo ( utxo. outpoint , psbt_input, foreign_utxo_satisfaction)
1158+ . unwrap ( ) ;
1159+ let psbt = builder. finish ( ) . unwrap ( ) ;
1160+ let psbt_fee = psbt. fee_amount ( ) . expect ( "psbt fee" ) ;
1161+ let tx = psbt. extract_tx ( ) ;
1162+
1163+ wallet1. insert_txout ( utxo. outpoint , utxo. txout ) ;
1164+ let wallet1_fee = wallet1. calculate_fee ( & tx) . expect ( "wallet fee" ) ;
1165+ assert_eq ! ( psbt_fee, wallet1_fee) ;
1166+ }
1167+
11011168#[ test]
11021169#[ should_panic( expected = "Generic(\" Foreign utxo missing witness_utxo or non_witness_utxo\" )" ) ]
11031170fn test_add_foreign_utxo_invalid_psbt_input ( ) {
@@ -1122,8 +1189,8 @@ fn test_add_foreign_utxo_where_outpoint_doesnt_match_psbt_input() {
11221189 get_funded_wallet ( "wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)" ) ;
11231190
11241191 let utxo2 = wallet2. list_unspent ( ) . next ( ) . unwrap ( ) ;
1125- let tx1 = wallet1. get_tx ( txid1) . unwrap ( ) . node . tx . clone ( ) ;
1126- let tx2 = wallet2. get_tx ( txid2) . unwrap ( ) . node . tx . clone ( ) ;
1192+ let tx1 = wallet1. get_tx ( txid1) . unwrap ( ) . tx_node . tx . clone ( ) ;
1193+ let tx2 = wallet2. get_tx ( txid2) . unwrap ( ) . tx_node . tx . clone ( ) ;
11271194
11281195 #[ allow( deprecated) ]
11291196 let satisfaction_weight = wallet2
@@ -1212,7 +1279,7 @@ fn test_add_foreign_utxo_only_witness_utxo() {
12121279
12131280 {
12141281 let mut builder = builder. clone ( ) ;
1215- let tx2 = wallet2. get_tx ( txid2) . unwrap ( ) . node . tx ;
1282+ let tx2 = wallet2. get_tx ( txid2) . unwrap ( ) . tx_node . tx ;
12161283 let psbt_input = psbt:: Input {
12171284 non_witness_utxo : Some ( tx2. clone ( ) ) ,
12181285 ..Default :: default ( )
@@ -2842,7 +2909,7 @@ fn test_taproot_sign_using_non_witness_utxo() {
28422909 let mut psbt = builder. finish ( ) . unwrap ( ) ;
28432910
28442911 psbt. inputs [ 0 ] . witness_utxo = None ;
2845- psbt. inputs [ 0 ] . non_witness_utxo = Some ( wallet. get_tx ( prev_txid) . unwrap ( ) . node . tx . clone ( ) ) ;
2912+ psbt. inputs [ 0 ] . non_witness_utxo = Some ( wallet. get_tx ( prev_txid) . unwrap ( ) . tx_node . tx . clone ( ) ) ;
28462913 assert ! (
28472914 psbt. inputs[ 0 ] . non_witness_utxo. is_some( ) ,
28482915 "Previous tx should be present in the database"
0 commit comments