Skip to content

Commit

Permalink
openingd: tell lightningd if we get a reestablish.
Browse files Browse the repository at this point in the history
It simply uses connectd to send an error if it doesn't know anything
about the channel.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Jun 9, 2021
1 parent 7fe769a commit 2ec8413
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 18 deletions.
42 changes: 42 additions & 0 deletions lightningd/opening_common.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include <ccan/ccan/tal/str/str.h>
#include <common/json_command.h>
#include <common/jsonrpc_errors.h>
#include <common/wire_error.h>
#include <connectd/connectd_wiregen.h>
#include <lightningd/channel.h>
#include <lightningd/channel_control.h>
#include <lightningd/log.h>
#include <lightningd/notification.h>
#include <lightningd/opening_common.h>
Expand Down Expand Up @@ -151,6 +153,46 @@ void channel_config(struct lightningd *ld,
ours->channel_reserve = AMOUNT_SAT(UINT64_MAX);
}

void handle_reestablish(struct lightningd *ld,
const struct node_id *peer_id,
const struct channel_id *channel_id,
const u8 *reestablish,
struct per_peer_state *pps)
{
struct peer *peer;
struct channel *c;

/* We very carefully re-xmit the last reestablish, so they can get
* their secrets back. We don't otherwise touch them. */
peer = peer_by_id(ld, peer_id);
if (peer)
c = find_channel_by_id(peer, channel_id);
else
c = NULL;

if (c && channel_closed(c)) {
log_debug(c->log, "Reestablish on %s channel: using channeld to reply",
channel_state_name(c));
peer_start_channeld(c, pps, NULL, true, reestablish);
} else {
const u8 *err = towire_errorfmt(tmpctx, channel_id,
"Unknown channel for reestablish");
log_debug(ld->log, "Reestablish on UNKNOWN channel %s",
type_to_string(tmpctx, struct channel_id, channel_id));
subd_send_msg(ld->connectd,
take(towire_connectd_peer_final_msg(NULL, peer_id,
pps, err)));
subd_send_fd(ld->connectd, pps->peer_fd);
subd_send_fd(ld->connectd, pps->gossip_fd);
subd_send_fd(ld->connectd, pps->gossip_store_fd);
/* Don't close those fds! */
pps->peer_fd
= pps->gossip_fd
= pps->gossip_store_fd
= -1;
}
}

#if DEVELOPER
/* Indented to avoid include ordering check */
#include <lightningd/memdump.h>
Expand Down
6 changes: 6 additions & 0 deletions lightningd/opening_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ void channel_config(struct lightningd *ld,
u32 *max_to_self_delay,
struct amount_msat *min_effective_htlc_capacity);

void handle_reestablish(struct lightningd *ld,
const struct node_id *peer_id,
const struct channel_id *channel_id,
const u8 *reestablish,
struct per_peer_state *pps);

#if DEVELOPER
struct command;
/* Calls report_leak_info() async. */
Expand Down
31 changes: 31 additions & 0 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,31 @@ static void opening_got_offer(struct subd *openingd,
plugin_hook_call_openchannel(openingd->ld, payload);
}

static void opening_got_reestablish(struct subd *openingd, const u8 *msg,
const int fds[3],
struct uncommitted_channel *uc)
{
struct lightningd *ld = openingd->ld;
struct node_id peer_id = uc->peer->id;
struct channel_id channel_id;
u8 *reestablish;
struct per_peer_state *pps;

if (!fromwire_openingd_got_reestablish(tmpctx, msg, &channel_id,
&reestablish, &pps)) {
log_broken(openingd->log, "Malformed opening_got_reestablish %s",
tal_hex(tmpctx, msg));
tal_free(openingd);
return;
}
per_peer_state_set_fds_arr(pps, fds);

/* This could free peer */
tal_free(uc);

handle_reestablish(ld, &peer_id, &channel_id, reestablish, pps);
}

