@@ -747,6 +747,239 @@ fn test_balances_on_local_commitment_htlcs() {
747747 test_spendable_output ( & nodes[ 0 ] , & as_txn[ 1 ] ) ;
748748}
749749
750+ #[ test]
751+ fn test_no_preimage_inbound_htlc_balances ( ) {
752+ // Tests that MaybePreimageCLaimableHTLCAwaitingTImeouts are generated for inbound HTLCs for
753+ // which we do not have a preimage.
754+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
755+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
756+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
757+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
758+
759+ let ( _, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 500_000_000 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
760+ let funding_outpoint = OutPoint { txid : funding_tx. txid ( ) , index : 0 } ;
761+
762+ // Send two HTLCs, one from A to B, and one from B to C.
763+ let to_b_failed_payment_hash = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 10_000_000 ) . 1 ;
764+ let to_a_failed_payment_hash = route_payment ( & nodes[ 1 ] , & [ & nodes[ 0 ] ] , 20_000_000 ) . 1 ;
765+ let htlc_cltv_timeout = nodes[ 0 ] . best_block_info ( ) . 1 + TEST_FINAL_CLTV + 1 ; // Note ChannelManager adds one to CLTV timeouts for safety
766+
767+ let chan_feerate = get_feerate ! ( nodes[ 0 ] , chan_id) as u64 ;
768+ let opt_anchors = get_opt_anchors ! ( nodes[ 0 ] , chan_id) ;
769+
770+ // Both A and B will have an HTLC that's claimable on timeout and one that's claimable if they
771+ // receive the preimage. These will remain the same through the channel closure and until the
772+ // HTLC output is spent.
773+
774+ assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableOnChannelClose {
775+ claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate *
776+ ( channel:: commitment_tx_base_weight( opt_anchors) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
777+ } , Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
778+ claimable_amount_satoshis: 20_000 ,
779+ expiry_height: htlc_cltv_timeout,
780+ } , Balance :: MaybeClaimableHTLCAwaitingTimeout {
781+ claimable_amount_satoshis: 10_000 ,
782+ claimable_height: htlc_cltv_timeout,
783+ } ] ) ,
784+ sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
785+
786+ assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableOnChannelClose {
787+ claimable_amount_satoshis: 500_000 - 20_000 ,
788+ } , Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
789+ claimable_amount_satoshis: 10_000 ,
790+ expiry_height: htlc_cltv_timeout,
791+ } , Balance :: MaybeClaimableHTLCAwaitingTimeout {
792+ claimable_amount_satoshis: 20_000 ,
793+ claimable_height: htlc_cltv_timeout,
794+ } ] ) ,
795+ sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
796+
797+ // Get nodes[0]'s commitment transaction and HTLC-Timeout transaction
798+ let as_txn = get_local_commitment_txn ! ( nodes[ 0 ] , chan_id) ;
799+ assert_eq ! ( as_txn. len( ) , 2 ) ;
800+ check_spends ! ( as_txn[ 1 ] , as_txn[ 0 ] ) ;
801+ check_spends ! ( as_txn[ 0 ] , funding_tx) ;
802+
803+ // Now close the channel by confirming A's commitment transaction on both nodes, checking the
804+ // claimable balances remain the same except for the non-HTLC balance changing variant.
805+ let node_a_commitment_claimable = nodes[ 0 ] . best_block_info ( ) . 1 + BREAKDOWN_TIMEOUT as u32 ;
806+ let as_pre_spend_claims = sorted_vec ( vec ! [ Balance :: ClaimableAwaitingConfirmations {
807+ claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate *
808+ ( channel:: commitment_tx_base_weight( opt_anchors) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
809+ confirmation_height: node_a_commitment_claimable,
810+ } , Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
811+ claimable_amount_satoshis: 20_000 ,
812+ expiry_height: htlc_cltv_timeout,
813+ } , Balance :: MaybeClaimableHTLCAwaitingTimeout {
814+ claimable_amount_satoshis: 10_000 ,
815+ claimable_height: htlc_cltv_timeout,
816+ } ] ) ;
817+
818+ mine_transaction ( & nodes[ 0 ] , & as_txn[ 0 ] ) ;
819+ nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clear ( ) ;
820+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
821+ check_closed_broadcast ! ( nodes[ 0 ] , true ) ;
822+ check_closed_event ! ( nodes[ 0 ] , 1 , ClosureReason :: CommitmentTxConfirmed ) ;
823+
824+ assert_eq ! ( as_pre_spend_claims,
825+ sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
826+
827+ mine_transaction ( & nodes[ 1 ] , & as_txn[ 0 ] ) ;
828+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
829+ check_closed_broadcast ! ( nodes[ 1 ] , true ) ;
830+ check_closed_event ! ( nodes[ 1 ] , 1 , ClosureReason :: CommitmentTxConfirmed ) ;
831+
832+ let node_b_commitment_claimable = nodes[ 1 ] . best_block_info ( ) . 1 + ANTI_REORG_DELAY - 1 ;
833+ let mut bs_pre_spend_claims = sorted_vec ( vec ! [ Balance :: ClaimableAwaitingConfirmations {
834+ claimable_amount_satoshis: 500_000 - 20_000 ,
835+ confirmation_height: node_b_commitment_claimable,
836+ } , Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
837+ claimable_amount_satoshis: 10_000 ,
838+ expiry_height: htlc_cltv_timeout,
839+ } , Balance :: MaybeClaimableHTLCAwaitingTimeout {
840+ claimable_amount_satoshis: 20_000 ,
841+ claimable_height: htlc_cltv_timeout,
842+ } ] ) ;
843+ assert_eq ! ( bs_pre_spend_claims,
844+ sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
845+
846+ // If we get one block prior to the HTLC expiring, we'll broadcast the HTLC-timeout transaction
847+ // (as it is confirmable in the next block), but will still include the same claimable
848+ // balances as no HTLC has been spent, even after the HTLC expires. We'll also fail the inbound
849+ // HTLC, but it won't do anything as the channel is already closed.
850+
851+ connect_blocks ( & nodes[ 0 ] , TEST_FINAL_CLTV - 1 ) ;
852+ let as_htlc_timeout_claim = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
853+ assert_eq ! ( as_htlc_timeout_claim. len( ) , 1 ) ;
854+ check_spends ! ( as_htlc_timeout_claim[ 0 ] , as_txn[ 0 ] ) ;
855+ expect_pending_htlcs_forwardable_conditions ! ( nodes[ 0 ] ,
856+ [ HTLCDestination :: FailedPayment { payment_hash: to_a_failed_payment_hash } ] ) ;
857+
858+ assert_eq ! ( as_pre_spend_claims,
859+ sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
860+
861+ connect_blocks ( & nodes[ 0 ] , 1 ) ;
862+ assert_eq ! ( as_pre_spend_claims,
863+ sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
864+
865+ // For node B, we'll get the non-HTLC funds claimable after ANTI_REORG_DELAY confirmations
866+ connect_blocks ( & nodes[ 1 ] , ANTI_REORG_DELAY - 1 ) ;
867+ test_spendable_output ( & nodes[ 1 ] , & as_txn[ 0 ] ) ;
868+ bs_pre_spend_claims. retain ( |e| if let Balance :: ClaimableAwaitingConfirmations { .. } = e { false } else { true } ) ;
869+
870+ // The next few blocks for B look the same as for A, though for the opposite HTLC
871+ nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clear ( ) ;
872+ connect_blocks ( & nodes[ 1 ] , TEST_FINAL_CLTV - ( ANTI_REORG_DELAY - 1 ) - 1 ) ;
873+ expect_pending_htlcs_forwardable_conditions ! ( nodes[ 1 ] ,
874+ [ HTLCDestination :: FailedPayment { payment_hash: to_b_failed_payment_hash } ] ) ;
875+ let bs_htlc_timeout_claim = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
876+ assert_eq ! ( bs_htlc_timeout_claim. len( ) , 1 ) ;
877+ check_spends ! ( bs_htlc_timeout_claim[ 0 ] , as_txn[ 0 ] ) ;
878+
879+ assert_eq ! ( bs_pre_spend_claims,
880+ sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
881+
882+ connect_blocks ( & nodes[ 1 ] , 1 ) ;
883+ assert_eq ! ( bs_pre_spend_claims,
884+ sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
885+
886+ // Now confirm the two HTLC timeout transactions for A, checking that the inbound HTLC resolves
887+ // after ANTI_REORG_DELAY confirmations and the other takes BREAKDOWN_TIMEOUT confirmations.
888+ mine_transaction ( & nodes[ 0 ] , & as_htlc_timeout_claim[ 0 ] ) ;
889+ let as_timeout_claimable_height = nodes[ 0 ] . best_block_info ( ) . 1 + ( BREAKDOWN_TIMEOUT as u32 ) - 1 ;
890+ assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableAwaitingConfirmations {
891+ claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate *
892+ ( channel:: commitment_tx_base_weight( opt_anchors) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
893+ confirmation_height: node_a_commitment_claimable,
894+ } , Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
895+ claimable_amount_satoshis: 20_000 ,
896+ expiry_height: htlc_cltv_timeout,
897+ } , Balance :: ClaimableAwaitingConfirmations {
898+ claimable_amount_satoshis: 10_000 ,
899+ confirmation_height: as_timeout_claimable_height,
900+ } ] ) ,
901+ sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
902+ assert ! ( nodes[ 0 ] . node. get_and_clear_pending_events( ) . is_empty( ) ) ;
903+
904+ mine_transaction ( & nodes[ 0 ] , & bs_htlc_timeout_claim[ 0 ] ) ;
905+ assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableAwaitingConfirmations {
906+ claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate *
907+ ( channel:: commitment_tx_base_weight( opt_anchors) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
908+ confirmation_height: node_a_commitment_claimable,
909+ } , Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
910+ claimable_amount_satoshis: 20_000 ,
911+ expiry_height: htlc_cltv_timeout,
912+ } , Balance :: ClaimableAwaitingConfirmations {
913+ claimable_amount_satoshis: 10_000 ,
914+ confirmation_height: as_timeout_claimable_height,
915+ } ] ) ,
916+ sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
917+
918+ // Once as_htlc_timeout_claim[0] reaches ANTI_REORG_DELAY confirmations, we should get a
919+ // payment failure event.
920+ connect_blocks ( & nodes[ 0 ] , ANTI_REORG_DELAY - 2 ) ;
921+ expect_payment_failed ! ( nodes[ 0 ] , to_b_failed_payment_hash, true ) ;
922+
923+ connect_blocks ( & nodes[ 0 ] , 1 ) ;
924+ assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableAwaitingConfirmations {
925+ claimable_amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate *
926+ ( channel:: commitment_tx_base_weight( opt_anchors) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
927+ confirmation_height: node_a_commitment_claimable,
928+ } , Balance :: ClaimableAwaitingConfirmations {
929+ claimable_amount_satoshis: 10_000 ,
930+ confirmation_height: core:: cmp:: max( as_timeout_claimable_height, htlc_cltv_timeout) ,
931+ } ] ) ,
932+ sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
933+
934+ connect_blocks ( & nodes[ 0 ] , node_a_commitment_claimable - nodes[ 0 ] . best_block_info ( ) . 1 ) ;
935+ assert_eq ! ( vec![ Balance :: ClaimableAwaitingConfirmations {
936+ claimable_amount_satoshis: 10_000 ,
937+ confirmation_height: core:: cmp:: max( as_timeout_claimable_height, htlc_cltv_timeout) ,
938+ } ] ,
939+ nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ;
940+ test_spendable_output ( & nodes[ 0 ] , & as_txn[ 0 ] ) ;
941+
942+ connect_blocks ( & nodes[ 0 ] , as_timeout_claimable_height - nodes[ 0 ] . best_block_info ( ) . 1 ) ;
943+ assert ! ( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) . is_empty( ) ) ;
944+ test_spendable_output ( & nodes[ 0 ] , & as_htlc_timeout_claim[ 0 ] ) ;
945+
946+ // The process for B should be completely identical as well, noting that the non-HTLC-balance
947+ // was already claimed.
948+ mine_transaction ( & nodes[ 1 ] , & bs_htlc_timeout_claim[ 0 ] ) ;
949+ let bs_timeout_claimable_height = nodes[ 1 ] . best_block_info ( ) . 1 + ANTI_REORG_DELAY - 1 ;
950+ assert_eq ! ( sorted_vec( vec![ Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
951+ claimable_amount_satoshis: 10_000 ,
952+ expiry_height: htlc_cltv_timeout,
953+ } , Balance :: ClaimableAwaitingConfirmations {
954+ claimable_amount_satoshis: 20_000 ,
955+ confirmation_height: bs_timeout_claimable_height,
956+ } ] ) ,
957+ sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
958+
959+ mine_transaction ( & nodes[ 1 ] , & as_htlc_timeout_claim[ 0 ] ) ;
960+ assert_eq ! ( sorted_vec( vec![ Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
961+ claimable_amount_satoshis: 10_000 ,
962+ expiry_height: htlc_cltv_timeout,
963+ } , Balance :: ClaimableAwaitingConfirmations {
964+ claimable_amount_satoshis: 20_000 ,
965+ confirmation_height: bs_timeout_claimable_height,
966+ } ] ) ,
967+ sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
968+
969+ connect_blocks ( & nodes[ 1 ] , ANTI_REORG_DELAY - 2 ) ;
970+ expect_payment_failed ! ( nodes[ 1 ] , to_a_failed_payment_hash, true ) ;
971+
972+ assert_eq ! ( vec![ Balance :: MaybePreimageClaimableHTLCAwaitingTimeout {
973+ claimable_amount_satoshis: 10_000 ,
974+ expiry_height: htlc_cltv_timeout,
975+ } ] ,
976+ nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ;
977+ test_spendable_output ( & nodes[ 1 ] , & bs_htlc_timeout_claim[ 0 ] ) ;
978+
979+ connect_blocks ( & nodes[ 1 ] , 1 ) ;
980+ assert ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) . is_empty( ) ) ;
981+ }
982+
750983fn sorted_vec_with_additions < T : Ord + Clone > ( v_orig : & Vec < T > , extra_ts : & [ & T ] ) -> Vec < T > {
751984 let mut v = v_orig. clone ( ) ;
752985 for t in extra_ts {
0 commit comments