(node_factory)
| 2936 | |
| 2937 | |
| 2938 | def test_sendonion_rpc(node_factory): |
| 2939 | l1, l2, l3, l4 = node_factory.line_graph(4, wait_for_announce=True) |
| 2940 | amt = 10**3 |
| 2941 | route = l1.single_route(l4.info['id'], 10**3) |
| 2942 | inv = l4.rpc.invoice(amt, "lbl", "desc") |
| 2943 | |
| 2944 | first_hop = {'id': route[0]['node_id_out'], 'amount_msat': route[0]['amount_out_msat'], 'delay': route[0]['cltv_out']} |
| 2945 | blockheight = l1.rpc.getinfo()['blockheight'] |
| 2946 | |
| 2947 | # Need to shift the parameters by one hop |
| 2948 | hops = [] |
| 2949 | for h, n in zip(route[:-1], route[1:]): |
| 2950 | # We tell the node h about the parameters to use for n (a.k.a. h + 1) |
| 2951 | hops.append({ |
| 2952 | "pubkey": h['node_id_out'], |
| 2953 | "payload": serialize_payload_tlv(n['amount_out_msat'], n['cltv_out'], n['short_channel_id_dir'].rsplit('/', 1)[0], blockheight).hex() |
| 2954 | }) |
| 2955 | |
| 2956 | # The last hop has a special payload: |
| 2957 | hops.append({ |
| 2958 | "pubkey": route[-1]['node_id_out'], |
| 2959 | "payload": serialize_payload_final_tlv(route[-1]['amount_out_msat'], route[-1]['cltv_out'], route[-1]['amount_out_msat'], blockheight, inv['payment_secret']).hex() |
| 2960 | }) |
| 2961 | |
| 2962 | onion = l1.rpc.createonion(hops=hops, assocdata=inv['payment_hash']) |
| 2963 | |
| 2964 | l1.rpc.sendonion(onion=onion['onion'], first_hop=first_hop, |
| 2965 | payment_hash=inv['payment_hash']) |
| 2966 | |
| 2967 | l1.rpc.waitsendpay(payment_hash=inv['payment_hash']) |
| 2968 | invs = l4.rpc.listinvoices(label="lbl")['invoices'] |
| 2969 | assert(len(invs) == 1 and invs[0]['status'] == 'paid') |
| 2970 | |
| 2971 | pay = only_one(l1.rpc.listsendpays()['payments']) |
| 2972 | assert (pay['status'] == 'complete' |
| 2973 | and pay['payment_hash'] == inv['payment_hash']) |
| 2974 | |
| 2975 | # listsendpays promised that amount would be missing if sendonion didn't |
| 2976 | # specify |
| 2977 | assert 'amount_msat' not in pay |
| 2978 | |
| 2979 | # And now for a failing payment, using a payment_hash that doesn't match an |
| 2980 | # invoice |
| 2981 | payment_hash = "00" * 32 |
| 2982 | onion = l1.rpc.createonion(hops=hops, assocdata=payment_hash) |
| 2983 | l1.rpc.sendonion(onion=onion['onion'], first_hop=first_hop, |
| 2984 | payment_hash=payment_hash, amount_msat=amt) |
| 2985 | |
| 2986 | try: |
| 2987 | l1.rpc.waitsendpay(payment_hash=payment_hash) |
| 2988 | raise ValueError() |
| 2989 | except RpcError as e: |
| 2990 | assert(e.error['code'] == 202) |
| 2991 | assert(e.error['message'] == "Malformed error reply") |
| 2992 | |
| 2993 | pay = only_one(l1.rpc.listsendpays(payment_hash=payment_hash)['payments']) |
| 2994 | assert(pay['status'] == 'failed' |
| 2995 | and pay['payment_hash'] == payment_hash) |
nothing calls this directly
no test coverage detected