@@ -997,6 +997,7 @@ def test_real_data(node_factory, bitcoind):
997997 assert (len (fees [best ]), len (improved ), total_first_fee , total_final_fee , percent_fee_reduction ) == (8 , 95 , 6007785 , 564997 , 91 )
998998
999999
1000+ @pytest .mark .slow_test
10001001def test_askrene_fake_channeld (node_factory , bitcoind ):
10011002 outfile = tempfile .NamedTemporaryFile (prefix = 'gossip-store-' )
10021003 nodeids = subprocess .check_output (['devtools/gossmap-compress' ,
@@ -1024,36 +1025,71 @@ def test_askrene_fake_channeld(node_factory, bitcoind):
10241025 shaseed = subprocess .check_output (["tools/hsmtool" , "dumpcommitments" , l1 .info ['id' ], "1" , "0" , hsmfile ]).decode ('utf-8' ).strip ().partition (": " )[2 ]
10251026 l1 .rpc .dev_peer_shachain (l2 .info ['id' ], shaseed )
10261027
1028+ TEMPORARY_CHANNEL_FAILURE = 0x1007
1029+ MPP_TIMEOUT = 0x17
1030+
1031+ l1 .rpc .askrene_create_layer ('test_askrene_fake_channeld' )
10271032 for n in range (0 , 100 ):
10281033 if n in (62 , 76 , 80 , 97 ):
10291034 continue
10301035
1031- routes = l1 .rpc .getroutes (source = l1 .info ['id' ],
1032- destination = nodeids [n ],
1033- amount_msat = AMOUNT ,
1034- layers = ['auto.sourcefree' , 'auto.localchans' ],
1035- maxfee_msat = AMOUNT ,
1036- final_cltv = 18 )
1037-
1038- preimage_hex = f'{ n :02} ' + '00' * 31
1039- hash_hex = sha256 (bytes .fromhex (preimage_hex )).hexdigest ()
1040-
1041- # Sendpay wants a different format, so we convert.
1042- for i , r in enumerate (routes ['routes' ]):
1043- hops = [{'id' : h ['next_node_id' ],
1044- 'channel' : h ['short_channel_id_dir' ].split ('/' )[0 ]}
1045- for h in r ['path' ]]
1046- # delay and amount_msat for sendpay are amounts at *end* of hop, not start!
1047- with_end = r ['path' ] + [{'amount_msat' : r ['amount_msat' ], 'delay' : r ['final_cltv' ]}]
1048- for n , h in enumerate (hops ):
1049- h ['delay' ] = with_end [n + 1 ]['delay' ]
1050- h ['amount_msat' ] = with_end [n + 1 ]['amount_msat' ]
1051-
1052- l1 .rpc .sendpay (hops , hash_hex ,
1053- amount_msat = AMOUNT ,
1054- payment_secret = '00' * 32 ,
1055- partid = i + 1 , groupid = 1 )
1056-
1057- for i , r in enumerate (routes ['routes' ]):
1058- # Worst-case timeout is 1 second per hop.
1059- assert l1 .rpc .waitsendpay (hash_hex , timeout = TIMEOUT + len (r ['path' ]), partid = i + 1 , groupid = 1 )['payment_preimage' ] == preimage_hex
1036+ print (f"PAYING Node #{ n } " )
1037+ success = False
1038+ while not success :
1039+ routes = l1 .rpc .getroutes (source = l1 .info ['id' ],
1040+ destination = nodeids [n ],
1041+ amount_msat = AMOUNT ,
1042+ layers = ['auto.sourcefree' , 'auto.localchans' ],
1043+ maxfee_msat = AMOUNT ,
1044+ final_cltv = 18 )
1045+
1046+ preimage_hex = f'{ n :02} ' + '00' * 31
1047+ hash_hex = sha256 (bytes .fromhex (preimage_hex )).hexdigest ()
1048+
1049+ paths = {}
1050+ # Sendpay wants a different format, so we convert.
1051+ for i , r in enumerate (routes ['routes' ]):
1052+ paths [i ] = [{'id' : h ['next_node_id' ],
1053+ 'channel' : h ['short_channel_id_dir' ].split ('/' )[0 ],
1054+ 'direction' : int (h ['short_channel_id_dir' ].split ('/' )[1 ])}
1055+ for h in r ['path' ]]
1056+
1057+ # delay and amount_msat for sendpay are amounts at *end* of hop, not start!
1058+ with_end = r ['path' ] + [{'amount_msat' : r ['amount_msat' ], 'delay' : r ['final_cltv' ]}]
1059+ for n , h in enumerate (paths [i ]):
1060+ h ['delay' ] = with_end [n + 1 ]['delay' ]
1061+ h ['amount_msat' ] = with_end [n + 1 ]['amount_msat' ]
1062+
1063+ l1 .rpc .sendpay (paths [i ], hash_hex ,
1064+ amount_msat = AMOUNT ,
1065+ payment_secret = '00' * 32 ,
1066+ partid = i + 1 , groupid = 1 )
1067+
1068+ for i , p in paths .items ():
1069+ # Worst-case timeout is 1 second per hop, + 60 seconds if MPP timeout!
1070+ try :
1071+ if l1 .rpc .waitsendpay (hash_hex , timeout = TIMEOUT + len (p ) + 60 , partid = i + 1 , groupid = 1 ):
1072+ success = True
1073+ except RpcError as err :
1074+ # Timeout means this one succeeded!
1075+ if err .error ['data' ]['failcode' ] == MPP_TIMEOUT :
1076+ for h in p :
1077+ l1 .rpc .askrene_inform_channel ('test_askrene_fake_channeld' ,
1078+ f"{ h ['channel' ]} /{ h ['direction' ]} " ,
1079+ h ['amount_msat' ],
1080+ 'unconstrained' )
1081+ elif err .error ['data' ]['failcode' ] == TEMPORARY_CHANNEL_FAILURE :
1082+ # We succeeded up to here
1083+ failpoint = err .error ['data' ]['erring_index' ]
1084+ for h in p [:failpoint ]:
1085+ l1 .rpc .askrene_inform_channel ('test_askrene_fake_channeld' ,
1086+ f"{ h ['channel' ]} /{ h ['direction' ]} " ,
1087+ h ['amount_msat' ],
1088+ 'unconstrained' )
1089+ h = p [failpoint ]
1090+ l1 .rpc .askrene_inform_channel ('test_askrene_fake_channeld' ,
1091+ f"{ h ['channel' ]} /{ h ['direction' ]} " ,
1092+ h ['amount_msat' ],
1093+ 'constrained' )
1094+ else :
1095+ raise err
0 commit comments