mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-08 15:44:19 +01:00
gossip: Disable channels when we lose the connection to the peer
We're telling gossipd about disconnections anyway, so let's just use that signal to disable both sides of the channel. Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
committed by
Rusty Russell
parent
3e5b798c60
commit
8e278044e3
183
gossipd/gossip.c
183
gossipd/gossip.c
@@ -2355,11 +2355,99 @@ static struct io_plan *peer_important(struct io_conn *conn,
|
||||
return daemon_conn_read_next(conn, &daemon->master);
|
||||
}
|
||||
|
||||
static void gossip_disable_channel(struct routing_state *rstate, struct chan *chan)
|
||||
{
|
||||
struct short_channel_id scid;
|
||||
u8 direction;
|
||||
struct half_chan *hc;
|
||||
u16 flags, cltv_expiry_delta;
|
||||
u32 timestamp, fee_base_msat, fee_proportional_millionths;
|
||||
struct bitcoin_blkid chain_hash;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
u64 htlc_minimum_msat;
|
||||
u8 *err, *msg;
|
||||
|
||||
direction = pubkey_eq(&chan->nodes[0]->id, &rstate->local_id)?0:1;
|
||||
|
||||
assert(chan);
|
||||
hc = &chan->half[direction];
|
||||
|
||||
status_trace("Disabling channel %s/%d, active %d -> %d",
|
||||
type_to_string(tmpctx, struct short_channel_id, &chan->scid),
|
||||
direction, is_halfchan_enabled(hc), 0);
|
||||
|
||||
if (!is_halfchan_defined(hc)) {
|
||||
status_trace(
|
||||
"Channel %s/%d doesn't have a channel_update yet, can't "
|
||||
"disable",
|
||||
type_to_string(tmpctx, struct short_channel_id, &scid),
|
||||
direction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fromwire_channel_update(
|
||||
hc->channel_update, &sig, &chain_hash, &scid, ×tamp,
|
||||
&flags, &cltv_expiry_delta, &htlc_minimum_msat, &fee_base_msat,
|
||||
&fee_proportional_millionths)) {
|
||||
status_failed(
|
||||
STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Unable to parse previously accepted channel_update");
|
||||
}
|
||||
|
||||
status_trace("Disabling channel %s", type_to_string(tmpctx, struct short_channel_id, &scid));
|
||||
|
||||
timestamp = time_now().ts.tv_sec;
|
||||
if (timestamp <= hc->last_timestamp)
|
||||
timestamp = hc->last_timestamp + 1;
|
||||
|
||||
status_trace("Disabling channel %s: %d", type_to_string(tmpctx, struct short_channel_id, &scid), 0);
|
||||
|
||||
flags = flags | ROUTING_FLAGS_DISABLED;
|
||||
|
||||
msg = towire_channel_update(tmpctx, &sig, &chain_hash, &scid, timestamp,
|
||||
flags, cltv_expiry_delta, htlc_minimum_msat,
|
||||
fee_base_msat, fee_proportional_millionths);
|
||||
|
||||
if (!wire_sync_write(HSM_FD,
|
||||
towire_hsm_cupdate_sig_req(tmpctx, msg))) {
|
||||
status_failed(STATUS_FAIL_HSM_IO, "Writing cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
msg = wire_sync_read(tmpctx, HSM_FD);
|
||||
if (!msg || !fromwire_hsm_cupdate_sig_reply(tmpctx, msg, &msg)) {
|
||||
status_failed(STATUS_FAIL_HSM_IO,
|
||||
"Reading cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
err = handle_channel_update(rstate, msg, "disable_channel");
|
||||
if (err)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"rejected disabling channel_update: %s",
|
||||
tal_hex(tmpctx, err));
|
||||
}
|
||||
|
||||
static void peer_disable_channels(struct routing_state *rstate, struct node *node)
|
||||
{
|
||||
struct chan *c;
|
||||
size_t i;
|
||||
for (i=0; i<tal_count(node->chans); i++) {
|
||||
c = node->chans[i];
|
||||
if (pubkey_eq(&other_node(node, c)->id, &rstate->local_id)) {
|
||||
c->half[0].flags |= ROUTING_FLAGS_DISABLED;
|
||||
c->half[1].flags |= ROUTING_FLAGS_DISABLED;
|
||||
gossip_disable_channel(rstate, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct io_plan *peer_disconnected(struct io_conn *conn,
|
||||
struct daemon *daemon, const u8 *msg)
|
||||
{
|
||||
struct pubkey id;
|
||||
struct peer *peer;
|
||||
struct node *node;
|
||||
|
||||
if (!fromwire_gossipctl_peer_disconnected(msg, &id))
|
||||
master_badmsg(WIRE_GOSSIPCTL_PEER_DISCONNECTED, msg);
|
||||
@@ -2375,6 +2463,11 @@ static struct io_plan *peer_disconnected(struct io_conn *conn,
|
||||
status_trace("Forgetting remote peer %s",
|
||||
type_to_string(tmpctx, struct pubkey, &peer->id));
|
||||
|
||||
/* Disable any channels to and from this peer */
|
||||
node = get_node(daemon->rstate, &id);
|
||||
if (node)
|
||||
peer_disable_channels(daemon->rstate, node);
|
||||
|
||||
tal_free(peer);
|
||||
|
||||
/* If there was a connecting peer waiting, wake it now */
|
||||
@@ -2440,92 +2533,6 @@ static struct io_plan *handle_txout_reply(struct io_conn *conn,
|
||||
return daemon_conn_read_next(conn, &daemon->master);
|
||||
}
|
||||
|
||||
static struct io_plan *handle_disable_channel(struct io_conn *conn,
|
||||
struct daemon *daemon, u8 *msg)
|
||||
{
|
||||
struct short_channel_id scid;
|
||||
u8 direction;
|
||||
struct chan *chan;
|
||||
struct half_chan *hc;
|
||||
bool active;
|
||||
u16 flags, cltv_expiry_delta;
|
||||
u32 timestamp, fee_base_msat, fee_proportional_millionths;
|
||||
struct bitcoin_blkid chain_hash;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
u64 htlc_minimum_msat;
|
||||
u8 *err;
|
||||
|
||||
if (!fromwire_gossip_disable_channel(msg, &scid, &direction, &active) ) {
|
||||
status_unusual("Unable to parse %s",
|
||||
gossip_wire_type_name(fromwire_peektype(msg)));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
chan = get_channel(daemon->rstate, &scid);
|
||||
if (!chan) {
|
||||
status_trace(
|
||||
"Unable to find channel %s",
|
||||
type_to_string(msg, struct short_channel_id, &scid));
|
||||
goto fail;
|
||||
}
|
||||
hc = &chan->half[direction];
|
||||
|
||||
status_trace("Disabling channel %s/%d, active %d -> %d",
|
||||
type_to_string(msg, struct short_channel_id, &scid),
|
||||
direction, is_halfchan_enabled(hc), active);
|
||||
|
||||
if (!is_halfchan_defined(hc)) {
|
||||
status_trace(
|
||||
"Channel %s/%d doesn't have a channel_update yet, can't "
|
||||
"disable",
|
||||
type_to_string(msg, struct short_channel_id, &scid),
|
||||
direction);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!fromwire_channel_update(
|
||||
hc->channel_update, &sig, &chain_hash, &scid, ×tamp,
|
||||
&flags, &cltv_expiry_delta, &htlc_minimum_msat, &fee_base_msat,
|
||||
&fee_proportional_millionths)) {
|
||||
status_failed(
|
||||
STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Unable to parse previously accepted channel_update");
|
||||
}
|
||||
|
||||
timestamp = time_now().ts.tv_sec;
|
||||
if (timestamp <= hc->last_timestamp)
|
||||
timestamp = hc->last_timestamp + 1;
|
||||
|
||||
flags = direction;
|
||||
if (!active)
|
||||
flags |= ROUTING_FLAGS_DISABLED;
|
||||
|
||||
msg = towire_channel_update(tmpctx, &sig, &chain_hash, &scid, timestamp,
|
||||
flags, cltv_expiry_delta, htlc_minimum_msat,
|
||||
fee_base_msat, fee_proportional_millionths);
|
||||
|
||||
if (!wire_sync_write(HSM_FD,
|
||||
towire_hsm_cupdate_sig_req(tmpctx, msg))) {
|
||||
status_failed(STATUS_FAIL_HSM_IO, "Writing cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
msg = wire_sync_read(tmpctx, HSM_FD);
|
||||
if (!msg || !fromwire_hsm_cupdate_sig_reply(tmpctx, msg, &msg)) {
|
||||
status_failed(STATUS_FAIL_HSM_IO,
|
||||
"Reading cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
err = handle_channel_update(daemon->rstate, msg, "disable_channel");
|
||||
if (err)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"rejected disabling channel_update: %s",
|
||||
tal_hex(tmpctx, err));
|
||||
|
||||
fail:
|
||||
return daemon_conn_read_next(conn, &daemon->master);
|
||||
}
|
||||
static struct io_plan *handle_routing_failure(struct io_conn *conn,
|
||||
struct daemon *daemon,
|
||||
const u8 *msg)
|
||||
@@ -2615,6 +2622,7 @@ static struct io_plan *handle_local_channel_close(struct io_conn *conn,
|
||||
if (chan) {
|
||||
chan->half[0].flags |= ROUTING_FLAGS_DISABLED;
|
||||
chan->half[1].flags |= ROUTING_FLAGS_DISABLED;
|
||||
gossip_disable_channel(rstate, chan);
|
||||
}
|
||||
return daemon_conn_read_next(conn, &daemon->master);
|
||||
}
|
||||
@@ -2670,9 +2678,6 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
|
||||
case WIRE_GOSSIP_GET_TXOUT_REPLY:
|
||||
return handle_txout_reply(conn, daemon, master->msg_in);
|
||||
|
||||
case WIRE_GOSSIP_DISABLE_CHANNEL:
|
||||
return handle_disable_channel(conn, daemon, master->msg_in);
|
||||
|
||||
case WIRE_GOSSIP_ROUTING_FAILURE:
|
||||
return handle_routing_failure(conn, daemon, master->msg_in);
|
||||
|
||||
|
||||
@@ -220,12 +220,6 @@ gossip_get_txout_reply,,satoshis,u64
|
||||
gossip_get_txout_reply,,len,u16
|
||||
gossip_get_txout_reply,,outscript,len*u8
|
||||
|
||||
# client->gossipd: Disable the channel matching the short_channel_id
|
||||
gossip_disable_channel,3019
|
||||
gossip_disable_channel,,short_channel_id,struct short_channel_id
|
||||
gossip_disable_channel,,direction,u8
|
||||
gossip_disable_channel,,active,bool
|
||||
|
||||
# master->gossipd a routing failure occurred
|
||||
gossip_routing_failure,3021
|
||||
gossip_routing_failure,,erring_node,struct pubkey
|
||||
|
||||
|
@@ -329,14 +329,6 @@ void channel_fail_permanent(struct channel *channel, const char *fmt, ...)
|
||||
why = tal_vfmt(channel, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (channel->scid) {
|
||||
u8 *msg = towire_gossip_disable_channel(NULL,
|
||||
channel->scid,
|
||||
channel->peer->direction,
|
||||
false);
|
||||
subd_send_msg(ld->gossip, take(msg));
|
||||
}
|
||||
|
||||
log_unusual(channel->log, "Peer permanent failure in %s: %s",
|
||||
channel_state_name(channel), why);
|
||||
|
||||
|
||||
@@ -133,7 +133,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
|
||||
case WIRE_GOSSIP_GET_UPDATE:
|
||||
case WIRE_GOSSIP_SEND_GOSSIP:
|
||||
case WIRE_GOSSIP_GET_TXOUT_REPLY:
|
||||
case WIRE_GOSSIP_DISABLE_CHANNEL:
|
||||
case WIRE_GOSSIP_OUTPOINT_SPENT:
|
||||
case WIRE_GOSSIP_ROUTING_FAILURE:
|
||||
case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE:
|
||||
|
||||
@@ -52,7 +52,7 @@ bool channel_tell_funding_locked(struct lightningd *ld UNNEEDED,
|
||||
{ fprintf(stderr, "channel_tell_funding_locked called!\n"); abort(); }
|
||||
/* Generated stub for command_fail */
|
||||
void command_fail(struct command *cmd UNNEEDED, int code UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "command_fail called!\n"); abort(); }
|
||||
/* Generated stub for command_still_pending */
|
||||
void command_still_pending(struct command *cmd UNNEEDED)
|
||||
@@ -388,9 +388,6 @@ u8 *towire_gossipctl_peer_disconnected(const tal_t *ctx UNNEEDED, const struct p
|
||||
/* Generated stub for towire_gossipctl_peer_important */
|
||||
u8 *towire_gossipctl_peer_important(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, bool important UNNEEDED)
|
||||
{ fprintf(stderr, "towire_gossipctl_peer_important called!\n"); abort(); }
|
||||
/* Generated stub for towire_gossip_disable_channel */
|
||||
u8 *towire_gossip_disable_channel(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED, u8 direction UNNEEDED, bool active UNNEEDED)
|
||||
{ fprintf(stderr, "towire_gossip_disable_channel called!\n"); abort(); }
|
||||
/* Generated stub for towire_gossip_getpeers_request */
|
||||
u8 *towire_gossip_getpeers_request(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED)
|
||||
{ fprintf(stderr, "towire_gossip_getpeers_request called!\n"); abort(); }
|
||||
|
||||
Reference in New Issue
Block a user