Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lightningd/opening_control.c: fundchannel_cancel no longer requires a channel_id argument. #3787

Merged
merged 1 commit into from
Jul 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions common/jsonrpc_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ static const errcode_t FUNDING_BROADCAST_FAIL = 303;
static const errcode_t FUNDING_STILL_SYNCING_BITCOIN = 304;
static const errcode_t FUNDING_PEER_NOT_CONNECTED = 305;
static const errcode_t FUNDING_UNKNOWN_PEER = 306;
static const errcode_t FUNDING_NOTHING_TO_CANCEL = 307;
static const errcode_t FUNDING_CANCEL_NOT_SAFE = 308;

/* `connect` errors */
static const errcode_t CONNECT_NO_KNOWN_ADDRESS = 400;
Expand Down
8 changes: 6 additions & 2 deletions doc/lightning-fundchannel_cancel.7

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion doc/lightning-fundchannel_cancel.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ On error the returned object will contain `code` and `message` properties,
with `code` being one of the following:

- -32602: If the given parameters are wrong.
- -1: Catchall nonspecific error.
- 306: Unknown peer id.
- 307: No channel currently being funded that can be cancelled.
- 308: It is unsafe to cancel the channel: the funding transaction
has been broadcast, or there are HTLCs already in the channel, or
the peer was the initiator and not us.

