@@ -559,3 +559,120 @@ fn test_sync_with_coinbase() -> anyhow::Result<()> {
559
559
560
560
Ok ( ( ) )
561
561
}
562
+
563
+ #[ test]
564
+ fn test_check_fee_calculation ( ) -> anyhow:: Result < ( ) > {
565
+ const SEND_AMOUNT : Amount = Amount :: from_sat ( 10_000 ) ;
566
+ const FEE_AMOUNT : Amount = Amount :: from_sat ( 1650 ) ;
567
+ let env = TestEnv :: new ( ) ?;
568
+ let electrum_client = electrum_client:: Client :: new ( env. electrsd . electrum_url . as_str ( ) ) ?;
569
+ let client = BdkElectrumClient :: new ( electrum_client) ;
570
+
571
+ let spk_to_track = ScriptBuf :: new_p2wsh ( & WScriptHash :: all_zeros ( ) ) ;
572
+ let addr_to_track = Address :: from_script ( & spk_to_track, bdk_chain:: bitcoin:: Network :: Regtest ) ?;
573
+
574
+ // Setup receiver.
575
+ let ( mut recv_chain, _) = LocalChain :: from_genesis_hash ( env. bitcoind . client . get_block_hash ( 0 ) ?) ;
576
+ let mut recv_graph = IndexedTxGraph :: < ConfirmationBlockTime , _ > :: new ( {
577
+ let mut recv_index = SpkTxOutIndex :: default ( ) ;
578
+ recv_index. insert_spk ( ( ) , spk_to_track. clone ( ) ) ;
579
+ recv_index
580
+ } ) ;
581
+
582
+ // Mine some blocks.
583
+ env. mine_blocks ( 101 , None ) ?;
584
+
585
+ // Send a preliminary tx such that the new utxo in Core's wallet
586
+ // becomes the input of the next tx
587
+ let new_addr = env
588
+ . rpc_client ( )
589
+ . get_new_address ( None , None ) ?
590
+ . assume_checked ( ) ;
591
+ let prev_amt = SEND_AMOUNT + FEE_AMOUNT ;
592
+ env. send ( & new_addr, prev_amt) ?;
593
+ let prev_block_hash = env. mine_blocks ( 1 , None ) ?. into_iter ( ) . next ( ) ;
594
+
595
+ let txid = env. send ( & addr_to_track, SEND_AMOUNT ) ?;
596
+
597
+ // Mine a block to confirm sent tx.
598
+ let block_hash = env. mine_blocks ( 1 , None ) ?. into_iter ( ) . next ( ) ;
599
+
600
+ // Look at the tx we just sent, it should have 1 input and 1 output
601
+ let tx = env
602
+ . rpc_client ( )
603
+ . get_raw_transaction_info ( & txid, block_hash. as_ref ( ) ) ?;
604
+ assert_eq ! ( tx. vin. len( ) , 1 ) ;
605
+ assert_eq ! ( tx. vout. len( ) , 1 ) ;
606
+ let vin = & tx. vin [ 0 ] ;
607
+ let prev_txid = vin. txid . unwrap ( ) ;
608
+ let vout = vin. vout . unwrap ( ) ;
609
+ let outpoint = bdk_chain:: bitcoin:: OutPoint :: new ( prev_txid, vout) ;
610
+
611
+ // Get the txout of the previous tx
612
+ let prev_tx = env
613
+ . rpc_client ( )
614
+ . get_raw_transaction_info ( & prev_txid, prev_block_hash. as_ref ( ) ) ?;
615
+ let txout = prev_tx
616
+ . vout
617
+ . iter ( )
618
+ . find ( |txout| txout. value == prev_amt)
619
+ . unwrap ( ) ;
620
+ let script_pubkey = ScriptBuf :: from_bytes ( txout. script_pub_key . hex . to_vec ( ) ) ;
621
+ let txout = bdk_chain:: bitcoin:: TxOut {
622
+ value : txout. value ,
623
+ script_pubkey,
624
+ } ;
625
+
626
+ // Sync up to tip.
627
+ env. wait_until_electrum_sees_block ( Duration :: from_secs ( 6 ) ) ?;
628
+ let _ = sync_with_electrum (
629
+ & client,
630
+ [ spk_to_track. clone ( ) ] ,
631
+ & mut recv_chain,
632
+ & mut recv_graph,
633
+ ) ?;
634
+
635
+ // Check the graph update contains the right floating txout
636
+ let graph_txout = recv_graph
637
+ . graph ( )
638
+ . all_txouts ( )
639
+ . find ( |( _op, txout) | txout. value == prev_amt)
640
+ . unwrap ( ) ;
641
+ assert_eq ! ( graph_txout, ( outpoint, & txout) ) ;
642
+
643
+ // Check to see if tx is confirmed.
644
+ assert_eq ! (
645
+ get_balance( & recv_chain, & recv_graph) ?,
646
+ Balance {
647
+ confirmed: SEND_AMOUNT ,
648
+ ..Balance :: default ( )
649
+ } ,
650
+ ) ;
651
+
652
+ for tx in recv_graph. graph ( ) . full_txs ( ) {
653
+ // Retrieve the calculated fee from `TxGraph`, which will panic if we do not have the
654
+ // floating txouts available from the transaction's previous outputs.
655
+ let fee = recv_graph
656
+ . graph ( )
657
+ . calculate_fee ( & tx. tx )
658
+ . expect ( "fee must exist" ) ;
659
+
660
+ // Check the fee calculated fee matches the initial fee amount
661
+ assert_eq ! ( fee, FEE_AMOUNT ) ;
662
+
663
+ // Retrieve the fee in the transaction data from `bitcoind`.
664
+ let tx_fee = env
665
+ . bitcoind
666
+ . client
667
+ . get_transaction ( & tx. txid , None )
668
+ . expect ( "Tx must exist" )
669
+ . fee
670
+ . expect ( "Fee must exist" )
671
+ . abs ( )
672
+ . to_sat ( ) as u64 ;
673
+
674
+ // Check that the calculated fee matches the fee from the transaction data.
675
+ assert_eq ! ( fee, Amount :: from_sat( tx_fee) ) ; // 1650sat
676
+ }
677
+ Ok ( ( ) )
678
+ }
0 commit comments