@@ -623,3 +623,78 @@ fn test_dup_htlc_onchain_fails_on_reload() {
623
623
do_test_dup_htlc_onchain_fails_on_reload ( false , true , false ) ;
624
624
do_test_dup_htlc_onchain_fails_on_reload ( false , false , false ) ;
625
625
}
626
+
627
+ #[ test]
628
+ fn test_fulfill_restart_failure ( ) {
629
+ // When we receive an update_fulfill_htlc message, we immediately consider the HTLC fully
630
+ // fulfilled. At this point, the peer can reconnect and decide to either fulfill the HTLC
631
+ // again, or fail it, giving us free money.
632
+ //
633
+ // Of course probably they won't fail it and give us free money, but because we have code to
634
+ // handle it, we should test the logic for it anyway. We do that here.
635
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
636
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
637
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
638
+ let persister: test_utils:: TestPersister ;
639
+ let new_chain_monitor: test_utils:: TestChainMonitor ;
640
+ let nodes_1_deserialized: ChannelManager < EnforcingSigner , & test_utils:: TestChainMonitor , & test_utils:: TestBroadcaster , & test_utils:: TestKeysInterface , & test_utils:: TestFeeEstimator , & test_utils:: TestLogger > ;
641
+ let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
642
+
643
+ let chan_id = create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) . 2 ;
644
+ let ( payment_preimage, payment_hash, _) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 100_000 ) ;
645
+
646
+ // The simplest way to get a failure after a fulfill is to reload nodes[1] from a state
647
+ // pre-fulfill, which we do by serializing it here.
648
+ let mut chan_manager_serialized = test_utils:: TestVecWriter ( Vec :: new ( ) ) ;
649
+ nodes[ 1 ] . node . write ( & mut chan_manager_serialized) . unwrap ( ) ;
650
+ let mut chan_0_monitor_serialized = test_utils:: TestVecWriter ( Vec :: new ( ) ) ;
651
+ get_monitor ! ( nodes[ 1 ] , chan_id) . write ( & mut chan_0_monitor_serialized) . unwrap ( ) ;
652
+
653
+ nodes[ 1 ] . node . claim_funds ( payment_preimage) ;
654
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
655
+ let htlc_fulfill_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
656
+ nodes[ 0 ] . node . handle_update_fulfill_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & htlc_fulfill_updates. update_fulfill_htlcs [ 0 ] ) ;
657
+ expect_payment_sent ! ( nodes[ 0 ] , payment_preimage) ;
658
+
659
+ // Now reload nodes[1]...
660
+ persister = test_utils:: TestPersister :: new ( ) ;
661
+ let keys_manager = & chanmon_cfgs[ 1 ] . keys_manager ;
662
+ new_chain_monitor = test_utils:: TestChainMonitor :: new ( Some ( nodes[ 1 ] . chain_source ) , nodes[ 1 ] . tx_broadcaster . clone ( ) , nodes[ 1 ] . logger , node_cfgs[ 1 ] . fee_estimator , & persister, keys_manager) ;
663
+ nodes[ 1 ] . chain_monitor = & new_chain_monitor;
664
+ let mut chan_0_monitor_read = & chan_0_monitor_serialized. 0 [ ..] ;
665
+ let ( _, mut chan_0_monitor) = <( BlockHash , ChannelMonitor < EnforcingSigner > ) >:: read (
666
+ & mut chan_0_monitor_read, keys_manager) . unwrap ( ) ;
667
+ assert ! ( chan_0_monitor_read. is_empty( ) ) ;
668
+
669
+ let ( _, nodes_1_deserialized_tmp) = {
670
+ let mut channel_monitors = HashMap :: new ( ) ;
671
+ channel_monitors. insert ( chan_0_monitor. get_funding_txo ( ) . 0 , & mut chan_0_monitor) ;
672
+ <( BlockHash , ChannelManager < EnforcingSigner , & test_utils:: TestChainMonitor , & test_utils:: TestBroadcaster , & test_utils:: TestKeysInterface , & test_utils:: TestFeeEstimator , & test_utils:: TestLogger > ) >
673
+ :: read ( & mut io:: Cursor :: new ( & chan_manager_serialized. 0 [ ..] ) , ChannelManagerReadArgs {
674
+ default_config : Default :: default ( ) ,
675
+ keys_manager,
676
+ fee_estimator : node_cfgs[ 1 ] . fee_estimator ,
677
+ chain_monitor : nodes[ 1 ] . chain_monitor ,
678
+ tx_broadcaster : nodes[ 1 ] . tx_broadcaster . clone ( ) ,
679
+ logger : nodes[ 1 ] . logger ,
680
+ channel_monitors,
681
+ } ) . unwrap ( )
682
+ } ;
683
+ nodes_1_deserialized = nodes_1_deserialized_tmp;
684
+
685
+ assert ! ( nodes[ 1 ] . chain_monitor. watch_channel( chan_0_monitor. get_funding_txo( ) . 0 , chan_0_monitor) . is_ok( ) ) ;
686
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
687
+ nodes[ 1 ] . node = & nodes_1_deserialized;
688
+
689
+ nodes[ 0 ] . node . peer_disconnected ( & nodes[ 1 ] . node . get_our_node_id ( ) , false ) ;
690
+ reconnect_nodes ( & nodes[ 0 ] , & nodes[ 1 ] , ( false , false ) , ( 0 , 0 ) , ( 0 , 0 ) , ( 0 , 0 ) , ( 0 , 0 ) , ( 0 , 0 ) , ( false , false ) ) ;
691
+
692
+ nodes[ 1 ] . node . fail_htlc_backwards ( & payment_hash) ;
693
+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
694
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
695
+ let htlc_fail_updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
696
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & htlc_fail_updates. update_fail_htlcs [ 0 ] ) ;
697
+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , htlc_fail_updates. commitment_signed, false ) ;
698
+ // nodes[0] shouldn't generate any events here, while it just got a payment failure completion
699
+ // it had already considered the payment fulfilled, and now they just got free money.
700
+ }
0 commit comments