AUTHOR
------
Expand Down
67 changes: 31 additions & 36 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,8 @@ static void process_check_funding_broadcast(struct bitcoind *bitcoind,

if (txout != NULL) {
for (size_t i = 0; i < tal_count(cancel->forgets); i++)
was_pending(command_fail(cancel->forgets[i], LIGHTNINGD,
was_pending(command_fail(cancel->forgets[i],
FUNDING_CANCEL_NOT_SAFE,
"The funding transaction has been broadcast, "
"please consider `close` or `dev-fail`! "));
tal_free(cancel->forgets);
Expand All @@ -767,47 +768,41 @@ static void process_check_funding_broadcast(struct bitcoind *bitcoind,
}

struct command_result *cancel_channel_before_broadcast(struct command *cmd,
const char *buffer,
struct peer *peer,
const jsmntok_t *cidtok)
struct peer *peer)
{
struct channel *cancel_channel;
struct channel_to_cancel *cc = tal(cmd, struct channel_to_cancel);
struct channel *channel;

cc->peer = peer->id;
if (!cidtok) {
struct channel *channel;

cancel_channel = NULL;
list_for_each(&peer->channels, channel, list) {
if (cancel_channel) {
return command_fail(cmd, LIGHTNINGD,
"Multiple channels:"
" please specify channel_id");
}
cancel_channel = channel;
}
if (!cancel_channel)
return command_fail(cmd, LIGHTNINGD,
"No channels matching that peer_id");
derive_channel_id(&cc->cid,
&cancel_channel->funding_txid,
cancel_channel->funding_outnum);
} else {
if (!json_tok_channel_id(buffer, cidtok, &cc->cid))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid channel_id parameter.");

cancel_channel = find_channel_by_id(peer, &cc->cid);
if (!cancel_channel)
return command_fail(cmd, LIGHTNINGD,
"Channel ID not found: '%.*s'",
cidtok->end - cidtok->start,
buffer + cidtok->start);
cancel_channel = NULL;
list_for_each(&peer->channels, channel, list) {
/* After `fundchannel_complete`, channel is in
* `CHANNELD_AWAITING_LOCKIN` state.
*
* TODO: This assumes only one channel at a time
* can be in this state, which is true at the
* time of this writing, but may change *if* we
* ever implement multiple channels per peer.
*/
if (channel->state != CHANNELD_AWAITING_LOCKIN)
continue;
cancel_channel = channel;
break;
}
if (!cancel_channel)
return command_fail(cmd, FUNDING_NOTHING_TO_CANCEL,
"No channels being opened or "
"awaiting lock-in for "
"peer_id %s",
type_to_string(tmpctx, struct node_id,
&peer->id));
derive_channel_id(&cc->cid,
&cancel_channel->funding_txid,
cancel_channel->funding_outnum);

if (cancel_channel->opener == REMOTE)
return command_fail(cmd, LIGHTNINGD,
return command_fail(cmd, FUNDING_CANCEL_NOT_SAFE,
"Cannot cancel channel that was "
"initiated by peer");

Expand All @@ -817,13 +812,13 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd,
if (wallet_transaction_type(cmd->ld->wallet,
&cancel_channel->funding_txid,
&type))
return command_fail(cmd, LIGHTNINGD,
return command_fail(cmd, FUNDING_CANCEL_NOT_SAFE,
"Has the funding transaction been broadcast? "
"Please use `close` or `dev-fail` instead.");

if (channel_has_htlc_out(cancel_channel) ||
channel_has_htlc_in(cancel_channel)) {
return command_fail(cmd, LIGHTNINGD,
return command_fail(cmd, FUNDING_CANCEL_NOT_SAFE,
"This channel has HTLCs attached and it is "
"not safe to cancel. Has the funding transaction "
"been broadcast? Please use `close` or `dev-fail` "
Expand Down
4 changes: 1 addition & 3 deletions lightningd/channel_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ void channel_notify_new_block(struct lightningd *ld,
/* Cancel the channel after `fundchannel_complete` succeeds
* but before funding broadcasts. */
struct command_result *cancel_channel_before_broadcast(struct command *cmd,
const char *buffer,
struct peer *peer,
const jsmntok_t *cidtok);
struct peer *peer);

/* Forget a channel. Deletes the channel and handles all
* associated waiting commands, if present. Notifies peer if available */
Expand Down
32 changes: 5 additions & 27 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,29 +308,7 @@ static void
cancel_after_fundchannel_complete_success(struct command *cmd,
struct channel *channel)
{
struct peer *peer;
struct channel_id cid;
/* Fake these to adapt to the existing
* cancel_channel_before_broadcast
* interface.
*/
const char *buffer;
jsmntok_t cidtok;

peer = channel->peer;
derive_channel_id(&cid,
&channel->funding_txid, channel->funding_outnum);

buffer = type_to_string(tmpctx, struct channel_id, &cid);
cidtok.type = JSMN_STRING;
cidtok.start = 0;
cidtok.end = strlen(buffer);
cidtok.size = 0;

was_pending(cancel_channel_before_broadcast(cmd,
buffer,
peer,
&cidtok));
was_pending(cancel_channel_before_broadcast(cmd, channel->peer));
}

static void funding_success(struct channel *channel)
Expand Down Expand Up @@ -1150,12 +1128,10 @@ static struct command_result *json_fund_channel_cancel(struct command *cmd,

struct node_id *id;
struct peer *peer;
const jsmntok_t *cidtok;
u8 *msg;

if (!param(cmd, buffer, params,
p_req("id", param_node_id, &id),
p_opt("channel_id", param_tok, &cidtok),
NULL))
return command_param_failed();

Expand All @@ -1166,7 +1142,8 @@ static struct command_result *json_fund_channel_cancel(struct command *cmd,

if (peer->uncommitted_channel) {
if (!peer->uncommitted_channel->fc || !peer->uncommitted_channel->fc->inflight)
return command_fail(cmd, LIGHTNINGD, "No channel funding in progress.");
return command_fail(cmd, FUNDING_NOTHING_TO_CANCEL,
"No channel funding in progress.");

/* Make sure this gets notified if we succeed or cancel */
tal_arr_expand(&peer->uncommitted_channel->fc->cancels, cmd);
Expand All @@ -1175,7 +1152,8 @@ static struct command_result *json_fund_channel_cancel(struct command *cmd,
return command_still_pending(cmd);
}

return cancel_channel_before_broadcast(cmd, buffer, peer, cidtok);
/* Handle `fundchannel_cancel` after `fundchannel_complete`. */
return cancel_channel_before_broadcast(cmd, peer);
}

/**
Expand Down
11 changes: 7 additions & 4 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1163,8 +1163,8 @@ def _fundchannel(l1, l2, amount, close_to):

@unittest.skipIf(TEST_NETWORK != 'regtest', "External wallet support doesn't work with elements yet.")
def test_funding_external_wallet(node_factory, bitcoind):
l1 = node_factory.get_node()
l2 = node_factory.get_node()
l1 = node_factory.get_node(options={'funding-confirms': 2})
l2 = node_factory.get_node(options={'funding-confirms': 2})
l3 = node_factory.get_node()

l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
Expand Down Expand Up @@ -1198,20 +1198,23 @@ def test_funding_external_wallet(node_factory, bitcoind):

assert l1.rpc.fundchannel_complete(l2.info['id'], txid, txout)['commitments_secured']

# Broadcast the transaction manually and confirm that channel locks in
# Broadcast the transaction manually
signed_tx = bitcoind.rpc.signrawtransactionwithwallet(raw_funded_tx)['hex']
assert txid == bitcoind.rpc.decoderawtransaction(signed_tx)['txid']

bitcoind.rpc.sendrawtransaction(signed_tx)
bitcoind.generate_block(1)

l1.daemon.wait_for_log(r'Funding tx {} depth 1 of 1'.format(txid))
l1.daemon.wait_for_log(r'Funding tx {} depth 1 of 2'.format(txid))

# Check that tx is broadcast by a third party can be catched.
# Only when the transaction (broadcast by a third pary) is onchain, we can catch it.
with pytest.raises(RpcError, match=r'.* been broadcast.*'):
l1.rpc.fundchannel_cancel(l2.info['id'])

# Confirm that channel locks in
bitcoind.generate_block(1)

for node in [l1, l2]:
node.daemon.wait_for_log(r'State changed from CHANNELD_AWAITING_LOCKIN to CHANNELD_NORMAL')
channel = node.rpc.listpeers()['peers'][0]['channels'][0]
Expand Down