openingd: tell lightningd if we get a reestablish.

It simply uses connectd to send an error if it doesn't know anything
about the channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2021-06-15 14:37:15 +09:30
parent 9929d6383a
commit 44829d1361
8 changed files with 147 additions and 18 deletions

View file

@ -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>
@ -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>

View file

@ -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. */

View file

@ -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)
{
@ -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:

View file

@ -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);
@ -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.
@ -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;
}

View file

@ -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,

1 #include <bitcoin/chainparams.h>
29 msgdata,openingd_init,dev_fast_gossip,bool,
30 # Openingd->master: they offered channel, should we continue? # Openingd->master: they tried to reestablish a channel.
31 msgtype,openingd_got_offer,6005 msgtype,openingd_got_reestablish,6001
32 msgdata,openingd_got_reestablish,channel_id,channel_id,
33 msgdata,openingd_got_reestablish,len,u16,
34 msgdata,openingd_got_reestablish,msg,u8,len
35 msgdata,openingd_got_reestablish,pps,per_peer_state,
36 # Openingd->master: they offered channel, should we continue?
37 msgtype,openingd_got_offer,6005
38 msgdata,openingd_got_offer,funding_satoshis,amount_sat,
39 msgdata,openingd_got_offer,funding_satoshis,amount_sat, msgdata,openingd_got_offer,push_msat,amount_msat,
40 msgdata,openingd_got_offer,push_msat,amount_msat, msgdata,openingd_got_offer,dust_limit_satoshis,amount_sat,
41 msgdata,openingd_got_offer,dust_limit_satoshis,amount_sat, msgdata,openingd_got_offer,max_htlc_value_in_flight_msat,amount_msat,

View file

