@@ -6112,3 +6112,50 @@ fn test_data_loss_protect() {
6112
6112
assert_eq ! ( spend_txn. len( ) , 1 ) ;
6113
6113
check_spends ! ( spend_txn[ 0 ] , node_txn[ 0 ] . clone( ) ) ;
6114
6114
}
6115
+
6116
+ #[ test]
6117
+ fn test_check_htlc_underpaying ( ) {
6118
+ // Send payment through A -> B but A is maliciously
6119
+ // sending a probe payment (i.e less than expected value0
6120
+ // to B, B should refuse payment.
6121
+
6122
+ let nodes = create_network ( 2 , & [ None , None , None ] ) ;
6123
+
6124
+ // Create some initial channels
6125
+ create_announced_chan_between_nodes ( & nodes, 0 , 1 , LocalFeatures :: new ( ) , LocalFeatures :: new ( ) ) ;
6126
+
6127
+ let ( payment_preimage, _) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , 10_000 ) ;
6128
+
6129
+ // Node 3 is expecting payment of 100_000 but receive 10_000,
6130
+ // fail htlc like we didn't know the preimage.
6131
+ nodes[ 1 ] . node . claim_funds ( payment_preimage, 100_000 ) ;
6132
+ nodes[ 1 ] . node . process_pending_htlc_forwards ( ) ;
6133
+
6134
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
6135
+ assert_eq ! ( events. len( ) , 1 ) ;
6136
+ let ( update_fail_htlc, commitment_signed) = match events[ 0 ] {
6137
+ MessageSendEvent :: UpdateHTLCs { node_id : _ , updates : msgs:: CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
6138
+ assert ! ( update_add_htlcs. is_empty( ) ) ;
6139
+ assert ! ( update_fulfill_htlcs. is_empty( ) ) ;
6140
+ assert_eq ! ( update_fail_htlcs. len( ) , 1 ) ;
6141
+ assert ! ( update_fail_malformed_htlcs. is_empty( ) ) ;
6142
+ assert ! ( update_fee. is_none( ) ) ;
6143
+ ( update_fail_htlcs[ 0 ] . clone ( ) , commitment_signed)
6144
+ } ,
6145
+ _ => panic ! ( "Unexpected event" ) ,
6146
+ } ;
6147
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
6148
+
6149
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & update_fail_htlc) . unwrap ( ) ;
6150
+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , commitment_signed, false , true ) ;
6151
+
6152
+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
6153
+ assert_eq ! ( events. len( ) , 1 ) ;
6154
+ if let & Event :: PaymentFailed { payment_hash : _, ref rejected_by_dest, ref error_code } = & events[ 0 ] {
6155
+ assert_eq ! ( * rejected_by_dest, true ) ;
6156
+ assert_eq ! ( error_code. unwrap( ) , 0x4000 |15 ) ;
6157
+ } else {
6158
+ panic ! ( "Unexpected event" ) ;
6159
+ }
6160
+ nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
6161
+ }
0 commit comments