mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-01 17:47:30 +01:00
pytest: Move forwarded payments to test_pay.py
This commit is contained in:
parent
58709cf190
commit
13d9f30a6a
2 changed files with 246 additions and 244 deletions
|
@ -367,249 +367,6 @@ class LightningDTests(BaseLightningDTests):
|
|||
l1.daemon.wait_for_log('Got pong 1000 bytes \({}\.\.\.\)'
|
||||
.format(l2.info['version']))
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "Too slow without --dev-bitcoind-poll")
|
||||
def test_forward(self):
|
||||
# Connect 1 -> 2 -> 3.
|
||||
l1, l2 = self.connect()
|
||||
l3 = self.node_factory.get_node()
|
||||
ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
|
||||
|
||||
assert ret['id'] == l3.info['id']
|
||||
|
||||
l3.daemon.wait_for_log('Handing back peer .* to master')
|
||||
self.fund_channel(l1, l2, 10**6)
|
||||
self.fund_channel(l2, l3, 10**6)
|
||||
|
||||
# Allow announce messages.
|
||||
l1.bitcoin.generate_block(5)
|
||||
|
||||
# If they're at different block heights we can get spurious errors.
|
||||
sync_blockheight([l1, l2, l3])
|
||||
|
||||
chanid1 = only_one(l1.rpc.getpeer(l2.info['id'])['channels'])['short_channel_id']
|
||||
chanid2 = only_one(l2.rpc.getpeer(l3.info['id'])['channels'])['short_channel_id']
|
||||
assert only_one(l2.rpc.getpeer(l1.info['id'])['channels'])['short_channel_id'] == chanid1
|
||||
assert only_one(l3.rpc.getpeer(l2.info['id'])['channels'])['short_channel_id'] == chanid2
|
||||
|
||||
rhash = l3.rpc.invoice(100000000, 'testpayment1', 'desc')['payment_hash']
|
||||
assert only_one(l3.rpc.listinvoices('testpayment1')['invoices'])['status'] == 'unpaid'
|
||||
|
||||
# Fee for node2 is 10 millionths, plus 1.
|
||||
amt = 100000000
|
||||
fee = amt * 10 // 1000000 + 1
|
||||
|
||||
baseroute = [{'msatoshi': amt + fee,
|
||||
'id': l2.info['id'],
|
||||
'delay': 12,
|
||||
'channel': chanid1},
|
||||
{'msatoshi': amt,
|
||||
'id': l3.info['id'],
|
||||
'delay': 6,
|
||||
'channel': chanid2}]
|
||||
|
||||
# Unknown other peer
|
||||
route = copy.deepcopy(baseroute)
|
||||
route[1]['id'] = '031a8dc444e41bb989653a4501e11175a488a57439b0c4947704fd6e3de5dca607'
|
||||
l1.rpc.sendpay(to_json(route), rhash)
|
||||
self.assertRaises(RpcError, l1.rpc.waitsendpay, rhash)
|
||||
|
||||
# Delay too short (we always add one internally anyway, so subtract 2 here).
|
||||
route = copy.deepcopy(baseroute)
|
||||
route[0]['delay'] = 8
|
||||
l1.rpc.sendpay(to_json(route), rhash)
|
||||
self.assertRaises(RpcError, l1.rpc.waitsendpay, rhash)
|
||||
|
||||
# Final delay too short
|
||||
route = copy.deepcopy(baseroute)
|
||||
route[1]['delay'] = 3
|
||||
l1.rpc.sendpay(to_json(route), rhash)
|
||||
self.assertRaises(RpcError, l1.rpc.waitsendpay, rhash)
|
||||
|
||||
# This one works
|
||||
route = copy.deepcopy(baseroute)
|
||||
l1.rpc.sendpay(to_json(route), rhash)
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for --dev-broadcast-interval")
|
||||
def test_forward_different_fees_and_cltv(self):
|
||||
# FIXME: Check BOLT quotes here too
|
||||
# BOLT #7:
|
||||
# ```
|
||||
# B
|
||||
# / \
|
||||
# / \
|
||||
# A C
|
||||
# \ /
|
||||
# \ /
|
||||
# D
|
||||
# ```
|
||||
#
|
||||
# Each advertises the following `cltv_expiry_delta` on its end of every
|
||||
# channel:
|
||||
#
|
||||
# 1. A: 10 blocks
|
||||
# 2. B: 20 blocks
|
||||
# 3. C: 30 blocks
|
||||
# 4. D: 40 blocks
|
||||
#
|
||||
# C also uses a minimum `cltv_expiry` of 9 (the default) when requesting
|
||||
# payments.
|
||||
#
|
||||
# Also, each node has the same fee scheme which it uses for each of its
|
||||
# channels:
|
||||
#
|
||||
# 1. A: 100 base + 1000 millionths
|
||||
# 1. B: 200 base + 2000 millionths
|
||||
# 1. C: 300 base + 3000 millionths
|
||||
# 1. D: 400 base + 4000 millionths
|
||||
|
||||
# We don't do D yet.
|
||||
l1 = self.node_factory.get_node(options={'cltv-delta': 10, 'fee-base': 100, 'fee-per-satoshi': 1000})
|
||||
l2 = self.node_factory.get_node(options={'cltv-delta': 20, 'fee-base': 200, 'fee-per-satoshi': 2000})
|
||||
l3 = self.node_factory.get_node(options={'cltv-delta': 30, 'cltv-final': 9, 'fee-base': 300, 'fee-per-satoshi': 3000})
|
||||
|
||||
ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
|
||||
assert ret['id'] == l2.info['id']
|
||||
|
||||
l1.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
|
||||
assert ret['id'] == l3.info['id']
|
||||
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l3.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
c1 = self.fund_channel(l1, l2, 10**6)
|
||||
c2 = self.fund_channel(l2, l3, 10**6)
|
||||
|
||||
# Make sure l1 has seen announce for all channels.
|
||||
self.wait_for_routes(l1, [c1, c2])
|
||||
|
||||
# BOLT #7:
|
||||
#
|
||||
# If B were to send 4,999,999 millisatoshi directly to C, it wouldn't
|
||||
# charge itself a fee nor add its own `cltv_expiry_delta`, so it would
|
||||
# use C's requested `cltv_expiry` of 9. We also assume it adds a
|
||||
# "shadow route" to give an extra CLTV of 42. It could also add extra
|
||||
# cltv deltas at other hops, as these values are a minimum, but we don't
|
||||
# here for simplicity:
|
||||
|
||||
# FIXME: Add shadow route
|
||||
shadow_route = 0
|
||||
route = l2.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
||||
assert len(route) == 1
|
||||
|
||||
# BOLT #7:
|
||||
#
|
||||
# * `amount_msat`: 4999999
|
||||
# * `cltv_expiry`: current-block-height + 9 + 42
|
||||
# * `onion_routing_packet`:
|
||||
# * `amt_to_forward` = 4999999
|
||||
# * `outgoing_cltv_value` = current-block-height + 9 + 42
|
||||
#
|
||||
assert route[0]['msatoshi'] == 4999999
|
||||
assert route[0]['delay'] == 9 + shadow_route
|
||||
|
||||
# BOLT #7:
|
||||
# If A were to send 4,999,999 millisatoshi to C via B, it needs to
|
||||
# pay B the fee it specified in the B->C `channel_update`, calculated as
|
||||
# per [HTLC Fees](#htlc_fees):
|
||||
#
|
||||
# 200 + 4999999 * 2000 / 1000000 = 10199
|
||||
#
|
||||
# Similarly, it would need to add the `cltv_expiry` from B->C's
|
||||
# `channel_update` (20), plus C's requested minimum (9), plus 42 for the
|
||||
# "shadow route". Thus the `update_add_htlc` message from A to B would
|
||||
# be:
|
||||
#
|
||||
# * `amount_msat`: 5010198
|
||||
# * `cltv_expiry`: current-block-height + 20 + 9 + 42
|
||||
# * `onion_routing_packet`:
|
||||
# * `amt_to_forward` = 4999999
|
||||
# * `outgoing_cltv_value` = current-block-height + 9 + 42
|
||||
route = l1.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
||||
assert len(route) == 2
|
||||
|
||||
assert route[0]['msatoshi'] == 5010198
|
||||
assert route[0]['delay'] == 20 + 9 + shadow_route
|
||||
assert route[1]['msatoshi'] == 4999999
|
||||
assert route[1]['delay'] == 9 + shadow_route
|
||||
|
||||
rhash = l3.rpc.invoice(4999999, 'test_forward_different_fees_and_cltv', 'desc')['payment_hash']
|
||||
assert only_one(l3.rpc.listinvoices('test_forward_different_fees_and_cltv')['invoices'])['status'] == 'unpaid'
|
||||
|
||||
# This should work.
|
||||
l1.rpc.sendpay(to_json(route), rhash)
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
|
||||
# We add one to the blockcount for a bit of fuzz (FIXME: Shadowroute would fix this!)
|
||||
shadow_route = 1
|
||||
l1.daemon.wait_for_log("Adding HTLC 0 msat=5010198 cltv={} gave CHANNEL_ERR_ADD_OK"
|
||||
.format(bitcoind.rpc.getblockcount() + 20 + 9 + shadow_route))
|
||||
l2.daemon.wait_for_log("Adding HTLC 0 msat=4999999 cltv={} gave CHANNEL_ERR_ADD_OK"
|
||||
.format(bitcoind.rpc.getblockcount() + 9 + shadow_route))
|
||||
l3.daemon.wait_for_log("test_forward_different_fees_and_cltv: Actual amount 4999999msat, HTLC expiry {}"
|
||||
.format(bitcoind.rpc.getblockcount() + 9 + shadow_route))
|
||||
assert only_one(l3.rpc.listinvoices('test_forward_different_fees_and_cltv')['invoices'])['status'] == 'paid'
|
||||
|
||||
# Check that we see all the channels
|
||||
shortids = set(c['short_channel_id'] for c in l2.rpc.listchannels()['channels'])
|
||||
for scid in shortids:
|
||||
c = l1.rpc.listchannels(scid)['channels']
|
||||
# We get one entry for each direction.
|
||||
assert len(c) == 2
|
||||
assert c[0]['short_channel_id'] == scid
|
||||
assert c[1]['short_channel_id'] == scid
|
||||
assert c[0]['source'] == c[1]['destination']
|
||||
assert c[1]['source'] == c[0]['destination']
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for --dev-broadcast-interval")
|
||||
def test_forward_pad_fees_and_cltv(self):
|
||||
"""Test that we are allowed extra locktime delta, and fees"""
|
||||
|
||||
l1 = self.node_factory.get_node(options={'cltv-delta': 10, 'fee-base': 100, 'fee-per-satoshi': 1000})
|
||||
l2 = self.node_factory.get_node(options={'cltv-delta': 20, 'fee-base': 200, 'fee-per-satoshi': 2000})
|
||||
l3 = self.node_factory.get_node(options={'cltv-delta': 30, 'cltv-final': 9, 'fee-base': 300, 'fee-per-satoshi': 3000})
|
||||
|
||||
ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
|
||||
assert ret['id'] == l2.info['id']
|
||||
|
||||
l1.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
|
||||
assert ret['id'] == l3.info['id']
|
||||
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l3.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
c1 = self.fund_channel(l1, l2, 10**6)
|
||||
c2 = self.fund_channel(l2, l3, 10**6)
|
||||
|
||||
# Make sure l1 has seen announce for all channels.
|
||||
self.wait_for_routes(l1, [c1, c2])
|
||||
|
||||
route = l1.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
||||
assert len(route) == 2
|
||||
|
||||
assert route[0]['msatoshi'] == 5010198
|
||||
assert route[0]['delay'] == 20 + 9
|
||||
assert route[1]['msatoshi'] == 4999999
|
||||
assert route[1]['delay'] == 9
|
||||
|
||||
# Modify so we overpay, overdo the cltv.
|
||||
route[0]['msatoshi'] += 2000
|
||||
route[0]['delay'] += 20
|
||||
route[1]['msatoshi'] += 1000
|
||||
route[1]['delay'] += 10
|
||||
|
||||
# This should work.
|
||||
rhash = l3.rpc.invoice(4999999, 'test_forward_pad_fees_and_cltv', 'desc')['payment_hash']
|
||||
l1.rpc.sendpay(to_json(route), rhash)
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
assert only_one(l3.rpc.listinvoices('test_forward_pad_fees_and_cltv')['invoices'])['status'] == 'paid'
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for --dev-broadcast-interval")
|
||||
def test_htlc_sig_persistence(self):
|
||||
"""Interrupt a payment between two peers, then fail and recover funds using the HTLC sig.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from fixtures import * # noqa: F401,F403
|
||||
from lightning import RpcError
|
||||
from utils import DEVELOPER, wait_for
|
||||
from utils import DEVELOPER, wait_for, only_one, sync_blockheight
|
||||
|
||||
|
||||
import copy
|
||||
|
@ -724,3 +724,248 @@ def test_decodepay(node_factory):
|
|||
|
||||
with pytest.raises(RpcError):
|
||||
l1.rpc.decodepay('1111111')
|
||||
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "Too slow without --dev-bitcoind-poll")
|
||||
def test_forward(node_factory, bitcoind):
|
||||
# Connect 1 -> 2 -> 3.
|
||||
l1, l2, l3 = node_factory.line_graph(3, fundchannel=True)
|
||||
|
||||
# Allow announce messages.
|
||||
l1.bitcoin.generate_block(5)
|
||||
|
||||
# If they're at different block heights we can get spurious errors.
|
||||
sync_blockheight(bitcoind, [l1, l2, l3])
|
||||
|
||||
chanid1 = only_one(l1.rpc.getpeer(l2.info['id'])['channels'])['short_channel_id']
|
||||
chanid2 = only_one(l2.rpc.getpeer(l3.info['id'])['channels'])['short_channel_id']
|
||||
assert only_one(l2.rpc.getpeer(l1.info['id'])['channels'])['short_channel_id'] == chanid1
|
||||
assert only_one(l3.rpc.getpeer(l2.info['id'])['channels'])['short_channel_id'] == chanid2
|
||||
|
||||
rhash = l3.rpc.invoice(100000000, 'testpayment1', 'desc')['payment_hash']
|
||||
assert only_one(l3.rpc.listinvoices('testpayment1')['invoices'])['status'] == 'unpaid'
|
||||
|
||||
# Fee for node2 is 10 millionths, plus 1.
|
||||
amt = 100000000
|
||||
fee = amt * 10 // 1000000 + 1
|
||||
|
||||
baseroute = [{'msatoshi': amt + fee,
|
||||
'id': l2.info['id'],
|
||||
'delay': 12,
|
||||
'channel': chanid1},
|
||||
{'msatoshi': amt,
|
||||
'id': l3.info['id'],
|
||||
'delay': 6,
|
||||
'channel': chanid2}]
|
||||
|
||||
# Unknown other peer
|
||||
route = copy.deepcopy(baseroute)
|
||||
route[1]['id'] = '031a8dc444e41bb989653a4501e11175a488a57439b0c4947704fd6e3de5dca607'
|
||||
l1.rpc.sendpay(route, rhash)
|
||||
with pytest.raises(RpcError):
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
|
||||
# Delay too short (we always add one internally anyway, so subtract 2 here).
|
||||
route = copy.deepcopy(baseroute)
|
||||
route[0]['delay'] = 8
|
||||
l1.rpc.sendpay(route, rhash)
|
||||
with pytest.raises(RpcError):
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
|
||||
# Final delay too short
|
||||
route = copy.deepcopy(baseroute)
|
||||
route[1]['delay'] = 3
|
||||
l1.rpc.sendpay(route, rhash)
|
||||
with pytest.raises(RpcError):
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
|
||||
# This one works
|
||||
route = copy.deepcopy(baseroute)
|
||||
l1.rpc.sendpay(route, rhash)
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for --dev-broadcast-interval")
|
||||
def test_forward_different_fees_and_cltv(node_factory, bitcoind):
|
||||
# FIXME: Check BOLT quotes here too
|
||||
# BOLT #7:
|
||||
# ```
|
||||
# B
|
||||
# / \
|
||||
# / \
|
||||
# A C
|
||||
# \ /
|
||||
# \ /
|
||||
# D
|
||||
# ```
|
||||
#
|
||||
# Each advertises the following `cltv_expiry_delta` on its end of every
|
||||
# channel:
|
||||
#
|
||||
# 1. A: 10 blocks
|
||||
# 2. B: 20 blocks
|
||||
# 3. C: 30 blocks
|
||||
# 4. D: 40 blocks
|
||||
#
|
||||
# C also uses a minimum `cltv_expiry` of 9 (the default) when requesting
|
||||
# payments.
|
||||
#
|
||||
# Also, each node has the same fee scheme which it uses for each of its
|
||||
# channels:
|
||||
#
|
||||
# 1. A: 100 base + 1000 millionths
|
||||
# 1. B: 200 base + 2000 millionths
|
||||
# 1. C: 300 base + 3000 millionths
|
||||
# 1. D: 400 base + 4000 millionths
|
||||
|
||||
# We don't do D yet.
|
||||
l1 = node_factory.get_node(options={'cltv-delta': 10, 'fee-base': 100, 'fee-per-satoshi': 1000})
|
||||
l2 = node_factory.get_node(options={'cltv-delta': 20, 'fee-base': 200, 'fee-per-satoshi': 2000})
|
||||
l3 = node_factory.get_node(options={'cltv-delta': 30, 'cltv-final': 9, 'fee-base': 300, 'fee-per-satoshi': 3000})
|
||||
|
||||
ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
|
||||
assert ret['id'] == l2.info['id']
|
||||
|
||||
l1.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
|
||||
assert ret['id'] == l3.info['id']
|
||||
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l3.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
c1 = l1.fund_channel(l2, 10**6)
|
||||
c2 = l2.fund_channel(l3, 10**6)
|
||||
bitcoind.generate_block(5)
|
||||
|
||||
# Make sure l1 has seen announce for all channels.
|
||||
l1.wait_channel_active(c1)
|
||||
l1.wait_channel_active(c2)
|
||||
|
||||
# BOLT #7:
|
||||
#
|
||||
# If B were to send 4,999,999 millisatoshi directly to C, it wouldn't
|
||||
# charge itself a fee nor add its own `cltv_expiry_delta`, so it would
|
||||
# use C's requested `cltv_expiry` of 9. We also assume it adds a
|
||||
# "shadow route" to give an extra CLTV of 42. It could also add extra
|
||||
# cltv deltas at other hops, as these values are a minimum, but we don't
|
||||
# here for simplicity:
|
||||
|
||||
# FIXME: Add shadow route
|
||||
shadow_route = 0
|
||||
route = l2.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
||||
assert len(route) == 1
|
||||
|
||||
# BOLT #7:
|
||||
#
|
||||
# * `amount_msat`: 4999999
|
||||
# * `cltv_expiry`: current-block-height + 9 + 42
|
||||
# * `onion_routing_packet`:
|
||||
# * `amt_to_forward` = 4999999
|
||||
# * `outgoing_cltv_value` = current-block-height + 9 + 42
|
||||
#
|
||||
assert route[0]['msatoshi'] == 4999999
|
||||
assert route[0]['delay'] == 9 + shadow_route
|
||||
|
||||
# BOLT #7:
|
||||
# If A were to send 4,999,999 millisatoshi to C via B, it needs to
|
||||
# pay B the fee it specified in the B->C `channel_update`, calculated as
|
||||
# per [HTLC Fees](#htlc_fees):
|
||||
#
|
||||
# 200 + 4999999 * 2000 / 1000000 = 10199
|
||||
#
|
||||
# Similarly, it would need to add the `cltv_expiry` from B->C's
|
||||
# `channel_update` (20), plus C's requested minimum (9), plus 42 for the
|
||||
# "shadow route". Thus the `update_add_htlc` message from A to B would
|
||||
# be:
|
||||
#
|
||||
# * `amount_msat`: 5010198
|
||||
# * `cltv_expiry`: current-block-height + 20 + 9 + 42
|
||||
# * `onion_routing_packet`:
|
||||
# * `amt_to_forward` = 4999999
|
||||
# * `outgoing_cltv_value` = current-block-height + 9 + 42
|
||||
route = l1.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
||||
assert len(route) == 2
|
||||
|
||||
assert route[0]['msatoshi'] == 5010198
|
||||
assert route[0]['delay'] == 20 + 9 + shadow_route
|
||||
assert route[1]['msatoshi'] == 4999999
|
||||
assert route[1]['delay'] == 9 + shadow_route
|
||||
|
||||
rhash = l3.rpc.invoice(4999999, 'test_forward_different_fees_and_cltv', 'desc')['payment_hash']
|
||||
assert only_one(l3.rpc.listinvoices('test_forward_different_fees_and_cltv')['invoices'])['status'] == 'unpaid'
|
||||
|
||||
# This should work.
|
||||
l1.rpc.sendpay(route, rhash)
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
|
||||
# We add one to the blockcount for a bit of fuzz (FIXME: Shadowroute would fix this!)
|
||||
shadow_route = 1
|
||||
l1.daemon.wait_for_log("Adding HTLC 0 msat=5010198 cltv={} gave CHANNEL_ERR_ADD_OK"
|
||||
.format(bitcoind.rpc.getblockcount() + 20 + 9 + shadow_route))
|
||||
l2.daemon.wait_for_log("Adding HTLC 0 msat=4999999 cltv={} gave CHANNEL_ERR_ADD_OK"
|
||||
.format(bitcoind.rpc.getblockcount() + 9 + shadow_route))
|
||||
l3.daemon.wait_for_log("test_forward_different_fees_and_cltv: Actual amount 4999999msat, HTLC expiry {}"
|
||||
.format(bitcoind.rpc.getblockcount() + 9 + shadow_route))
|
||||
assert only_one(l3.rpc.listinvoices('test_forward_different_fees_and_cltv')['invoices'])['status'] == 'paid'
|
||||
|
||||
# Check that we see all the channels
|
||||
shortids = set(c['short_channel_id'] for c in l2.rpc.listchannels()['channels'])
|
||||
for scid in shortids:
|
||||
c = l1.rpc.listchannels(scid)['channels']
|
||||
# We get one entry for each direction.
|
||||
assert len(c) == 2
|
||||
assert c[0]['short_channel_id'] == scid
|
||||
assert c[1]['short_channel_id'] == scid
|
||||
assert c[0]['source'] == c[1]['destination']
|
||||
assert c[1]['source'] == c[0]['destination']
|
||||
|
||||
|
||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for --dev-broadcast-interval")
|
||||
def test_forward_pad_fees_and_cltv(node_factory, bitcoind):
|
||||
"""Test that we are allowed extra locktime delta, and fees"""
|
||||
|
||||
l1 = node_factory.get_node(options={'cltv-delta': 10, 'fee-base': 100, 'fee-per-satoshi': 1000})
|
||||
l2 = node_factory.get_node(options={'cltv-delta': 20, 'fee-base': 200, 'fee-per-satoshi': 2000})
|
||||
l3 = node_factory.get_node(options={'cltv-delta': 30, 'cltv-final': 9, 'fee-base': 300, 'fee-per-satoshi': 3000})
|
||||
|
||||
ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
|
||||
assert ret['id'] == l2.info['id']
|
||||
|
||||
l1.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
|
||||
assert ret['id'] == l3.info['id']
|
||||
|
||||
l2.daemon.wait_for_log('Handing back peer .* to master')
|
||||
l3.daemon.wait_for_log('Handing back peer .* to master')
|
||||
|
||||
c1 = l1.fund_channel(l2, 10**6)
|
||||
c2 = l2.fund_channel(l3, 10**6)
|
||||
bitcoind.generate_block(5)
|
||||
|
||||
# Make sure l1 has seen announce for all channels.
|
||||
l1.wait_channel_active(c1)
|
||||
l1.wait_channel_active(c2)
|
||||
|
||||
route = l1.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
||||
assert len(route) == 2
|
||||
|
||||
assert route[0]['msatoshi'] == 5010198
|
||||
assert route[0]['delay'] == 20 + 9
|
||||
assert route[1]['msatoshi'] == 4999999
|
||||
assert route[1]['delay'] == 9
|
||||
|
||||
# Modify so we overpay, overdo the cltv.
|
||||
route[0]['msatoshi'] += 2000
|
||||
route[0]['delay'] += 20
|
||||
route[1]['msatoshi'] += 1000
|
||||
route[1]['delay'] += 10
|
||||
|
||||
# This should work.
|
||||
rhash = l3.rpc.invoice(4999999, 'test_forward_pad_fees_and_cltv', 'desc')['payment_hash']
|
||||
l1.rpc.sendpay(route, rhash)
|
||||
l1.rpc.waitsendpay(rhash)
|
||||
assert only_one(l3.rpc.listinvoices('test_forward_pad_fees_and_cltv')['invoices'])['status'] == 'paid'
|
||||
|
|
Loading…
Add table
Reference in a new issue