Skip to content

Commit

Permalink
channel control: check that peer is connected before canceling
Browse files Browse the repository at this point in the history
Use the new forget_channel method to cancel, which checks that
peer is still connected before attempting to send message.
  • Loading branch information
niftynei committed Dec 12, 2019
1 parent 2d61fff commit 844de0e
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
8 changes: 2 additions & 6 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,14 +683,10 @@ static void process_check_funding_broadcast(struct bitcoind *bitcoind,
return;
}

const char *error_reason = "Cancel channel by our RPC "
char *error_reason = "Cancel channel by our RPC "
"command before funding "
"transaction broadcast.";
/* Set error so we don't try to reconnect. */
cancel->error = towire_errorfmt(cancel, NULL, "%s", error_reason);

subd_send_msg(cancel->owner,
take(towire_channel_send_error(NULL, error_reason)));
forget_channel(cancel, error_reason);
}

struct command_result *cancel_channel_before_broadcast(struct command *cmd,
Expand Down
25 changes: 23 additions & 2 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -944,8 +944,8 @@ def test_funding_by_utxos(node_factory, bitcoind):


def test_funding_external_wallet_corners(node_factory, bitcoind):
l1 = node_factory.get_node()
l2 = node_factory.get_node()
l1 = node_factory.get_node(may_reconnect=True)
l2 = node_factory.get_node(may_reconnect=True)

amount = 2**24
l1.fundwallet(amount + 10000000)
Expand Down Expand Up @@ -1005,6 +1005,27 @@ def test_funding_external_wallet_corners(node_factory, bitcoind):
# We can cancel channel after fundchannel_complete
assert l1.rpc.fundchannel_cancel(l2.info['id'])['cancelled']

l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
l1.rpc.fundchannel_start(l2.info['id'], amount)['funding_address']
assert l1.rpc.fundchannel_complete(l2.info['id'], prep['txid'], txout)['commitments_secured']

# Check that can still cancel when peer is disconnected
l1.rpc.disconnect(l2.info['id'], force=True)
wait_for(lambda: not only_one(l1.rpc.listpeers()['peers'])['connected'])
assert l1.rpc.fundchannel_cancel(l2.info['id'])['cancelled']
assert len(l1.rpc.listpeers()['peers']) == 0

# l2 still has the channel open/waiting
wait_for(lambda: only_one(only_one(l2.rpc.listpeers()['peers'])['channels'])['state']
== 'CHANNELD_AWAITING_LOCKIN')

# on reconnect, channel should get destroyed
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
l1.daemon.wait_for_log('Rejecting WIRE_CHANNEL_REESTABLISH for unknown channel_id')
wait_for(lambda: len(l1.rpc.listpeers()['peers']) == 0)
wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 0)

# we have to connect again, because we got disconnected when everything errored
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
l1.rpc.fundchannel_start(l2.info['id'], amount)['funding_address']
assert l1.rpc.fundchannel_complete(l2.info['id'], prep['txid'], txout)['commitments_secured']
Expand Down

0 comments on commit 844de0e

Please sign in to comment.