static unsigned int openingd_msg(struct subd *openingd,
const u8 *msg, const int *fds)
{
Expand Down Expand Up @@ -848,6 +873,12 @@ static unsigned int openingd_msg(struct subd *openingd,
opening_got_offer(openingd, msg, uc);
return 0;

case WIRE_OPENINGD_GOT_REESTABLISH:
if (tal_count(fds) != 3)
return 3;
opening_got_reestablish(openingd, msg, fds, uc);
return 0;

/* We send these! */
case WIRE_OPENINGD_INIT:
case WIRE_OPENINGD_FUNDER_START:
Expand Down
29 changes: 15 additions & 14 deletions openingd/openingd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,7 @@ static u8 *handle_peer_in(struct state *state)
u8 *msg = sync_crypto_read(tmpctx, state->pps);
enum peer_wire t = fromwire_peektype(msg);
struct channel_id channel_id;
bool extracted;

if (t == WIRE_OPEN_CHANNEL)
return fundee_channel(state, msg);
Expand All @@ -1170,21 +1171,20 @@ static u8 *handle_peer_in(struct state *state)
&state->channel_id, false, msg))
return NULL;

if (extract_channel_id(msg, &channel_id)) {
sync_crypto_write(state->pps,
take(towire_errorfmt(NULL,
&channel_id,
"Unexpected message %s: %s",
peer_wire_name(t),
tal_hex(tmpctx, msg))));
} else {
sync_crypto_write(state->pps,
take(towire_warningfmt(NULL,
NULL,
"Unexpected message %s: %s",
peer_wire_name(t),
tal_hex(tmpctx, msg))));
extracted = extract_channel_id(msg, &channel_id);

/* Reestablish on some now-closed channel? Be nice. */
if (extracted && fromwire_peektype(msg) == WIRE_CHANNEL_REESTABLISH) {
return towire_openingd_got_reestablish(NULL,
&channel_id, msg,
state->pps);
}
sync_crypto_write(state->pps,
take(towire_warningfmt(NULL,
extracted ? &channel_id : NULL,
"Unexpected message %s: %s",
peer_wire_name(t),
tal_hex(tmpctx, msg))));

/* FIXME: We don't actually want master to try to send an
* error, since peer is transient. This is a hack.
Expand Down Expand Up @@ -1296,6 +1296,7 @@ static u8 *handle_master_in(struct state *state)
case WIRE_OPENINGD_FUNDER_FAILED:
case WIRE_OPENINGD_GOT_OFFER:
case WIRE_OPENINGD_GOT_OFFER_REPLY:
case WIRE_OPENINGD_GOT_REESTABLISH:
break;
}

Expand Down
7 changes: 7 additions & 0 deletions openingd/openingd_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ msgdata,openingd_init,option_anchor_outputs,bool,
msgdata,openingd_init,dev_temporary_channel_id,?byte,32
msgdata,openingd_init,dev_fast_gossip,bool,

# Openingd->master: they tried to reestablish a channel.
msgtype,openingd_got_reestablish,6001
msgdata,openingd_got_reestablish,channel_id,channel_id,
msgdata,openingd_got_reestablish,len,u16,
msgdata,openingd_got_reestablish,msg,u8,len
msgdata,openingd_got_reestablish,pps,per_peer_state,

# Openingd->master: they offered channel, should we continue?
msgtype,openingd_got_offer,6005
msgdata,openingd_got_offer,funding_satoshis,amount_sat,
Expand Down
37 changes: 36 additions & 1 deletion openingd/openingd_wiregen.c

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

9 changes: 8 additions & 1 deletion openingd/openingd_wiregen.h

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

4 changes: 2 additions & 2 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,7 @@ def test_funding_by_utxos(node_factory, bitcoind):
@pytest.mark.developer("needs dev_forget_channel")
@pytest.mark.openchannel('v1')
def test_funding_external_wallet_corners(node_factory, bitcoind):
l1 = node_factory.get_node(may_reconnect=True, allow_broken_log=True)
l1 = node_factory.get_node(may_reconnect=True)
l2 = node_factory.get_node(may_reconnect=True)

amount = 2**24
Expand Down Expand Up @@ -1242,7 +1242,7 @@ def test_funding_external_wallet_corners(node_factory, bitcoind):

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

Expand Down

0 comments on commit 2ec8413

Please sign in to comment.