mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
channel: Disable channels that are lost via a channel_update
Before exiting, `channeld` constructs and sends a `channel_update` marking the channel as disabled. This is the pro-active signalling that the channel may no longer be used.
This commit is contained in:
parent
c8da420a9d
commit
60a2227f0d
@ -750,7 +750,7 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update, size_
|
|||||||
c->htlc_minimum_msat = htlc_minimum_msat;
|
c->htlc_minimum_msat = htlc_minimum_msat;
|
||||||
c->base_fee = fee_base_msat;
|
c->base_fee = fee_base_msat;
|
||||||
c->proportional_fee = fee_proportional_millionths;
|
c->proportional_fee = fee_proportional_millionths;
|
||||||
c->active = true;
|
c->active = (flags & ROUTING_FLAGS_DISABLED) == 0;
|
||||||
log_debug(rstate->base_log, "Channel %d:%d:%d(%d) was updated.",
|
log_debug(rstate->base_log, "Channel %d:%d:%d(%d) was updated.",
|
||||||
short_channel_id.blocknum,
|
short_channel_id.blocknum,
|
||||||
short_channel_id.txnum,
|
short_channel_id.txnum,
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <ccan/htable/htable_type.h>
|
#include <ccan/htable/htable_type.h>
|
||||||
|
|
||||||
#define ROUTING_MAX_HOPS 20
|
#define ROUTING_MAX_HOPS 20
|
||||||
|
#define ROUTING_FLAGS_DISABLED 2
|
||||||
|
|
||||||
struct node_connection {
|
struct node_connection {
|
||||||
struct node *src, *dst;
|
struct node *src, *dst;
|
||||||
|
@ -97,19 +97,46 @@ static void send_announcement_signatures(struct peer *peer)
|
|||||||
tal_free(tmpctx);
|
tal_free(tmpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void announce_channel(struct peer *peer)
|
/* The direction bit is 0 if our local node-id is lexicographically
|
||||||
|
* smaller than the remote node-id. */
|
||||||
|
static int get_direction_bit(struct peer *peer)
|
||||||
{
|
{
|
||||||
tal_t *tmpctx = tal_tmpctx(peer);
|
|
||||||
u8 local_der[33], remote_der[33];
|
u8 local_der[33], remote_der[33];
|
||||||
int first, second;
|
|
||||||
u32 timestamp = time_now().ts.tv_sec;
|
|
||||||
u8 *cannounce, *cupdate, *features = tal_arr(peer, u8, 0);
|
|
||||||
u16 flags;
|
|
||||||
|
|
||||||
/* Find out in which order we have to list the endpoints */
|
/* Find out in which order we have to list the endpoints */
|
||||||
pubkey_to_der(local_der, &peer->node_ids[LOCAL]);
|
pubkey_to_der(local_der, &peer->node_ids[LOCAL]);
|
||||||
pubkey_to_der(remote_der, &peer->node_ids[REMOTE]);
|
pubkey_to_der(remote_der, &peer->node_ids[REMOTE]);
|
||||||
if (memcmp(local_der, remote_der, sizeof(local_der)) < 0) {
|
return memcmp(local_der, remote_der, sizeof(local_der)) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_channel_update(struct peer *peer, bool disabled)
|
||||||
|
{
|
||||||
|
tal_t *tmpctx = tal_tmpctx(peer);
|
||||||
|
u32 timestamp = time_now().ts.tv_sec;
|
||||||
|
u16 flags;
|
||||||
|
u8 *cupdate;
|
||||||
|
// TODO(cdecker) Create a real signature for this update
|
||||||
|
secp256k1_ecdsa_signature *sig =
|
||||||
|
talz(tmpctx, secp256k1_ecdsa_signature);
|
||||||
|
|
||||||
|
flags = get_direction_bit(peer) | (disabled << 1);
|
||||||
|
cupdate = towire_channel_update(
|
||||||
|
tmpctx, sig, &peer->short_channel_ids[LOCAL], timestamp, flags, 36,
|
||||||
|
1, 10, peer->channel->view[LOCAL].feerate_per_kw);
|
||||||
|
|
||||||
|
daemon_conn_send(&peer->gossip_client, take(cupdate));
|
||||||
|
|
||||||
|
msg_enqueue(&peer->peer_out, cupdate);
|
||||||
|
tal_free(tmpctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now that we have a working channel, tell the world. */
|
||||||
|
static void send_channel_announcement(struct peer *peer)
|
||||||
|
{
|
||||||
|
tal_t *tmpctx = tal_tmpctx(peer);
|
||||||
|
int first, second;
|
||||||
|
u8 *cannounce, *features = tal_arr(peer, u8, 0);
|
||||||
|
|
||||||
|
if (get_direction_bit(peer) == 1) {
|
||||||
first = LOCAL;
|
first = LOCAL;
|
||||||
second = REMOTE;
|
second = REMOTE;
|
||||||
} else {
|
} else {
|
||||||
@ -117,7 +144,6 @@ static void announce_channel(struct peer *peer)
|
|||||||
second = LOCAL;
|
second = LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that we have a working channel, tell the world. */
|
|
||||||
cannounce = towire_channel_announcement(
|
cannounce = towire_channel_announcement(
|
||||||
tmpctx, &peer->announcement_node_sigs[first],
|
tmpctx, &peer->announcement_node_sigs[first],
|
||||||
&peer->announcement_node_sigs[second],
|
&peer->announcement_node_sigs[second],
|
||||||
@ -127,21 +153,8 @@ static void announce_channel(struct peer *peer)
|
|||||||
&peer->node_ids[second], &peer->funding_pubkey[first],
|
&peer->node_ids[second], &peer->funding_pubkey[first],
|
||||||
&peer->funding_pubkey[second], features);
|
&peer->funding_pubkey[second], features);
|
||||||
|
|
||||||
// TODO(cdecker) Create a real signature for this update
|
|
||||||
secp256k1_ecdsa_signature *sig =
|
|
||||||
talz(tmpctx, secp256k1_ecdsa_signature);
|
|
||||||
|
|
||||||
flags = first == LOCAL;
|
|
||||||
cupdate = towire_channel_update(
|
|
||||||
tmpctx, sig, &peer->short_channel_ids[LOCAL], timestamp, flags, 36,
|
|
||||||
1, 10, peer->channel->view[LOCAL].feerate_per_kw);
|
|
||||||
|
|
||||||
msg_enqueue(&peer->peer_out, cannounce);
|
msg_enqueue(&peer->peer_out, cannounce);
|
||||||
msg_enqueue(&peer->peer_out, cupdate);
|
|
||||||
|
|
||||||
daemon_conn_send(&peer->gossip_client, take(cannounce));
|
daemon_conn_send(&peer->gossip_client, take(cannounce));
|
||||||
daemon_conn_send(&peer->gossip_client, take(cupdate));
|
|
||||||
|
|
||||||
tal_free(tmpctx);
|
tal_free(tmpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +205,8 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg)
|
|||||||
sizeof(struct short_channel_id)));
|
sizeof(struct short_channel_id)));
|
||||||
}
|
}
|
||||||
if (peer->funding_locked[LOCAL]) {
|
if (peer->funding_locked[LOCAL]) {
|
||||||
announce_channel(peer);
|
send_channel_announcement(peer);
|
||||||
|
send_channel_update(peer, false);
|
||||||
}
|
}
|
||||||
} else if (type == WIRE_CHANNEL_ANNOUNCEMENT ||
|
} else if (type == WIRE_CHANNEL_ANNOUNCEMENT ||
|
||||||
type == WIRE_CHANNEL_UPDATE ||
|
type == WIRE_CHANNEL_UPDATE ||
|
||||||
@ -211,6 +225,9 @@ static struct io_plan *setup_peer_conn(struct io_conn *conn, struct peer *peer)
|
|||||||
|
|
||||||
static void peer_conn_broken(struct io_conn *conn, struct peer *peer)
|
static void peer_conn_broken(struct io_conn *conn, struct peer *peer)
|
||||||
{
|
{
|
||||||
|
send_channel_update(peer, true);
|
||||||
|
/* Make sure gossipd actually gets this message before dying */
|
||||||
|
daemon_conn_sync_flush(&peer->gossip_client);
|
||||||
status_failed(WIRE_CHANNEL_PEER_READ_FAILED,
|
status_failed(WIRE_CHANNEL_PEER_READ_FAILED,
|
||||||
"peer connection broken: %s", strerror(errno));
|
"peer connection broken: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
@ -274,7 +291,8 @@ static struct io_plan *req_in(struct io_conn *conn, struct daemon_conn *master)
|
|||||||
peer->funding_locked[LOCAL] = true;
|
peer->funding_locked[LOCAL] = true;
|
||||||
|
|
||||||
if (peer->funding_locked[REMOTE]) {
|
if (peer->funding_locked[REMOTE]) {
|
||||||
announce_channel(peer);
|
send_channel_announcement(peer);
|
||||||
|
send_channel_update(peer, false);
|
||||||
daemon_conn_send(master,
|
daemon_conn_send(master,
|
||||||
take(towire_channel_normal_operation(peer)));
|
take(towire_channel_normal_operation(peer)));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user