Browse Source

lightningd: Allow in excess of ctlv_expiry.

We add a test which both overpays and over-sets the delta on the
intermediate and final nodes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
0000dc5908
  1. 4
      lightningd/peer_htlcs.c
  2. 52
      tests/test_lightningd.py

4
lightningd/peer_htlcs.c

@ -243,7 +243,7 @@ static bool check_amount(struct htlc_in *hin,
* * `outgoing_cltv_value` - The CLTV value that the _outgoing_ HTLC carrying
* the packet should have.
*
* cltv_expiry - cltv_expiry_delta = outgoing_cltv_value
* cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value
*
* Inclusion of this field allows a node to both authenticate the information
* specified by the original sender and the parameters of the HTLC forwarded,
@ -259,7 +259,7 @@ static bool check_amount(struct htlc_in *hin,
static bool check_cltv(struct htlc_in *hin,
u32 cltv_expiry, u32 outgoing_cltv_value, u32 delta)
{
if (cltv_expiry - delta == outgoing_cltv_value)
if (cltv_expiry - delta >= outgoing_cltv_value)
return true;
log_debug(hin->key.peer->ld->log, "HTLC %"PRIu64" incorrect CLTV:"
" %u in, %u out, delta reqd %u",

52
tests/test_lightningd.py

@ -1290,6 +1290,58 @@ class LightningDTests(BaseLightningDTests):
.format(bitcoind.rpc.getblockcount() + 9 + shadow_route))
assert l3.rpc.listinvoice('test_forward_different_fees_and_cltv')[0]['complete'] == True
@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:{}'.format(l2.info['port']))
assert ret['id'] == l2.info['id']
l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
ret = l2.rpc.connect(l3.info['id'], 'localhost:{}'.format(l3.info['port']))
assert ret['id'] == l3.info['id']
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
c1 = self.fund_channel(l1, l2, 10**6)
c2 = self.fund_channel(l2, l3, 10**6)
# Allow announce messages.
l1.bitcoin.rpc.generate(5)
# Make sure l1 has seen announce for all channels.
l1.daemon.wait_for_logs([
'Received channel_update for channel {}\\(0\\)'.format(c1),
'Received channel_update for channel {}\\(1\\)'.format(c1),
'Received channel_update for channel {}\\(0\\)'.format(c2),
'Received channel_update for channel {}\\(1\\)'.format(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')['rhash']
l1.rpc.sendpay(to_json(route), rhash)
assert l3.rpc.listinvoice('test_forward_pad_fees_and_cltv')[0]['complete'] == True
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
def test_disconnect(self):
# These should all make us fail, and retry.

Loading…
Cancel
Save