mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
gossipd: Implement gossip_routing_failure
for master to report routing failures.
This commit is contained in:
parent
7a651c62fa
commit
b255d82ae2
@ -56,7 +56,8 @@ GOSSIPD_COMMON_OBJS := \
|
||||
common/wire_error.o \
|
||||
hsmd/client.o \
|
||||
hsmd/gen_hsm_client_wire.o \
|
||||
lightningd/gossip_msg.o
|
||||
lightningd/gossip_msg.o \
|
||||
wire/gen_onion_wire.o
|
||||
|
||||
$(LIGHTNINGD_GOSSIP_OBJS) $(LIGHTNINGD_GOSSIP_CLIENT_OBJS): $(LIGHTNINGD_HEADERS) $(LIGHTNINGD_GOSSIP_HEADERS)
|
||||
|
||||
|
@ -1883,6 +1883,27 @@ fail:
|
||||
tal_free(tmpctx);
|
||||
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)
|
||||
{
|
||||
struct pubkey erring_node;
|
||||
struct short_channel_id erring_channel;
|
||||
u16 failcode;
|
||||
|
||||
if (!fromwire_gossip_routing_failure(msg, NULL,
|
||||
&erring_node,
|
||||
&erring_channel,
|
||||
&failcode))
|
||||
master_badmsg(WIRE_GOSSIP_ROUTING_FAILURE, msg);
|
||||
|
||||
routing_failure(daemon->rstate,
|
||||
&erring_node,
|
||||
&erring_channel,
|
||||
(enum onion_type) failcode);
|
||||
|
||||
return daemon_conn_read_next(conn, &daemon->master);
|
||||
}
|
||||
|
||||
static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master)
|
||||
{
|
||||
@ -1932,6 +1953,9 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
|
||||
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);
|
||||
|
||||
/* We send these, we don't receive them */
|
||||
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
|
||||
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL:
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <common/cryptomsg.h>
|
||||
#include <common/wireaddr.h>
|
||||
#include <wire/gen_onion_wire.h>
|
||||
|
||||
# Initialize the gossip daemon.
|
||||
gossipctl_init,3000
|
||||
@ -195,3 +196,9 @@ 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
|
||||
gossip_routing_failure,,erring_channel,struct short_channel_id
|
||||
gossip_routing_failure,,failcode,u16
|
||||
|
|
@ -13,6 +13,7 @@
|
||||
#include <common/type_to_string.h>
|
||||
#include <common/wireaddr.h>
|
||||
#include <inttypes.h>
|
||||
#include <wire/gen_onion_wire.h>
|
||||
#include <wire/gen_peer_wire.h>
|
||||
|
||||
#ifndef SUPERVERBOSE
|
||||
@ -238,6 +239,12 @@ get_or_make_connection(struct routing_state *rstate,
|
||||
return nc;
|
||||
}
|
||||
|
||||
static void delete_connection(struct routing_state *rstate,
|
||||
const struct node_connection *connection)
|
||||
{
|
||||
tal_free(connection);
|
||||
}
|
||||
|
||||
struct node_connection *half_add_connection(
|
||||
struct routing_state *rstate,
|
||||
const struct pubkey *from,
|
||||
@ -1007,3 +1014,99 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
|
||||
/* FIXME: Shadow route! */
|
||||
return hops;
|
||||
}
|
||||
|
||||
/* Get the struct node_connection matching the short_channel_id,
|
||||
* which must be an out connection of the given node. */
|
||||
static struct node_connection *
|
||||
get_out_node_connection_of(struct routing_state *rstate,
|
||||
const struct node *node,
|
||||
const struct short_channel_id *short_channel_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tal_count(node->out); ++i) {
|
||||
if (short_channel_id_eq(&node->out[i]->short_channel_id, short_channel_id))
|
||||
return node->out[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* routing_failure_on_nc - Handle routing failure on a specific
|
||||
* node_connection.
|
||||
*/
|
||||
static void routing_failure_on_nc(struct routing_state *rstate,
|
||||
enum onion_type failcode,
|
||||
struct node_connection *nc)
|
||||
{
|
||||
/* BOLT #4:
|
||||
*
|
||||
* - if the PERM bit is NOT set:
|
||||
* - SHOULD restore the channels as it receives new `channel_update`s.
|
||||
*/
|
||||
if (failcode & PERM)
|
||||
nc->active = false;
|
||||
else
|
||||
delete_connection(rstate, nc);
|
||||
}
|
||||
|
||||
void routing_failure(struct routing_state *rstate,
|
||||
const struct pubkey *erring_node_pubkey,
|
||||
const struct short_channel_id *scid,
|
||||
enum onion_type failcode)
|
||||
{
|
||||
const tal_t *tmpctx = tal_tmpctx(rstate);
|
||||
struct node *node;
|
||||
struct node_connection *nc;
|
||||
int i;
|
||||
|
||||
status_trace("Received routing failure 0x%04x (%s), "
|
||||
"erring node %s, "
|
||||
"channel %s",
|
||||
(int) failcode, onion_type_name(failcode),
|
||||
type_to_string(tmpctx, struct pubkey, erring_node_pubkey),
|
||||
type_to_string(tmpctx, struct short_channel_id, scid));
|
||||
|
||||
node = get_node(rstate, erring_node_pubkey);
|
||||
if (!node) {
|
||||
status_trace("UNUSUAL routing_failure: "
|
||||
"Erring node %s not in map",
|
||||
type_to_string(tmpctx, struct pubkey,
|
||||
erring_node_pubkey));
|
||||
/* No node, so no channel, so any channel_update
|
||||
* can also be ignored. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* BOLT #4:
|
||||
*
|
||||
* - if the NODE bit is set:
|
||||
* - SHOULD remove all channels connected with the erring node from
|
||||
* consideration.
|
||||
*
|
||||
*/
|
||||
if (failcode & NODE) {
|
||||
for (i = 0; i < tal_count(node->in); ++i)
|
||||
routing_failure_on_nc(rstate, failcode, node->in[i]);
|
||||
for (i = 0; i < tal_count(node->out); ++i)
|
||||
routing_failure_on_nc(rstate, failcode, node->out[i]);
|
||||
} else {
|
||||
nc = get_out_node_connection_of(rstate, node, scid);
|
||||
if (nc)
|
||||
routing_failure_on_nc(rstate, failcode, nc);
|
||||
else
|
||||
status_trace("UNUSUAL routing_failure: "
|
||||
"Channel %s not an out channel "
|
||||
"of node %s",
|
||||
type_to_string(tmpctx,
|
||||
struct short_channel_id,
|
||||
scid),
|
||||
type_to_string(tmpctx, struct pubkey,
|
||||
erring_node_pubkey));
|
||||
}
|
||||
|
||||
/* FIXME: if UPDATE is set, apply the channel update. */
|
||||
out:
|
||||
tal_free(tmpctx);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <bitcoin/pubkey.h>
|
||||
#include <ccan/htable/htable_type.h>
|
||||
#include <gossipd/broadcast.h>
|
||||
#include <wire/gen_onion_wire.h>
|
||||
#include <wire/wire.h>
|
||||
|
||||
#define ROUTING_MAX_HOPS 20
|
||||
@ -148,6 +149,11 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
|
||||
const struct pubkey *destination,
|
||||
const u32 msatoshi, double riskfactor,
|
||||
u32 final_cltv);
|
||||
/* Disable channel(s) based on the given routing failure. */
|
||||
void routing_failure(struct routing_state *rstate,
|
||||
const struct pubkey *erring_node,
|
||||
const struct short_channel_id *erring_channel,
|
||||
enum onion_type failcode);
|
||||
|
||||
/* Utility function that, given a source and a destination, gives us
|
||||
* the direction bit the matching channel should get */
|
||||
|
@ -63,6 +63,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
/* Generated stub for fromwire_wireaddr */
|
||||
bool fromwire_wireaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct wireaddr *addr UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_wireaddr called!\n"); abort(); }
|
||||
/* Generated stub for onion_type_name */
|
||||
const char *onion_type_name(int e UNNEEDED)
|
||||
{ fprintf(stderr, "onion_type_name called!\n"); abort(); }
|
||||
/* Generated stub for queue_broadcast */
|
||||
bool queue_broadcast(struct broadcast_state *bstate UNNEEDED,
|
||||
const int type UNNEEDED,
|
||||
|
@ -34,6 +34,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
/* Generated stub for fromwire_wireaddr */
|
||||
bool fromwire_wireaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct wireaddr *addr UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_wireaddr called!\n"); abort(); }
|
||||
/* Generated stub for onion_type_name */
|
||||
const char *onion_type_name(int e UNNEEDED)
|
||||
{ fprintf(stderr, "onion_type_name called!\n"); abort(); }
|
||||
/* Generated stub for queue_broadcast */
|
||||
bool queue_broadcast(struct broadcast_state *bstate UNNEEDED,
|
||||
const int type UNNEEDED,
|
||||
|
@ -27,6 +27,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
/* Generated stub for fromwire_wireaddr */
|
||||
bool fromwire_wireaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct wireaddr *addr UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_wireaddr called!\n"); abort(); }
|
||||
/* Generated stub for onion_type_name */
|
||||
const char *onion_type_name(int e UNNEEDED)
|
||||
{ fprintf(stderr, "onion_type_name called!\n"); abort(); }
|
||||
/* Generated stub for queue_broadcast */
|
||||
bool queue_broadcast(struct broadcast_state *bstate UNNEEDED,
|
||||
const int type UNNEEDED,
|
||||
|
@ -110,6 +110,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
|
||||
case WIRE_GOSSIP_SEND_GOSSIP:
|
||||
case WIRE_GOSSIP_GET_TXOUT_REPLY:
|
||||
case WIRE_GOSSIP_DISABLE_CHANNEL:
|
||||
case WIRE_GOSSIP_ROUTING_FAILURE:
|
||||
/* This is a reply, so never gets through to here. */
|
||||
case WIRE_GOSSIP_GET_UPDATE_REPLY:
|
||||
case WIRE_GOSSIP_GETNODES_REPLY:
|
||||
|
Loading…
Reference in New Issue
Block a user