@@ -832,3 +832,53 @@ def test_xpay_twohop_bug(node_factory, bitcoind):
832832 # This doesn't!
833833 l1 .rpc .xpay (inv )
834834 l1 .daemon .wait_for_log (f'Adding HTLC 1 amount=15002msat cltv={ 110 + 1 + 100 + 200 + 400 } ' )
835+
836+
837+ def test_attempt_notifications (node_factory ):
838+ plugin_path = os .path .join (os .getcwd (), 'tests/plugins/custom_notifications.py' )
839+ l1 , l2 , l3 = node_factory .line_graph (3 , wait_for_announce = True ,
840+ opts = [{"plugin" : plugin_path }, {}, {}])
841+
842+ scid12 = only_one (l1 .rpc .listpeerchannels (l2 .info ['id' ])['channels' ])['short_channel_id' ]
843+ scid12_dir = only_one (l1 .rpc .listpeerchannels (l2 .info ['id' ])['channels' ])['direction' ]
844+ scid23 = only_one (l2 .rpc .listpeerchannels (l3 .info ['id' ])['channels' ])['short_channel_id' ]
845+ scid23_dir = only_one (l2 .rpc .listpeerchannels (l3 .info ['id' ])['channels' ])['direction' ]
846+ inv1 = l3 .rpc .invoice (5000000 , 'test_attempt_notifications1' , 'test_attempt_notifications1' )
847+ l1 .rpc .xpay (inv1 ['bolt11' ])
848+
849+ line = l1 .daemon .wait_for_log ("plugin-custom_notifications.py: Got pay_part_start: " )
850+ regex = r".*Got pay_part_start: \{'payment_hash': '" + inv1 ['payment_hash' ] + r"', 'groupid': [0-9]*, 'partid': 1, 'total_payment_msat': 5000000, 'attempt_msat': 5000000, 'hops': \[\{'next_node': '" + l2 .info ['id' ] + r"', 'short_channel_id': '" + scid12 + r"', 'direction': " + str (scid12_dir ) + r", 'channel_in_msat': 5000051, 'channel_out_msat': 5000051\}, \{'next_node': '" + l3 .info ['id' ] + r"', 'short_channel_id': '" + scid23 + r"', 'direction': " + str (scid23_dir ) + r", 'channel_in_msat': 5000051, 'channel_out_msat': 5000000\}\]\}"
851+ assert re .match (regex , line )
852+
853+ # Note, duration always has 9 decimals, EXCEPT that the python code interprets it, so if the last digit is a 0 it will only print 8.
854+ line = l1 .daemon .wait_for_log ("plugin-custom_notifications.py: Got pay_part_end: " )
855+ regex = r".*Got pay_part_end: \{'status': 'success', 'duration': [0-9]*\.[0-9]*, 'payment_hash': '" + inv1 ['payment_hash' ] + r"', 'groupid': [0-9]*, 'partid': 1\}"
856+ assert re .match (regex , line )
857+
858+ inv2 = l3 .rpc .invoice (10000000 , 'test_attempt_notifications2' , 'test_attempt_notifications2' )
859+ l3 .rpc .delinvoice ('test_attempt_notifications2' , "unpaid" )
860+
861+ # Final node failure
862+ with pytest .raises (RpcError , match = r"Destination said it doesn't know invoice: incorrect_or_unknown_payment_details" ):
863+ l1 .rpc .xpay (inv2 ['bolt11' ])
864+
865+ line = l1 .daemon .wait_for_log ("plugin-custom_notifications.py: Got pay_part_start: " )
866+ regex = r".*Got pay_part_start: \{'payment_hash': '" + inv2 ['payment_hash' ] + r"', 'groupid': [0-9]*, 'partid': 1, 'total_payment_msat': 10000000, 'attempt_msat': 10000000, 'hops': \[\{'next_node': '" + l2 .info ['id' ] + r"', 'short_channel_id': '" + scid12 + r"', 'direction': " + str (scid12_dir ) + r", 'channel_in_msat': 10000101, 'channel_out_msat': 10000101\}, \{'next_node': '" + l3 .info ['id' ] + r"', 'short_channel_id': '" + scid23 + r"', 'direction': " + str (scid23_dir ) + r", 'channel_in_msat': 10000101, 'channel_out_msat': 10000000\}\]\}"
867+ assert re .match (regex , line )
868+
869+ line = l1 .daemon .wait_for_log ("plugin-custom_notifications.py: Got pay_part_end: " )
870+ regex = r".*Got pay_part_end: \{'status': 'failure', 'payment_hash': '" + inv2 ['payment_hash' ] + r"', 'groupid': [0-9]*, 'partid': 1, 'failed_msg': '400f00000000009896800000006c', 'duration': [0-9]*\.[0-9]*, 'failed_node_id': '" + l3 .info ['id' ] + r"', 'error_code': 16399, 'error_message': 'incorrect_or_unknown_payment_details'\}"
871+ assert re .match (regex , line )
872+
873+ # Intermediary node failure
874+ l3 .stop ()
875+ with pytest .raises (RpcError , match = r"Failed after 1 attempts" ):
876+ l1 .rpc .xpay (inv2 ['bolt11' ])
877+
878+ line = l1 .daemon .wait_for_log ("plugin-custom_notifications.py: Got pay_part_start: " )
879+ regex = r".*Got pay_part_start: \{'payment_hash': '" + inv2 ['payment_hash' ] + r"', 'groupid': [0-9]*, 'partid': 1, 'total_payment_msat': 10000000, 'attempt_msat': 10000000, 'hops': \[\{'next_node': '" + l2 .info ['id' ] + r"', 'short_channel_id': '" + scid12 + r"', 'direction': " + str (scid12_dir ) + r", 'channel_in_msat': 10000101, 'channel_out_msat': 10000101\}, \{'next_node': '" + l3 .info ['id' ] + r"', 'short_channel_id': '" + scid23 + r"', 'direction': " + str (scid23_dir ) + r", 'channel_in_msat': 10000101, 'channel_out_msat': 10000000\}\]\}"
880+ assert re .match (regex , line )
881+
882+ line = l1 .daemon .wait_for_log ("plugin-custom_notifications.py: Got pay_part_end: " )
883+ regex = r".*Got pay_part_end: \{'status': 'failure', 'payment_hash': '" + inv2 ['payment_hash' ] + r"', 'groupid': [0-9]*, 'partid': 1, 'failed_msg': '1007[a-f0-9]*', 'duration': [0-9]*\.[0-9]*, 'failed_node_id': '" + l2 .info ['id' ] + r"', 'failed_short_channel_id': '" + scid23 + r"', 'failed_direction': " + str (scid23_dir ) + r", 'error_code': 4103, 'error_message': 'temporary_channel_failure'\}"
884+ assert re .match (regex , line )
0 commit comments