Skip to content

Commit

Permalink
gossip: Implement gossip_routing_failure for master to report routi…
Browse files Browse the repository at this point in the history
…ng failures.
  • Loading branch information
ZmnSCPxj committed Jan 20, 2018
1 parent 2f179fb commit e2c4997
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 1 deletion.
25 changes: 25 additions & 0 deletions gossipd/gossip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1769,6 +1769,28 @@ static struct io_plan *handle_txout_reply(struct io_conn *conn,
return daemon_conn_read_next(conn, &daemon->master);
}

static struct io_plan *routing_failure_req(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)
{
struct daemon *daemon = container_of(master, struct daemon, master);
Expand Down Expand Up @@ -1814,6 +1836,9 @@ 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_ROUTING_FAILURE:
return routing_failure_req(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:
Expand Down
6 changes: 6 additions & 0 deletions gossipd/gossip_wire.csv
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -183,3 +184,8 @@ gossip_get_txout_reply,,short_channel_id,struct short_channel_id
gossip_get_txout_reply,,len,u16
gossip_get_txout_reply,,outscript,len*u8

# master->gossipd a routing failure occurred
gossip_routing_failure,3019
gossip_routing_failure,,erring_node,struct pubkey
gossip_routing_failure,,erring_channel,struct short_channel_id
gossip_routing_failure,,failcode,u16
87 changes: 86 additions & 1 deletion gossipd/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -225,6 +226,7 @@ get_or_make_connection(struct routing_state *rstate,
nc->dst = to;
nc->channel_announcement = NULL;
nc->channel_update = NULL;
nc->perminactive = false;

/* Hook it into in/out arrays. */
i = tal_count(to->in);
Expand Down Expand Up @@ -800,7 +802,8 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update)
c->htlc_minimum_msat = htlc_minimum_msat;
c->base_fee = fee_base_msat;
c->proportional_fee = fee_proportional_millionths;
c->active = (flags & ROUTING_FLAGS_DISABLED) == 0;
if (!c->perminactive)
c->active = (flags & ROUTING_FLAGS_DISABLED) == 0;
status_trace("Channel %s(%d) was updated.",
type_to_string(trc, struct short_channel_id,
&short_channel_id),
Expand Down Expand Up @@ -994,3 +997,85 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
/* FIXME: Shadow route! */
return hops;
}

/* Get a singleton array of struct node_connection containing
* the channel matching the short_channel_id, which must be
* an out connection of the given node. */
static struct node_connection **
get_out_node_connection_of(const tal_t *ctx,
struct routing_state *rstate,
const struct node *node,
const struct short_channel_id *short_channel_id)
{
struct node_connection **ncs;
int i;

for (i = 0; i < tal_count(node->out); ++i) {
if (structeq(&node->out[i]->short_channel_id, short_channel_id)) {
ncs = tal_arr(ctx, struct node_connection*, 1);
ncs[0] = node->out[i];
return ncs;
}
}

return NULL;
}
/* Get an array of all channels connected to this node. */
static struct node_connection **
get_all_node_connections_of(const tal_t *ctx,
struct routing_state *rstate,
const struct node *node)
{
struct node_connection **ncs;

u64 num_ins = tal_count(node->in);
u64 num_outs = tal_count(node->out);
u64 num = num_ins + num_outs;

ncs = tal_arr(ctx, struct node_connection*, num);
memcpy(&ncs[0], node->in, num_ins * sizeof(struct node_connection*));
memcpy(&ncs[num_ins], node->out, num_outs * sizeof(struct node_connection*));

return ncs;
}

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 **ncs;
int i;

node = get_node(rstate, erring_node_pubkey);

/* Get all affected channels. */
/* BOLT #4:
*
* - if the NODE bit is set:
* - SHOULD remove all channels connected with the erring node from
* consideration.
*
*/
if ((failcode & NODE) != 0)
ncs = get_all_node_connections_of(tmpctx, rstate, node);
else
ncs = get_out_node_connection_of(tmpctx, rstate, node, scid);

for (i = 0; i < tal_count(ncs); ++i) {
ncs[i]->active = false;
/* BOLT #4:
*
* - if the PERM bit is NOT set:
* - SHOULD restore the channels as it receives new `channel_update`s.
*/
if ((failcode & PERM) != 0)
ncs[i]->perminactive = true;
}

/* FIXME: if UPDATE is set, apply the channel update. */

tal_free(tmpctx);
}
8 changes: 8 additions & 0 deletions gossipd/routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -21,6 +22,8 @@ struct node_connection {

/* Is this connection active? */
bool active;
/* Is this connection permanently inactive? */
bool perminactive;

s64 last_timestamp;

Expand Down Expand Up @@ -148,6 +151,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 */
Expand Down
1 change: 1 addition & 0 deletions lightningd/gossip_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ 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_ROUTING_FAILURE:
/* This is a reply, so never gets through to here. */
case WIRE_GOSSIP_GET_UPDATE_REPLY:
case WIRE_GOSSIP_GETNODES_REPLY:
Expand Down

0 comments on commit e2c4997

Please sign in to comment.