mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-22 08:34:20 +01:00
onchaind: fulfill HTLCs onchain.
When we see an offered HTLC onchain, we need to use the preimage if we know it. So we dump all the known HTLC preimages at startup, and send new ones as we discover them. This doesn't cover preimages we know because we're the final recipient; that can happen if an HTLC hasn't been irrevocably committed yet. We'll do that in a followup patch. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -153,6 +153,8 @@ class BaseLightningDTests(unittest.TestCase):
|
||||
return 1 if errors else 0
|
||||
|
||||
def getCrashLog(self, node):
|
||||
if node.known_fail:
|
||||
return None, None
|
||||
try:
|
||||
crashlog = os.path.join(node.daemon.lightning_dir, 'crash.log')
|
||||
with open(crashlog, 'r') as f:
|
||||
@@ -444,6 +446,66 @@ class LightningDTests(BaseLightningDTests):
|
||||
bitcoind.rpc.generate(100)
|
||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
|
||||
def test_onchain_middleman(self):
|
||||
# HTLC 1->2->3, 1->2 goes down after 2 gets preimage from 3.
|
||||
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
|
||||
l1 = self.node_factory.get_node()
|
||||
l2 = self.node_factory.get_node(disconnect=disconnects)
|
||||
l3 = self.node_factory.get_node()
|
||||
|
||||
# l2 connects to both, so l1 can't reconnect and thus l2 drops to chain
|
||||
l2.rpc.connect('localhost', l1.info['port'], l1.info['id'])
|
||||
l2.rpc.connect('localhost', l3.info['port'], l3.info['id'])
|
||||
self.fund_channel(l2, l1, 10**6)
|
||||
self.fund_channel(l2, l3, 10**6)
|
||||
|
||||
# Give l1 some money to play with.
|
||||
self.pay(l2, l1, 2 * 10**8)
|
||||
|
||||
# Must be bigger than dust!
|
||||
rhash = l3.rpc.invoice(10**8, 'middleman')['rhash']
|
||||
# Wait for route propagation.
|
||||
l1.bitcoin.rpc.generate(5)
|
||||
l1.daemon.wait_for_log('Received node_announcement for node {}'
|
||||
.format(l3.info['id']))
|
||||
|
||||
route = l1.rpc.getroute(l3.info['id'], 10**8, 1)["route"]
|
||||
assert len(route) == 2
|
||||
|
||||
def try_pay():
|
||||
l1.rpc.sendpay(to_json(route), rhash, async=False)
|
||||
|
||||
t = threading.Thread(target=try_pay)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
# l2 will drop to chain.
|
||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||
l1.bitcoin.rpc.generate(1)
|
||||
l2.daemon.wait_for_log('-> ONCHAIND_OUR_UNILATERAL')
|
||||
l1.daemon.wait_for_log('-> ONCHAIND_THEIR_UNILATERAL')
|
||||
l2.daemon.wait_for_log('OUR_UNILATERAL/THEIR_HTLC')
|
||||
|
||||
# l2 should fulfill HTLC onchain
|
||||
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks')
|
||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||
|
||||
l1.bitcoin.rpc.generate(1)
|
||||
# FIXME: l1 should get preimage off the chain!
|
||||
l1.daemon.wait_for_log('FIXME: handle_htlc_onchain_fulfill')
|
||||
l1.has_failed()
|
||||
|
||||
# After 5 more blocks, l2 can spend to-us
|
||||
l1.bitcoin.rpc.generate(5)
|
||||
l2.daemon.wait_for_log('Broadcasting OUR_UNILATERAL_TO_US_RETURN_TO_WALLET')
|
||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||
|
||||
# 100 blocks after last spend, l2 should be done.
|
||||
l1.bitcoin.rpc.generate(100)
|
||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
|
||||
# FIXME: kill thread?
|
||||
|
||||
def test_permfail_new_commit(self):
|
||||
# Test case where we have two possible commits: it will use new one.
|
||||
disconnects = ['-WIRE_REVOKE_AND_ACK', 'permfail']
|
||||
@@ -504,14 +566,15 @@ class LightningDTests(BaseLightningDTests):
|
||||
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) in 5 blocks')
|
||||
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) in 5 blocks')
|
||||
|
||||
# FIXME: Implement FULFILL!
|
||||
|
||||
# OK, time out HTLC.
|
||||
bitcoind.rpc.generate(5)
|
||||
l1.daemon.wait_for_log('sendrawtx exit 0')
|
||||
l1.daemon.wait_for_log('FIXME: handle_htlc_onchain_fulfill')
|
||||
l1.has_failed()
|
||||
|
||||
# l1.daemon.wait_for_log('sendrawtx exit 0')
|
||||
bitcoind.rpc.generate(1)
|
||||
l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
|
||||
l2.daemon.wait_for_log('Ignoring output.*: OUR_UNILATERAL/THEIR_HTLC')
|
||||
# l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
|
||||
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks')
|
||||
|
||||
# FIXME: This doesn't work :(
|
||||
# FIXME: sendpay command should time out!
|
||||
@@ -519,7 +582,7 @@ class LightningDTests(BaseLightningDTests):
|
||||
|
||||
# Now, 100 blocks it should be done.
|
||||
bitcoind.rpc.generate(100)
|
||||
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
# l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
|
||||
def test_permfail_htlc_out(self):
|
||||
@@ -543,14 +606,15 @@ class LightningDTests(BaseLightningDTests):
|
||||
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US \\(.*\\) in 5 blocks')
|
||||
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) in 5 blocks')
|
||||
|
||||
# FIXME: Implement FULFILL!
|
||||
|
||||
# OK, time out HTLC.
|
||||
bitcoind.rpc.generate(5)
|
||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||
|
||||
l2.daemon.wait_for_log('FIXME: handle_htlc_onchain_fulfill')
|
||||
l2.has_failed()
|
||||
|
||||
bitcoind.rpc.generate(1)
|
||||
l1.daemon.wait_for_log('Ignoring output.*: THEIR_UNILATERAL/THEIR_HTLC')
|
||||
l2.daemon.wait_for_log('Resolved OUR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
|
||||
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_FULFILL_TO_US .* in 0 blocks')
|
||||
# l2.daemon.wait_for_log('Resolved OUR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
|
||||
|
||||
# FIXME: This doesn't work :(
|
||||
# FIXME: sendpay command should time out!
|
||||
@@ -559,7 +623,7 @@ class LightningDTests(BaseLightningDTests):
|
||||
# Now, 100 blocks it should be done.
|
||||
bitcoind.rpc.generate(100)
|
||||
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
# l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||
|
||||
def test_gossip_jsonrpc(self):
|
||||
l1,l2 = self.connect()
|
||||
|
||||
Reference in New Issue
Block a user