Skip to content
Open
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
66 changes: 46 additions & 20 deletions openingd/dualopend.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,32 @@ static void handle_failure_fatal(struct state *state, u8 *msg)
open_err_fatal(state, "%s", err);
}

static bool check_accepter_error(struct state *state,
u8 *msg,
char *err_reason)
{
if (!msg) {
if (err_reason)
negotiation_failed(state, "%s", err_reason);
else
/* FIXME: what do we do here?? */
return false;
}

/* `msg` could be a failure message */
if (fromwire_peektype(msg) == WIRE_DUALOPEND_FAIL) {
handle_failure_fatal(state, msg);
return false;
}

if (fromwire_peektype(msg) != WIRE_DUALOPEND_SEND_TX_SIGS) {
master_badmsg(WIRE_DUALOPEND_SEND_TX_SIGS, msg);
return false;
}

return true;
}

static void check_channel_id(struct state *state,
struct channel_id *id_in,
struct channel_id *orig_id)
Expand Down Expand Up @@ -2305,9 +2331,6 @@ static u8 *accepter_commits(struct state *state,
wire_sync_write(REQ_FD, take(msg));
msg = wire_sync_read(tmpctx, REQ_FD);

if (fromwire_peektype(msg) != WIRE_DUALOPEND_SEND_TX_SIGS)
master_badmsg(WIRE_DUALOPEND_SEND_TX_SIGS, msg);

return msg;
}

Expand Down Expand Up @@ -2751,11 +2774,8 @@ static void accepter_start(struct state *state, const u8 *oc2_msg)
}

msg = accepter_commits(state, tx_state, total, &err_reason);
if (!msg) {
if (err_reason)
negotiation_failed(state, "%s", err_reason);
return;
}
if (!check_accepter_error(state, msg, err_reason))
return;

/* Finally, send our funding tx sigs */
handle_send_tx_sigs(state, msg);
Expand Down Expand Up @@ -3462,19 +3482,25 @@ static void rbf_wrap_up(struct state *state,
else
msg = opener_commits(state, tx_state, total, &err_reason);

if (!msg) {
if (err_reason)
open_abort(state, "%s", err_reason);
else
open_abort(state, "%s", "Unable to commit");
/* We need to 'reset' the channel to what it
* was before we did this. */
return;
}

if (state->our_role == TX_ACCEPTER)
/* in TX_ACCEPTER case, `msg` could be a failure message */
if (msg && (fromwire_peektype(msg) == WIRE_DUALOPEND_FAIL)) {
if (fromwire_dualopend_fail(msg, msg, &err_reason))
msg = tal_free(msg);
}

if (!msg) {
if (err_reason)
open_abort(state, "%s", err_reason);
else
open_abort(state, "%s", "Unable to commit");
/* We need to 'reset' the channel to what it
* was before we did this. */
return;
}

if (state->our_role == TX_ACCEPTER) {
handle_send_tx_sigs(state, msg);
else
} else
wire_sync_write(REQ_FD, take(msg));
}

Expand Down
41 changes: 0 additions & 41 deletions plugins/funder.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,6 @@ static struct command_result *unreserve_psbt(struct command *cmd,
return command_still_pending(aux);
}

static void cleanup_peer_pending_opens(struct command *cmd,
const struct node_id *id)
{
struct pending_open *i, *next;
list_for_each_safe(&pending_opens, i, next, list) {
if (node_id_eq(&i->peer_id, id)) {
unreserve_psbt(cmd, i);
}
}
}

static struct command_result *
command_hook_cont_psbt(struct command *cmd, struct wally_psbt *psbt)
{
Expand Down Expand Up @@ -1086,32 +1075,6 @@ json_rbf_channel_call(struct command *cmd,
return send_outreq(req);
}

static struct command_result *json_disconnect(struct command *cmd,
const char *buf,
const jsmntok_t *params)
{
struct node_id id;
const char *err;

err = json_scan(tmpctx, buf, params,
"{disconnect:{id:%}}",
JSON_SCAN(json_to_node_id, &id));
if (err)
plugin_err(cmd->plugin,
"`disconnect` notification payload did not"
" scan %s: %.*s",
err, json_tok_full_len(params),
json_tok_full(buf, params));

plugin_log(cmd->plugin, LOG_DBG,
"Cleaning up inflights for peer id %s",
fmt_node_id(tmpctx, &id));

cleanup_peer_pending_opens(cmd, &id);

return notification_handled(cmd);
}

static struct command_result *
delete_channel_from_datastore(struct command *cmd,
struct channel_id *cid)
Expand Down Expand Up @@ -1552,10 +1515,6 @@ const struct plugin_notification notifs[] = {
"channel_open_failed",
json_channel_open_failed,
},
{
"disconnect",
json_disconnect,
},
{
"channel_state_changed",
json_channel_state_changed,
Expand Down
39 changes: 38 additions & 1 deletion tests/test_opening.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from fixtures import TEST_NETWORK
from pyln.client import RpcError, Millisatoshi
from utils import (
only_one, wait_for, sync_blockheight, first_channel_id, calc_lease_fee, check_coin_moves
TIMEOUT, only_one, wait_for, sync_blockheight, first_channel_id, calc_lease_fee, check_coin_moves
)
from pyln.testing.utils import FUNDAMOUNT

Expand Down Expand Up @@ -3089,3 +3089,40 @@ def test_no_retransmit_confirmed_funding(node_factory):
# Should not have attempted (and failed) to re-broadcast the funding tx.
assert not l1.daemon.is_in_log('Failed to re-transmit funding tx')
assert not l1.daemon.is_in_log('Successfully rexmitted funding tx')


@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
@pytest.mark.openchannel('v2')
def test_inflight_disconnect_commitment_v2(node_factory, bitcoind):
"""Disconnect during dual-fund commitment signing should not trigger spurious BROKEN messages.
"""
disconnects = ["+WIRE_COMMITMENT_SIGNED"]

opts = [{'experimental-dual-fund': None, 'dev-no-reconnect': None,
'may_reconnect': True, 'disconnect': disconnects},
{'experimental-dual-fund': None, 'dev-no-reconnect': None,
'may_reconnect': True}]

opener, funder = node_factory.get_nodes(2, opts=opts)

feerate = 2000
amount = 500000
opener.fundwallet(20000000)
funder.fundwallet(20000000)

funder.rpc.call('funderupdate',
{'policy': 'available',
'policy_mod': 100,
'per_channel_max_msat': '1btc',
'reserve_tank_msat': '0msat',
'fund_probability': 100,
'fuzz_percent': 0,
'leases_only': False})

opener.rpc.connect(funder.info['id'], 'localhost', funder.port)
fut = node_factory.executor.submit(opener.rpc.fundchannel,
funder.info['id'], amount)

opener.daemon.wait_for_log(r'dev_disconnect: .WIRE_COMMITMENT_SIGNED')
opener.rpc.connect(funder.info['id'], 'localhost', funder.port)
fut.result(timeout=TIMEOUT)
Loading