@ -21,6 +21,7 @@ const char *openingd_wire_name(int e)
switch ((enum openingd_wire)e) {
case WIRE_OPENINGD_INIT: return "WIRE_OPENINGD_INIT";
case WIRE_OPENINGD_GOT_REESTABLISH: return "WIRE_OPENINGD_GOT_REESTABLISH";
case WIRE_OPENINGD_GOT_OFFER: return "WIRE_OPENINGD_GOT_OFFER";
case WIRE_OPENINGD_GOT_OFFER_REPLY: return "WIRE_OPENINGD_GOT_OFFER_REPLY";
case WIRE_OPENINGD_FUNDER_REPLY: return "WIRE_OPENINGD_FUNDER_REPLY";
@ -42,6 +43,7 @@ bool openingd_wire_is_defined(u16 type)
{
switch ((enum openingd_wire)type) {
case WIRE_OPENINGD_INIT:;
case WIRE_OPENINGD_GOT_REESTABLISH:;
case WIRE_OPENINGD_GOT_OFFER:;
case WIRE_OPENINGD_GOT_OFFER_REPLY:;
case WIRE_OPENINGD_FUNDER_REPLY:;
@ -138,6 +140,39 @@ bool fromwire_openingd_init(const tal_t *ctx, const void *p, const struct chainp
return cursor != NULL;
}
/* WIRE: OPENINGD_GOT_REESTABLISH */
/* Openingd->master: they tried to reestablish a channel. */
u8 *towire_openingd_got_reestablish(const tal_t *ctx, const struct channel_id *channel_id, const u8 *msg, const struct per_peer_state *pps)
{
u16 len = tal_count(msg);
u8 *p = tal_arr(ctx, u8, 0);
towire_u16(&p, WIRE_OPENINGD_GOT_REESTABLISH);
towire_channel_id(&p, channel_id);
towire_u16(&p, len);
towire_u8_array(&p, msg, len);
towire_per_peer_state(&p, pps);
return memcheck(p, tal_count(p));
}
bool fromwire_openingd_got_reestablish(const tal_t *ctx, const void *p, struct channel_id *channel_id, u8 **msg, struct per_peer_state **pps)
{
u16 len;
const u8 *cursor = p;
size_t plen = tal_count(p);
if (fromwire_u16(&cursor, &plen) != WIRE_OPENINGD_GOT_REESTABLISH)
return false;
fromwire_channel_id(&cursor, &plen, channel_id);
len = fromwire_u16(&cursor, &plen);
// 2nd case msg
*msg = len ? tal_arr(ctx, u8, len) : NULL;
fromwire_u8_array(&cursor, &plen, *msg, len);
*pps = fromwire_per_peer_state(ctx, &cursor, &plen);
return cursor != NULL;
}
/* WIRE: OPENINGD_GOT_OFFER */
/* Openingd->master: they offered channel */
u8 *towire_openingd_got_offer(const tal_t *ctx, struct amount_sat funding_satoshis, struct amount_msat push_msat, struct amount_sat dust_limit_satoshis, struct amount_msat max_htlc_value_in_flight_msat, struct amount_sat channel_reserve_satoshis, struct amount_msat htlc_minimum_msat, u32 feerate_per_kw, u16 to_self_delay, u16 max_accepted_htlcs, u8 channel_flags, const u8 *shutdown_scriptpubkey)
@ -569,4 +604,4 @@ bool fromwire_openingd_dev_memleak_reply(const void *p, bool *leak)
*leak = fromwire_bool(&cursor, &plen);
return cursor != NULL;
}
// SHA256STAMP:d2fcabdf157b098608e47dcdc37db0f46fe8d466d74159969544d7c4bb77f061
// SHA256STAMP:005577de0219577522210df32b3ed325f028b24fc25d3b77a1dc770077381b6b

View file

@ -18,6 +18,8 @@
enum openingd_wire {
WIRE_OPENINGD_INIT = 6000,
/* Openingd->master: they tried to reestablish a channel. */
WIRE_OPENINGD_GOT_REESTABLISH = 6001,
/* Openingd->master: they offered channel */
WIRE_OPENINGD_GOT_OFFER = 6005,
/* master->openingd: optional rejection message */
@ -61,6 +63,11 @@ bool openingd_wire_is_defined(u16 type);
u8 *towire_openingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_features, const struct channel_config *our_config, u32 max_to_self_delay, struct amount_msat min_effective_htlc_capacity_msat, const struct per_peer_state *pps, const struct basepoints *our_basepoints, const struct pubkey *our_funding_pubkey, u32 minimum_depth, u32 min_feerate, u32 max_feerate, const u8 *lfeatures, bool option_static_remotekey, bool option_anchor_outputs, const struct channel_id *dev_temporary_channel_id, bool dev_fast_gossip);
bool fromwire_openingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_features, struct channel_config *our_config, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity_msat, struct per_peer_state **pps, struct basepoints *our_basepoints, struct pubkey *our_funding_pubkey, u32 *minimum_depth, u32 *min_feerate, u32 *max_feerate, u8 **lfeatures, bool *option_static_remotekey, bool *option_anchor_outputs, struct channel_id **dev_temporary_channel_id, bool *dev_fast_gossip);
/* WIRE: OPENINGD_GOT_REESTABLISH */
/* Openingd->master: they tried to reestablish a channel. */
u8 *towire_openingd_got_reestablish(const tal_t *ctx, const struct channel_id *channel_id, const u8 *msg, const struct per_peer_state *pps);
bool fromwire_openingd_got_reestablish(const tal_t *ctx, const void *p, struct channel_id *channel_id, u8 **msg, struct per_peer_state **pps);
/* WIRE: OPENINGD_GOT_OFFER */
/* Openingd->master: they offered channel */
u8 *towire_openingd_got_offer(const tal_t *ctx, struct amount_sat funding_satoshis, struct amount_msat push_msat, struct amount_sat dust_limit_satoshis, struct amount_msat max_htlc_value_in_flight_msat, struct amount_sat channel_reserve_satoshis, struct amount_msat htlc_minimum_msat, u32 feerate_per_kw, u16 to_self_delay, u16 max_accepted_htlcs, u8 channel_flags, const u8 *shutdown_scriptpubkey);
@ -121,4 +128,4 @@ bool fromwire_openingd_dev_memleak_reply(const void *p, bool *leak);
#endif /* LIGHTNING_OPENINGD_OPENINGD_WIREGEN_H */
// SHA256STAMP:d2fcabdf157b098608e47dcdc37db0f46fe8d466d74159969544d7c4bb77f061
// SHA256STAMP:005577de0219577522210df32b3ed325f028b24fc25d3b77a1dc770077381b6b

View file

@ -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
@ -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)