diff --git a/gossipd/gossip_generation.c b/gossipd/gossip_generation.c index 1baddd1fca37..7defae9f434c 100644 --- a/gossipd/gossip_generation.c +++ b/gossipd/gossip_generation.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -414,6 +415,12 @@ void refresh_local_channel(struct daemon *daemon, { const struct half_chan *hc; struct local_cupdate *lc; + u8 *prev; + secp256k1_ecdsa_signature signature; + struct bitcoin_blkid chain_hash; + struct short_channel_id short_channel_id; + u32 timestamp; + u8 message_flags, channel_flags; hc = &local_chan->chan->half[local_chan->direction]; @@ -425,14 +432,32 @@ void refresh_local_channel(struct daemon *daemon, lc->daemon = daemon; lc->local_chan = local_chan; lc->even_if_identical = even_if_identical; - lc->disable = (hc->channel_flags & ROUTING_FLAGS_DISABLED) - || local_chan->local_disabled; - lc->cltv_expiry_delta = hc->delay; - lc->htlc_minimum = hc->htlc_minimum; - lc->htlc_maximum = hc->htlc_maximum; - lc->fee_base_msat = hc->base_fee; - lc->fee_proportional_millionths = hc->proportional_fee; + prev = cast_const(u8 *, + gossip_store_get(tmpctx, daemon->rstate->gs, + local_chan->chan->half[local_chan->direction] + .bcast.index)); + + /* If it's a private update, unwrap */ + fromwire_gossip_store_private_update(tmpctx, prev, &prev); + + if (!fromwire_channel_update_option_channel_htlc_max(prev, + &signature, &chain_hash, + &short_channel_id, ×tamp, + &message_flags, &channel_flags, + &lc->cltv_expiry_delta, + &lc->htlc_minimum, + &lc->fee_base_msat, + &lc->fee_proportional_millionths, + &lc->htlc_maximum)) { + status_broken("Could not decode local channel_update %s!", + tal_hex(tmpctx, prev)); + tal_free(lc); + return; + } + + lc->disable = (channel_flags & ROUTING_FLAGS_DISABLED) + || local_chan->local_disabled; update_local_channel(lc); } diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index d495771e8008..eea5fd3d6904 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -1025,7 +1025,7 @@ static void gossip_refresh_network(struct daemon *daemon) continue; } - if (!is_halfchan_enabled(hc)) { + if (is_chan_local_disabled(daemon->rstate, c)) { /* Only send keepalives for active connections */ continue; } @@ -1138,285 +1138,6 @@ static struct io_plan *gossip_init(struct io_conn *conn, return daemon_conn_read_next(conn, daemon->master); } -/*~ lightningd can ask for a route between nodes. */ -static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon, - const u8 *msg) -{ - struct node_id *source, destination; - struct amount_msat msat; - u32 final_cltv; - /* risk factor 12.345% -> riskfactor_millionths = 12345000 */ - u64 riskfactor_millionths; - u32 max_hops; - u8 *out; - struct route_hop **hops; - /* fuzz 12.345% -> fuzz_millionths = 12345000 */ - u64 fuzz_millionths; - struct exclude_entry **excluded; - - /* To choose between variations, we need to know how much we're - * sending (eliminates too-small channels, and also effects the fees - * we'll pay), how to trade off more locktime vs. more fees, and how - * much cltv we need a the final node to give exact values for each - * intermediate hop, as well as how much random fuzz to inject to - * avoid being too predictable. - * - * We also treat routing slightly differently if we're asking - * for a route from ourselves (the usual case): in that case, - * we don't have to consider fees on our own outgoing channels. - */ - if (!fromwire_gossipd_getroute_request( - msg, msg, &source, &destination, &msat, &riskfactor_millionths, - &final_cltv, &fuzz_millionths, &excluded, &max_hops)) - master_badmsg(WIRE_GOSSIPD_GETROUTE_REQUEST, msg); - - status_debug("Trying to find a route from %s to %s for %s", - source - ? type_to_string(tmpctx, struct node_id, source) : "(me)", - type_to_string(tmpctx, struct node_id, &destination), - type_to_string(tmpctx, struct amount_msat, &msat)); - - /* routing.c does all the hard work; can return NULL. */ - hops = get_route(tmpctx, daemon->rstate, source, &destination, msat, - riskfactor_millionths / 1000000.0, final_cltv, - fuzz_millionths / 1000000.0, pseudorand_u64(), - excluded, max_hops); - - out = towire_gossipd_getroute_reply(NULL, - cast_const2(const struct route_hop **, - hops)); - daemon_conn_send(daemon->master, take(out)); - return daemon_conn_read_next(conn, daemon->master); -} - -/*~ When someone asks lightningd to `listchannels`, gossipd does the work: - * marshalling the channel information for all channels into an array of - * gossip_getchannels_entry, which lightningd converts to JSON. Each channel - * is represented by two half_chan; one in each direction. - */ -static struct gossip_halfchannel_entry *hc_entry(const tal_t *ctx, - const struct chan *chan, - int idx) -{ - /* Our 'struct chan' contains two nodes: they are in pubkey_cmp order - * (ie. chan->nodes[0] is the lesser pubkey) and this is the same as - * the direction bit in `channel_update`s `channel_flags`. - * - * The halfchans are arranged so that half[0] src == nodes[0], and we - * use that here. */ - const struct half_chan *c = &chan->half[idx]; - struct gossip_halfchannel_entry *e; - - /* If we've never seen a channel_update for this direction... */ - if (!is_halfchan_defined(c)) - return NULL; - - e = tal(ctx, struct gossip_halfchannel_entry); - e->channel_flags = c->channel_flags; - e->message_flags = c->message_flags; - e->last_update_timestamp = c->bcast.timestamp; - e->base_fee_msat = c->base_fee; - e->fee_per_millionth = c->proportional_fee; - e->delay = c->delay; - e->min = c->htlc_minimum; - e->max = c->htlc_maximum; - - return e; -} - -/*~ We don't keep channel features in memory; they're rarely used. So we - * remember if it exists, and load it off disk when needed. */ -static u8 *get_channel_features(const tal_t *ctx, - struct gossip_store *gs, - const struct chan *chan) -{ - secp256k1_ecdsa_signature sig; - u8 *features; - struct bitcoin_blkid chain_hash; - struct short_channel_id short_channel_id; - struct node_id node_id; - struct pubkey bitcoin_key; - struct amount_sat sats; - u8 *ann; - - /* This is where we stash a flag to indicate it exists. */ - if (!chan->half[0].any_features) - return NULL; - - ann = cast_const(u8 *, gossip_store_get(tmpctx, gs, chan->bcast.index)); - - /* Could be a private_channel */ - fromwire_gossip_store_private_channel(tmpctx, ann, &sats, &ann); - - if (!fromwire_channel_announcement(ctx, ann, &sig, &sig, &sig, &sig, - &features, &chain_hash, - &short_channel_id, - &node_id, &node_id, - &bitcoin_key, &bitcoin_key)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "bad channel_announcement / local_add_channel at %u: %s", - chan->bcast.index, tal_hex(tmpctx, ann)); - - return features; -} - -/*~ Marshal (possibly) both channel directions into entries. */ -static void append_channel(struct routing_state *rstate, - const struct gossip_getchannels_entry ***entries, - const struct chan *chan, - const struct node_id *srcfilter) -{ - struct gossip_getchannels_entry *e = tal(*entries, struct gossip_getchannels_entry); - - e->node[0] = chan->nodes[0]->id; - e->node[1] = chan->nodes[1]->id; - e->sat = chan->sat; - e->local_disabled = is_chan_local_disabled(rstate, chan); - e->public = is_chan_public(chan); - e->short_channel_id = chan->scid; - e->features = get_channel_features(e, rstate->gs, chan); - if (!srcfilter || node_id_eq(&e->node[0], srcfilter)) - e->e[0] = hc_entry(*entries, chan, 0); - else - e->e[0] = NULL; - if (!srcfilter || node_id_eq(&e->node[1], srcfilter)) - e->e[1] = hc_entry(*entries, chan, 1); - else - e->e[1] = NULL; - - /* We choose not to tell lightningd about channels with no updates, - * as they're unusable and can't be represented in the listchannels - * JSON output we use anyway. */ - if (e->e[0] || e->e[1]) - tal_arr_expand(entries, e); -} - -/*~ This is where lightningd asks for all channels we know about. */ -static struct io_plan *getchannels_req(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) -{ - u8 *out; - const struct gossip_getchannels_entry **entries; - struct chan *chan; - struct short_channel_id *scid, *prev; - struct node_id *source; - bool complete = true; - - /* Note: scid is marked optional in gossip_wire.csv */ - if (!fromwire_gossipd_getchannels_request(msg, msg, &scid, &source, - &prev)) - master_badmsg(WIRE_GOSSIPD_GETCHANNELS_REQUEST, msg); - - entries = tal_arr(tmpctx, const struct gossip_getchannels_entry *, 0); - /* They can ask about a particular channel by short_channel_id */ - if (scid) { - chan = get_channel(daemon->rstate, scid); - if (chan) - append_channel(daemon->rstate, &entries, chan, NULL); - } else if (source) { - struct node *s = get_node(daemon->rstate, source); - if (s) { - struct chan_map_iter i; - struct chan *c; - - for (c = first_chan(s, &i); c; c = next_chan(s, &i)) { - append_channel(daemon->rstate, - &entries, c, source); - } - } - } else { - u64 idx; - - /* For the more general case, we just iterate through every - * short channel id, starting with previous if any (there is - * no scid 0). */ - idx = prev ? prev->u64 : 0; - while ((chan = uintmap_after(&daemon->rstate->chanmap, &idx))) { - append_channel(daemon->rstate, &entries, chan, NULL); - /* Limit how many we do at once. */ - if (tal_count(entries) == 4096) { - complete = false; - break; - } - } - } - - out = towire_gossipd_getchannels_reply(NULL, complete, entries); - daemon_conn_send(daemon->master, take(out)); - return daemon_conn_read_next(conn, daemon->master); -} - -/*~ Similarly, lightningd asks us for all nodes when it gets `listnodes` */ -/* We keep pointers into n, assuming it won't change. */ -static void add_node_entry(const tal_t *ctx, - struct daemon *daemon, - const struct node *n, - struct gossip_getnodes_entry *e) -{ - e->nodeid = n->id; - if (get_node_announcement(ctx, daemon, n, - e->color, e->alias, - &e->features, - &e->addresses)) { - e->last_timestamp = n->bcast.timestamp; - } else { - /* Timestamp on wire is an unsigned 32 bit: we use a 64-bit - * signed, so -1 means "we never received a - * channel_update". */ - e->last_timestamp = -1; - } -} - -/* Simply routine when they ask for `listnodes` */ -static struct io_plan *getnodes(struct io_conn *conn, struct daemon *daemon, - const u8 *msg) -{ - u8 *out; - struct node *n; - const struct gossip_getnodes_entry **nodes; - struct gossip_getnodes_entry *node_arr; - struct node_id *id; - - if (!fromwire_gossipd_getnodes_request(tmpctx, msg, &id)) - master_badmsg(WIRE_GOSSIPD_GETNODES_REQUEST, msg); - - /* Format of reply is the same whether they ask for a specific node - * (0 or one responses) or all nodes (0 or more) */ - if (id) { - n = get_node(daemon->rstate, id); - if (n) { - node_arr = tal_arr(tmpctx, - struct gossip_getnodes_entry, - 1); - add_node_entry(node_arr, daemon, n, &node_arr[0]); - } else { - nodes = NULL; - node_arr = NULL; - } - } else { - struct node_map_iter it; - size_t i = 0; - node_arr = tal_arr(tmpctx, struct gossip_getnodes_entry, - node_map_count(daemon->rstate->nodes)); - n = node_map_first(daemon->rstate->nodes, &it); - while (n != NULL) { - add_node_entry(node_arr, daemon, n, &node_arr[i++]); - n = node_map_next(daemon->rstate->nodes, &it); - } - assert(i == node_map_count(daemon->rstate->nodes)); - } - - /* FIXME: towire wants array of pointers. */ - nodes = tal_arr(tmpctx, const struct gossip_getnodes_entry *, - tal_count(node_arr)); - for (size_t i = 0; i < tal_count(node_arr); i++) - nodes[i] = &node_arr[i]; - out = towire_gossipd_getnodes_reply(NULL, nodes); - daemon_conn_send(daemon->master, take(out)); - return daemon_conn_read_next(conn, daemon->master); -} - /*~ We currently have a JSON command to ping a peer: it ends up here, where * gossipd generates the actual ping and sends it like any other gossip. */ static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon, @@ -1472,81 +1193,6 @@ static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon, return daemon_conn_read_next(conn, daemon->master); } -/*~ If a node has no public channels (other than the one to us), it's not - * a very useful route to tell anyone about. */ -static bool node_has_public_channels(const struct node *peer, - const struct chan *exclude) -{ - struct chan_map_iter i; - struct chan *c; - - for (c = first_chan(peer, &i); c; c = next_chan(peer, &i)) { - if (c == exclude) - continue; - if (is_chan_public(c)) - return true; - } - return false; -} - -/*~ For routeboost, we offer payers a hint of what incoming channels might - * have capacity for their payment. To do this, lightningd asks for the - * information about all channels to this node; but gossipd doesn't know about - * current capacities, so lightningd selects which to use. */ -static struct io_plan *get_incoming_channels(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) -{ - struct node *node; - struct route_info *public = tal_arr(tmpctx, struct route_info, 0); - struct route_info *private = tal_arr(tmpctx, struct route_info, 0); - bool *priv_deadends = tal_arr(tmpctx, bool, 0); - bool *pub_deadends = tal_arr(tmpctx, bool, 0); - - if (!fromwire_gossipd_get_incoming_channels(msg)) - master_badmsg(WIRE_GOSSIPD_GET_INCOMING_CHANNELS, msg); - - node = get_node(daemon->rstate, &daemon->rstate->local_id); - if (node) { - struct chan_map_iter i; - struct chan *c; - - for (c = first_chan(node, &i); c; c = next_chan(node, &i)) { - const struct half_chan *hc; - struct route_info ri; - bool deadend; - - hc = &c->half[half_chan_to(node, c)]; - - if (!is_halfchan_enabled(hc)) - continue; - - ri.pubkey = other_node(node, c)->id; - ri.short_channel_id = c->scid; - ri.fee_base_msat = hc->base_fee; - ri.fee_proportional_millionths = hc->proportional_fee; - ri.cltv_expiry_delta = hc->delay; - - deadend = !node_has_public_channels(other_node(node, c), - c); - if (is_chan_public(c)) { - tal_arr_expand(&public, ri); - tal_arr_expand(&pub_deadends, deadend); - } else { - tal_arr_expand(&private, ri); - tal_arr_expand(&priv_deadends, deadend); - } - } - } - - msg = towire_gossipd_get_incoming_channels_reply(NULL, - public, pub_deadends, - private, priv_deadends); - daemon_conn_send(daemon->master, take(msg)); - - return daemon_conn_read_next(conn, daemon->master); -} - static struct io_plan *new_blockheight(struct io_conn *conn, struct daemon *daemon, const u8 *msg) @@ -1816,15 +1462,6 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_GOSSIPD_INIT: return gossip_init(conn, daemon, msg); - case WIRE_GOSSIPD_GETNODES_REQUEST: - return getnodes(conn, daemon, msg); - - case WIRE_GOSSIPD_GETROUTE_REQUEST: - return getroute_req(conn, daemon, msg); - - case WIRE_GOSSIPD_GETCHANNELS_REQUEST: - return getchannels_req(conn, daemon, msg); - case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE: return get_stripped_cupdate(conn, daemon, msg); @@ -1840,9 +1477,6 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_GOSSIPD_PING: return ping_req(conn, daemon, msg); - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS: - return get_incoming_channels(conn, daemon, msg); - case WIRE_GOSSIPD_NEW_BLOCKHEIGHT: return new_blockheight(conn, daemon, msg); @@ -1872,12 +1506,8 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_GOSSIPD_SEND_ONIONMSG: return onionmsg_req(conn, daemon, msg); /* We send these, we don't receive them */ - case WIRE_GOSSIPD_GETNODES_REPLY: - case WIRE_GOSSIPD_GETROUTE_REPLY: - case WIRE_GOSSIPD_GETCHANNELS_REPLY: case WIRE_GOSSIPD_PING_REPLY: case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE_REPLY: - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY: case WIRE_GOSSIPD_GET_TXOUT: case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY: case WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY: diff --git a/gossipd/gossipd_wire.csv b/gossipd/gossipd_wire.csv index f9b6e0f61939..bb51590e2803 100644 --- a/gossipd/gossipd_wire.csv +++ b/gossipd/gossipd_wire.csv @@ -20,42 +20,6 @@ msgdata,gossipd_init,dev_fast_gossip_prune,bool, msgtype,gossipd_dev_set_time,3001 msgdata,gossipd_dev_set_time,dev_gossip_time,u32, -# Pass JSON-RPC getnodes call through -msgtype,gossipd_getnodes_request,3005 -msgdata,gossipd_getnodes_request,id,?node_id, - -#include -msgtype,gossipd_getnodes_reply,3105 -msgdata,gossipd_getnodes_reply,num_nodes,u32, -msgdata,gossipd_getnodes_reply,nodes,gossip_getnodes_entry,num_nodes - -# Pass JSON-RPC getroute call through -msgtype,gossipd_getroute_request,3006 -# Source defaults to "us", and means we don't consider first-hop channel fees -msgdata,gossipd_getroute_request,source,?node_id, -msgdata,gossipd_getroute_request,destination,node_id, -msgdata,gossipd_getroute_request,msatoshi,amount_msat, -msgdata,gossipd_getroute_request,riskfactor_millionths,u64, -msgdata,gossipd_getroute_request,final_cltv,u32, -msgdata,gossipd_getroute_request,fuzz_millionths,u64, -msgdata,gossipd_getroute_request,num_excluded,u16, -msgdata,gossipd_getroute_request,excluded,exclude_entry,num_excluded -msgdata,gossipd_getroute_request,max_hops,u32, - -msgtype,gossipd_getroute_reply,3106 -msgdata,gossipd_getroute_reply,num_hops,u16, -msgdata,gossipd_getroute_reply,hops,route_hop,num_hops - -msgtype,gossipd_getchannels_request,3007 -msgdata,gossipd_getchannels_request,short_channel_id,?short_channel_id, -msgdata,gossipd_getchannels_request,source,?node_id, -msgdata,gossipd_getchannels_request,prev,?short_channel_id, - -msgtype,gossipd_getchannels_reply,3107 -msgdata,gossipd_getchannels_reply,complete,bool, -msgdata,gossipd_getchannels_reply,num_channels,u32, -msgdata,gossipd_getchannels_reply,nodes,gossip_getchannels_entry,num_channels - # Ping/pong test. Waits for a reply if it expects one. msgtype,gossipd_ping,3008 msgdata,gossipd_ping,id,node_id, @@ -116,20 +80,6 @@ msgtype,gossipd_dev_compact_store,3034 msgtype,gossipd_dev_compact_store_reply,3134 msgdata,gossipd_dev_compact_store_reply,success,bool, -#include - -# master -> gossipd: get route_info for our incoming channels -msgtype,gossipd_get_incoming_channels,3025 - -# gossipd -> master: here they are. -msgtype,gossipd_get_incoming_channels_reply,3125 -msgdata,gossipd_get_incoming_channels_reply,num_public,u16, -msgdata,gossipd_get_incoming_channels_reply,public_route_info,route_info,num_public -msgdata,gossipd_get_incoming_channels_reply,public_deadends,bool,num_public -msgdata,gossipd_get_incoming_channels_reply,num_private,u16, -msgdata,gossipd_get_incoming_channels_reply,private_route_info,route_info,num_private -msgdata,gossipd_get_incoming_channels_reply,private_deadends,bool,num_private - # master -> gossipd: blockheight increased. msgtype,gossipd_new_blockheight,3026 msgdata,gossipd_new_blockheight,blockheight,u32, diff --git a/gossipd/gossipd_wiregen.c b/gossipd/gossipd_wiregen.c index 6e86ca01e0e8..e779e960192f 100644 --- a/gossipd/gossipd_wiregen.c +++ b/gossipd/gossipd_wiregen.c @@ -22,12 +22,6 @@ const char *gossipd_wire_name(int e) switch ((enum gossipd_wire)e) { case WIRE_GOSSIPD_INIT: return "WIRE_GOSSIPD_INIT"; case WIRE_GOSSIPD_DEV_SET_TIME: return "WIRE_GOSSIPD_DEV_SET_TIME"; - case WIRE_GOSSIPD_GETNODES_REQUEST: return "WIRE_GOSSIPD_GETNODES_REQUEST"; - case WIRE_GOSSIPD_GETNODES_REPLY: return "WIRE_GOSSIPD_GETNODES_REPLY"; - case WIRE_GOSSIPD_GETROUTE_REQUEST: return "WIRE_GOSSIPD_GETROUTE_REQUEST"; - case WIRE_GOSSIPD_GETROUTE_REPLY: return "WIRE_GOSSIPD_GETROUTE_REPLY"; - case WIRE_GOSSIPD_GETCHANNELS_REQUEST: return "WIRE_GOSSIPD_GETCHANNELS_REQUEST"; - case WIRE_GOSSIPD_GETCHANNELS_REPLY: return "WIRE_GOSSIPD_GETCHANNELS_REPLY"; case WIRE_GOSSIPD_PING: return "WIRE_GOSSIPD_PING"; case WIRE_GOSSIPD_PING_REPLY: return "WIRE_GOSSIPD_PING_REPLY"; case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: return "WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE"; @@ -42,8 +36,6 @@ const char *gossipd_wire_name(int e) case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY: return "WIRE_GOSSIPD_DEV_MEMLEAK_REPLY"; case WIRE_GOSSIPD_DEV_COMPACT_STORE: return "WIRE_GOSSIPD_DEV_COMPACT_STORE"; case WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY: return "WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY"; - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS: return "WIRE_GOSSIPD_GET_INCOMING_CHANNELS"; - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY: return "WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY"; case WIRE_GOSSIPD_NEW_BLOCKHEIGHT: return "WIRE_GOSSIPD_NEW_BLOCKHEIGHT"; case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US: return "WIRE_GOSSIPD_GOT_ONIONMSG_TO_US"; case WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD: return "WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD"; @@ -61,12 +53,6 @@ bool gossipd_wire_is_defined(u16 type) switch ((enum gossipd_wire)type) { case WIRE_GOSSIPD_INIT:; case WIRE_GOSSIPD_DEV_SET_TIME:; - case WIRE_GOSSIPD_GETNODES_REQUEST:; - case WIRE_GOSSIPD_GETNODES_REPLY:; - case WIRE_GOSSIPD_GETROUTE_REQUEST:; - case WIRE_GOSSIPD_GETROUTE_REPLY:; - case WIRE_GOSSIPD_GETCHANNELS_REQUEST:; - case WIRE_GOSSIPD_GETCHANNELS_REPLY:; case WIRE_GOSSIPD_PING:; case WIRE_GOSSIPD_PING_REPLY:; case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE:; @@ -81,8 +67,6 @@ bool gossipd_wire_is_defined(u16 type) case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY:; case WIRE_GOSSIPD_DEV_COMPACT_STORE:; case WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY:; - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS:; - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY:; case WIRE_GOSSIPD_NEW_BLOCKHEIGHT:; case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US:; case WIRE_GOSSIPD_GOT_ONIONMSG_FORWARD:; @@ -177,242 +161,6 @@ bool fromwire_gossipd_dev_set_time(const void *p, u32 *dev_gossip_time) return cursor != NULL; } -/* WIRE: GOSSIPD_GETNODES_REQUEST */ -/* Pass JSON-RPC getnodes call through */ -u8 *towire_gossipd_getnodes_request(const tal_t *ctx, const struct node_id *id) -{ - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GETNODES_REQUEST); - if (!id) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_node_id(&p, id); - } - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_getnodes_request(const tal_t *ctx, const void *p, struct node_id **id) -{ - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GETNODES_REQUEST) - return false; - if (!fromwire_bool(&cursor, &plen)) - *id = NULL; - else { - *id = tal(ctx, struct node_id); - fromwire_node_id(&cursor, &plen, *id); - } - return cursor != NULL; -} - -/* WIRE: GOSSIPD_GETNODES_REPLY */ -u8 *towire_gossipd_getnodes_reply(const tal_t *ctx, const struct gossip_getnodes_entry **nodes) -{ - u32 num_nodes = tal_count(nodes); - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GETNODES_REPLY); - towire_u32(&p, num_nodes); - for (size_t i = 0; i < num_nodes; i++) - towire_gossip_getnodes_entry(&p, nodes[i]); - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_getnodes_reply(const tal_t *ctx, const void *p, struct gossip_getnodes_entry ***nodes) -{ - u32 num_nodes; - - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GETNODES_REPLY) - return false; - num_nodes = fromwire_u32(&cursor, &plen); - // 2nd case nodes - *nodes = num_nodes ? tal_arr(ctx, struct gossip_getnodes_entry *, num_nodes) : NULL; - for (size_t i = 0; i < num_nodes; i++) - (*nodes)[i] = fromwire_gossip_getnodes_entry(*nodes, &cursor, &plen); - return cursor != NULL; -} - -/* WIRE: GOSSIPD_GETROUTE_REQUEST */ -/* Pass JSON-RPC getroute call through */ -u8 *towire_gossipd_getroute_request(const tal_t *ctx, const struct node_id *source, const struct node_id *destination, struct amount_msat msatoshi, u64 riskfactor_millionths, u32 final_cltv, u64 fuzz_millionths, const struct exclude_entry **excluded, u32 max_hops) -{ - u16 num_excluded = tal_count(excluded); - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GETROUTE_REQUEST); - /* Source defaults to "us" */ - if (!source) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_node_id(&p, source); - } - towire_node_id(&p, destination); - towire_amount_msat(&p, msatoshi); - towire_u64(&p, riskfactor_millionths); - towire_u32(&p, final_cltv); - towire_u64(&p, fuzz_millionths); - towire_u16(&p, num_excluded); - for (size_t i = 0; i < num_excluded; i++) - towire_exclude_entry(&p, excluded[i]); - towire_u32(&p, max_hops); - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_getroute_request(const tal_t *ctx, const void *p, struct node_id **source, struct node_id *destination, struct amount_msat *msatoshi, u64 *riskfactor_millionths, u32 *final_cltv, u64 *fuzz_millionths, struct exclude_entry ***excluded, u32 *max_hops) -{ - u16 num_excluded; - - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GETROUTE_REQUEST) - return false; - /* Source defaults to "us" */ - if (!fromwire_bool(&cursor, &plen)) - *source = NULL; - else { - *source = tal(ctx, struct node_id); - fromwire_node_id(&cursor, &plen, *source); - } - fromwire_node_id(&cursor, &plen, destination); - *msatoshi = fromwire_amount_msat(&cursor, &plen); - *riskfactor_millionths = fromwire_u64(&cursor, &plen); - *final_cltv = fromwire_u32(&cursor, &plen); - *fuzz_millionths = fromwire_u64(&cursor, &plen); - num_excluded = fromwire_u16(&cursor, &plen); - // 2nd case excluded - *excluded = num_excluded ? tal_arr(ctx, struct exclude_entry *, num_excluded) : NULL; - for (size_t i = 0; i < num_excluded; i++) - (*excluded)[i] = fromwire_exclude_entry(*excluded, &cursor, &plen); - *max_hops = fromwire_u32(&cursor, &plen); - return cursor != NULL; -} - -/* WIRE: GOSSIPD_GETROUTE_REPLY */ -u8 *towire_gossipd_getroute_reply(const tal_t *ctx, const struct route_hop **hops) -{ - u16 num_hops = tal_count(hops); - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GETROUTE_REPLY); - towire_u16(&p, num_hops); - for (size_t i = 0; i < num_hops; i++) - towire_route_hop(&p, hops[i]); - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_getroute_reply(const tal_t *ctx, const void *p, struct route_hop ***hops) -{ - u16 num_hops; - - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GETROUTE_REPLY) - return false; - num_hops = fromwire_u16(&cursor, &plen); - // 2nd case hops - *hops = num_hops ? tal_arr(ctx, struct route_hop *, num_hops) : NULL; - for (size_t i = 0; i < num_hops; i++) - (*hops)[i] = fromwire_route_hop(*hops, &cursor, &plen); - return cursor != NULL; -} - -/* WIRE: GOSSIPD_GETCHANNELS_REQUEST */ -u8 *towire_gossipd_getchannels_request(const tal_t *ctx, const struct short_channel_id *short_channel_id, const struct node_id *source, const struct short_channel_id *prev) -{ - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GETCHANNELS_REQUEST); - if (!short_channel_id) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_short_channel_id(&p, short_channel_id); - } - if (!source) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_node_id(&p, source); - } - if (!prev) - towire_bool(&p, false); - else { - towire_bool(&p, true); - towire_short_channel_id(&p, prev); - } - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_getchannels_request(const tal_t *ctx, const void *p, struct short_channel_id **short_channel_id, struct node_id **source, struct short_channel_id **prev) -{ - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GETCHANNELS_REQUEST) - return false; - if (!fromwire_bool(&cursor, &plen)) - *short_channel_id = NULL; - else { - *short_channel_id = tal(ctx, struct short_channel_id); - fromwire_short_channel_id(&cursor, &plen, *short_channel_id); - } - if (!fromwire_bool(&cursor, &plen)) - *source = NULL; - else { - *source = tal(ctx, struct node_id); - fromwire_node_id(&cursor, &plen, *source); - } - if (!fromwire_bool(&cursor, &plen)) - *prev = NULL; - else { - *prev = tal(ctx, struct short_channel_id); - fromwire_short_channel_id(&cursor, &plen, *prev); - } - return cursor != NULL; -} - -/* WIRE: GOSSIPD_GETCHANNELS_REPLY */ -u8 *towire_gossipd_getchannels_reply(const tal_t *ctx, bool complete, const struct gossip_getchannels_entry **nodes) -{ - u32 num_channels = tal_count(nodes); - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GETCHANNELS_REPLY); - towire_bool(&p, complete); - towire_u32(&p, num_channels); - for (size_t i = 0; i < num_channels; i++) - towire_gossip_getchannels_entry(&p, nodes[i]); - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_getchannels_reply(const tal_t *ctx, const void *p, bool *complete, struct gossip_getchannels_entry ***nodes) -{ - u32 num_channels; - - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GETCHANNELS_REPLY) - return false; - *complete = fromwire_bool(&cursor, &plen); - num_channels = fromwire_u32(&cursor, &plen); - // 2nd case nodes - *nodes = num_channels ? tal_arr(ctx, struct gossip_getchannels_entry *, num_channels) : NULL; - for (size_t i = 0; i < num_channels; i++) - (*nodes)[i] = fromwire_gossip_getchannels_entry(*nodes, &cursor, &plen); - return cursor != NULL; -} - /* WIRE: GOSSIPD_PING */ /* Ping/pong test. Waits for a reply if it expects one. */ u8 *towire_gossipd_ping(const tal_t *ctx, const struct node_id *id, u16 num_pong_bytes, u16 len) @@ -742,79 +490,6 @@ bool fromwire_gossipd_dev_compact_store_reply(const void *p, bool *success) return cursor != NULL; } -/* WIRE: GOSSIPD_GET_INCOMING_CHANNELS */ -/* master -> gossipd: get route_info for our incoming channels */ -u8 *towire_gossipd_get_incoming_channels(const tal_t *ctx) -{ - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GET_INCOMING_CHANNELS); - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_get_incoming_channels(const void *p) -{ - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GET_INCOMING_CHANNELS) - return false; - return cursor != NULL; -} - -/* WIRE: GOSSIPD_GET_INCOMING_CHANNELS_REPLY */ -/* gossipd -> master: here they are. */ -u8 *towire_gossipd_get_incoming_channels_reply(const tal_t *ctx, const struct route_info *public_route_info, const bool *public_deadends, const struct route_info *private_route_info, const bool *private_deadends) -{ - u16 num_public = tal_count(public_deadends); - u16 num_private = tal_count(private_deadends); - u8 *p = tal_arr(ctx, u8, 0); - - towire_u16(&p, WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY); - towire_u16(&p, num_public); - for (size_t i = 0; i < num_public; i++) - towire_route_info(&p, public_route_info + i); - for (size_t i = 0; i < num_public; i++) - towire_bool(&p, public_deadends[i]); - towire_u16(&p, num_private); - for (size_t i = 0; i < num_private; i++) - towire_route_info(&p, private_route_info + i); - for (size_t i = 0; i < num_private; i++) - towire_bool(&p, private_deadends[i]); - - return memcheck(p, tal_count(p)); -} -bool fromwire_gossipd_get_incoming_channels_reply(const tal_t *ctx, const void *p, struct route_info **public_route_info, bool **public_deadends, struct route_info **private_route_info, bool **private_deadends) -{ - u16 num_public; - u16 num_private; - - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY) - return false; - num_public = fromwire_u16(&cursor, &plen); - // 2nd case public_route_info - *public_route_info = num_public ? tal_arr(ctx, struct route_info, num_public) : NULL; - for (size_t i = 0; i < num_public; i++) - fromwire_route_info(&cursor, &plen, *public_route_info + i); - // 2nd case public_deadends - *public_deadends = num_public ? tal_arr(ctx, bool, num_public) : NULL; - for (size_t i = 0; i < num_public; i++) - (*public_deadends)[i] = fromwire_bool(&cursor, &plen); - num_private = fromwire_u16(&cursor, &plen); - // 2nd case private_route_info - *private_route_info = num_private ? tal_arr(ctx, struct route_info, num_private) : NULL; - for (size_t i = 0; i < num_private; i++) - fromwire_route_info(&cursor, &plen, *private_route_info + i); - // 2nd case private_deadends - *private_deadends = num_private ? tal_arr(ctx, bool, num_private) : NULL; - for (size_t i = 0; i < num_private; i++) - (*private_deadends)[i] = fromwire_bool(&cursor, &plen); - return cursor != NULL; -} - /* WIRE: GOSSIPD_NEW_BLOCKHEIGHT */ /* master -> gossipd: blockheight increased. */ u8 *towire_gossipd_new_blockheight(const tal_t *ctx, u32 blockheight) @@ -1057,4 +732,4 @@ bool fromwire_gossipd_addgossip_reply(const tal_t *ctx, const void *p, wirestrin *err = fromwire_wirestring(ctx, &cursor, &plen); return cursor != NULL; } -// SHA256STAMP:a0d7494995d7f95fb7df295bab9d865e18670f15243116a0aaa9b9548534b922 +// SHA256STAMP:bc9045727cefbbe29118c8eae928972fe009a4d9d8c9e903f8b35f006973f462 diff --git a/gossipd/gossipd_wiregen.h b/gossipd/gossipd_wiregen.h index 0e989c517672..5059fb559d93 100644 --- a/gossipd/gossipd_wiregen.h +++ b/gossipd/gossipd_wiregen.h @@ -11,22 +11,12 @@ #include #include #include -#include -#include enum gossipd_wire { /* Initialize the gossip daemon. */ WIRE_GOSSIPD_INIT = 3000, /* In developer mode */ WIRE_GOSSIPD_DEV_SET_TIME = 3001, - /* Pass JSON-RPC getnodes call through */ - WIRE_GOSSIPD_GETNODES_REQUEST = 3005, - WIRE_GOSSIPD_GETNODES_REPLY = 3105, - /* Pass JSON-RPC getroute call through */ - WIRE_GOSSIPD_GETROUTE_REQUEST = 3006, - WIRE_GOSSIPD_GETROUTE_REPLY = 3106, - WIRE_GOSSIPD_GETCHANNELS_REQUEST = 3007, - WIRE_GOSSIPD_GETCHANNELS_REPLY = 3107, /* Ping/pong test. Waits for a reply if it expects one. */ WIRE_GOSSIPD_PING = 3008, WIRE_GOSSIPD_PING_REPLY = 3108, @@ -52,10 +42,6 @@ enum gossipd_wire { WIRE_GOSSIPD_DEV_COMPACT_STORE = 3034, /* gossipd -> master: ok */ WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY = 3134, - /* master -> gossipd: get route_info for our incoming channels */ - WIRE_GOSSIPD_GET_INCOMING_CHANNELS = 3025, - /* gossipd -> master: here they are. */ - WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY = 3125, /* master -> gossipd: blockheight increased. */ WIRE_GOSSIPD_NEW_BLOCKHEIGHT = 3026, /* Tell lightningd we got a onion message (for us */ @@ -91,32 +77,6 @@ bool fromwire_gossipd_init(const tal_t *ctx, const void *p, const struct chainpa u8 *towire_gossipd_dev_set_time(const tal_t *ctx, u32 dev_gossip_time); bool fromwire_gossipd_dev_set_time(const void *p, u32 *dev_gossip_time); -/* WIRE: GOSSIPD_GETNODES_REQUEST */ -/* Pass JSON-RPC getnodes call through */ -u8 *towire_gossipd_getnodes_request(const tal_t *ctx, const struct node_id *id); -bool fromwire_gossipd_getnodes_request(const tal_t *ctx, const void *p, struct node_id **id); - -/* WIRE: GOSSIPD_GETNODES_REPLY */ -u8 *towire_gossipd_getnodes_reply(const tal_t *ctx, const struct gossip_getnodes_entry **nodes); -bool fromwire_gossipd_getnodes_reply(const tal_t *ctx, const void *p, struct gossip_getnodes_entry ***nodes); - -/* WIRE: GOSSIPD_GETROUTE_REQUEST */ -/* Pass JSON-RPC getroute call through */ -u8 *towire_gossipd_getroute_request(const tal_t *ctx, const struct node_id *source, const struct node_id *destination, struct amount_msat msatoshi, u64 riskfactor_millionths, u32 final_cltv, u64 fuzz_millionths, const struct exclude_entry **excluded, u32 max_hops); -bool fromwire_gossipd_getroute_request(const tal_t *ctx, const void *p, struct node_id **source, struct node_id *destination, struct amount_msat *msatoshi, u64 *riskfactor_millionths, u32 *final_cltv, u64 *fuzz_millionths, struct exclude_entry ***excluded, u32 *max_hops); - -/* WIRE: GOSSIPD_GETROUTE_REPLY */ -u8 *towire_gossipd_getroute_reply(const tal_t *ctx, const struct route_hop **hops); -bool fromwire_gossipd_getroute_reply(const tal_t *ctx, const void *p, struct route_hop ***hops); - -/* WIRE: GOSSIPD_GETCHANNELS_REQUEST */ -u8 *towire_gossipd_getchannels_request(const tal_t *ctx, const struct short_channel_id *short_channel_id, const struct node_id *source, const struct short_channel_id *prev); -bool fromwire_gossipd_getchannels_request(const tal_t *ctx, const void *p, struct short_channel_id **short_channel_id, struct node_id **source, struct short_channel_id **prev); - -/* WIRE: GOSSIPD_GETCHANNELS_REPLY */ -u8 *towire_gossipd_getchannels_reply(const tal_t *ctx, bool complete, const struct gossip_getchannels_entry **nodes); -bool fromwire_gossipd_getchannels_reply(const tal_t *ctx, const void *p, bool *complete, struct gossip_getchannels_entry ***nodes); - /* WIRE: GOSSIPD_PING */ /* Ping/pong test. Waits for a reply if it expects one. */ u8 *towire_gossipd_ping(const tal_t *ctx, const struct node_id *id, u16 num_pong_bytes, u16 len); @@ -184,16 +144,6 @@ bool fromwire_gossipd_dev_compact_store(const void *p); u8 *towire_gossipd_dev_compact_store_reply(const tal_t *ctx, bool success); bool fromwire_gossipd_dev_compact_store_reply(const void *p, bool *success); -/* WIRE: GOSSIPD_GET_INCOMING_CHANNELS */ -/* master -> gossipd: get route_info for our incoming channels */ -u8 *towire_gossipd_get_incoming_channels(const tal_t *ctx); -bool fromwire_gossipd_get_incoming_channels(const void *p); - -/* WIRE: GOSSIPD_GET_INCOMING_CHANNELS_REPLY */ -/* gossipd -> master: here they are. */ -u8 *towire_gossipd_get_incoming_channels_reply(const tal_t *ctx, const struct route_info *public_route_info, const bool *public_deadends, const struct route_info *private_route_info, const bool *private_deadends); -bool fromwire_gossipd_get_incoming_channels_reply(const tal_t *ctx, const void *p, struct route_info **public_route_info, bool **public_deadends, struct route_info **private_route_info, bool **private_deadends); - /* WIRE: GOSSIPD_NEW_BLOCKHEIGHT */ /* master -> gossipd: blockheight increased. */ u8 *towire_gossipd_new_blockheight(const tal_t *ctx, u32 blockheight); @@ -225,4 +175,4 @@ bool fromwire_gossipd_addgossip_reply(const tal_t *ctx, const void *p, wirestrin #endif /* LIGHTNING_GOSSIPD_GOSSIPD_WIREGEN_H */ -// SHA256STAMP:a0d7494995d7f95fb7df295bab9d865e18670f15243116a0aaa9b9548534b922 +// SHA256STAMP:bc9045727cefbbe29118c8eae928972fe009a4d9d8c9e903f8b35f006973f462 diff --git a/gossipd/routing.c b/gossipd/routing.c index 96e24d9ae257..fabb469d6b55 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -94,8 +94,6 @@ HTABLE_DEFINE_TYPE(struct pending_node_announce, pending_node_announce_keyof, struct unupdated_channel { /* The channel_announcement message */ const u8 *channel_announce; - /* The feature bitmap within it */ - const u8 *features; /* The short_channel_id */ struct short_channel_id scid; /* The ids of the nodes */ @@ -381,8 +379,6 @@ static struct node *new_node(struct routing_state *rstate, n->id = *id; memset(n->chans.arr, 0, sizeof(n->chans.arr)); broadcastable_init(&n->bcast); - /* We don't know, so assume legacy. */ - n->hop_style = ROUTE_HOP_LEGACY; n->tokens = TOKEN_MAX; node_map_add(rstate->nodes, n); tal_add_destructor2(n, destroy_node, rstate); @@ -522,10 +518,6 @@ static void init_half_chan(struct routing_state *rstate, { struct half_chan *c = &chan->half[channel_idx]; - /* Set the channel direction */ - c->channel_flags = channel_idx; - // TODO: wireup message_flags - c->message_flags = 0; broadcastable_init(&c->bcast); c->tokens = TOKEN_MAX; } @@ -574,8 +566,7 @@ struct chan *new_chan(struct routing_state *rstate, const struct short_channel_id *scid, const struct node_id *id1, const struct node_id *id2, - struct amount_sat satoshis, - const u8 *features) + struct amount_sat satoshis) { struct chan *chan = tal(rstate, struct chan); int n1idx = node_id_idx(id1, id2); @@ -610,8 +601,6 @@ struct chan *new_chan(struct routing_state *rstate, init_half_chan(rstate, chan, n1idx); init_half_chan(rstate, chan, !n1idx); - /* Stash hint here about whether we have features */ - chan->half[0].any_features = tal_bytelen(features) != 0; uintmap_add(&rstate->chanmap, scid->u64, chan); /* Initialize shadow structure if it's local */ @@ -619,755 +608,6 @@ struct chan *new_chan(struct routing_state *rstate, return chan; } -/* Too big to reach, but don't overflow if added. */ -#define INFINITE AMOUNT_MSAT(0x3FFFFFFFFFFFFFFFULL) - -/* We hack a multimap into a uintmap to implement a minheap by cost. - * This is relatively inefficient, containing an array for each cost - * value, assuming there aren't too many at same cost. - * - * We further optimize by never freeing or shrinking these entries, - * but delete by replacing with NULL. This means that we cache the - * lowest index which actually contains something, since others may - * contain empty arrays. */ -struct unvisited { - u64 min_index; - UINTMAP(struct node **) map; -}; - - -/* Risk of passing through this channel. - * - * There are two ways this function is used: - * - * 1. Normally, riskbias = 1. A tiny bias here in order to prefer - * shorter routes, all things equal. - * 2. Trying to find a shorter route, riskbias > 1. By adding an extra - * cost to every hop, we're trying to bias against overlength routes. - */ -static WARN_UNUSED_RESULT bool risk_add_fee(struct amount_msat *risk, - struct amount_msat msat, - u32 delay, double riskfactor, - u64 riskbias) -{ - struct amount_msat riskfee; - - if (!amount_msat_scale(&riskfee, msat, riskfactor * delay)) - return false; - if (!amount_msat_add(&riskfee, riskfee, amount_msat(riskbias))) - return false; - return amount_msat_add(risk, *risk, riskfee); -} - -/* Check that we can fit through this channel's indicated - * maximum_ and minimum_msat requirements. - */ -static bool hc_can_carry(const struct half_chan *hc, - struct amount_msat requiredcap) -{ - return amount_msat_greater_eq(hc->htlc_maximum, requiredcap) && - amount_msat_less_eq(hc->htlc_minimum, requiredcap); -} - -/* Theoretically, this could overflow. */ -static bool fuzz_fee(u64 *fee, - const struct short_channel_id *scid, - double fuzz, const struct siphash_seed *base_seed) -{ - u64 fuzzed_fee, h; - double fee_scale; - - if (fuzz == 0.0) - return true; - - h = siphash24(base_seed, scid, sizeof(*scid)); - - /* Scale fees for this channel */ - /* rand = (h / UINT64_MAX) random number between 0.0 -> 1.0 - * 2*fuzz*rand random number between 0.0 -> 2*fuzz - * 2*fuzz*rand - fuzz random number between -fuzz -> +fuzz - */ - fee_scale = 1.0 + (2.0 * fuzz * h / (double)UINT64_MAX) - fuzz; - fuzzed_fee = *fee * fee_scale; - if (fee_scale > 1.0 && fuzzed_fee < *fee) - return false; - *fee = fuzzed_fee; - return true; -} - -/* Can we carry this amount across the channel? If so, returns true and - * sets newtotal and newrisk */ -static bool can_reach(const struct half_chan *c, - const struct short_channel_id *scid, - bool no_charge, - struct amount_msat total, - struct amount_msat risk, - double riskfactor, - u64 riskbias, - double fuzz, const struct siphash_seed *base_seed, - struct amount_msat *newtotal, struct amount_msat *newrisk) -{ - /* FIXME: Bias against smaller channels. */ - struct amount_msat fee; - - if (!amount_msat_fee(&fee, total, c->base_fee, c->proportional_fee)) - return false; - - if (!fuzz_fee(&fee.millisatoshis, scid, fuzz, base_seed)) /* Raw: double manipulation */ - return false; - - if (no_charge) { - *newtotal = total; - - /* We still want to consider the "charge", since it's indicative - * of a bias (we discounted one channel for a reason), but we - * don't pay it. So we count it as additional risk. */ - if (!amount_msat_add(newrisk, risk, fee)) - return false; - } else { - *newrisk = risk; - - if (!amount_msat_add(newtotal, total, fee)) - return false; - } - - /* Skip a channel if it indicated that it won't route the - * requested amount. */ - if (!hc_can_carry(c, *newtotal)) - return false; - - if (!risk_add_fee(newrisk, *newtotal, c->delay, riskfactor, riskbias)) - return false; - - return true; -} - -/* Returns false on overflow (shouldn't happen!) */ -typedef bool WARN_UNUSED_RESULT costfn_t(struct amount_msat *, - struct amount_msat, - struct amount_msat); - -static WARN_UNUSED_RESULT bool -normal_cost_function(struct amount_msat *cost, - struct amount_msat total, struct amount_msat risk) -{ - if (amount_msat_add(cost, total, risk)) - return true; - - status_broken("Can't add cost of node %s + %s", - type_to_string(tmpctx, struct amount_msat, &total), - type_to_string(tmpctx, struct amount_msat, &risk)); - return false; -} - -static WARN_UNUSED_RESULT bool -shortest_cost_function(struct amount_msat *cost, - struct amount_msat total, struct amount_msat risk) -{ - /* We add 1, so cost is never 0, for our hacky uintmap-as-minheap. */ - if (amount_msat_add(cost, risk, AMOUNT_MSAT(1))) - return true; - - status_broken("Can't add 1 to risk of node %s", - type_to_string(tmpctx, struct amount_msat, &risk)); - return false; -} - -/* Does totala+riska add up to less than totalb+riskb? - * Saves sums if you want them. - */ -static bool costs_less(struct amount_msat totala, - struct amount_msat riska, - struct amount_msat *costa, - struct amount_msat totalb, - struct amount_msat riskb, - struct amount_msat *costb, - costfn_t *costfn) -{ - struct amount_msat suma, sumb; - - if (!costfn(&suma, totala, riska)) - return false; - if (!costfn(&sumb, totalb, riskb)) - return false; - - if (costa) - *costa = suma; - if (costb) - *costb = sumb; - return amount_msat_less(suma, sumb); -} - -/* Determine if the given half_chan is routable */ -static bool hc_is_routable(struct routing_state *rstate, - const struct chan *chan, int idx) -{ - return is_halfchan_enabled(&chan->half[idx]) - && !is_chan_local_disabled(rstate, chan); -} - -static void unvisited_add(struct unvisited *unvisited, struct amount_msat cost, - struct node **arr) -{ - u64 idx = cost.millisatoshis; /* Raw: uintmap needs u64 index */ - if (idx < unvisited->min_index) { - assert(idx); /* We don't allow sending 0 satoshis */ - unvisited->min_index = idx - 1; - } - uintmap_add(&unvisited->map, idx, arr); -} - -static struct node **unvisited_get(const struct unvisited *unvisited, - struct amount_msat cost) -{ - return uintmap_get(&unvisited->map, cost.millisatoshis); /* Raw: uintmap */ -} - -static struct node **unvisited_del(struct unvisited *unvisited, - struct amount_msat cost) -{ - return uintmap_del(&unvisited->map, cost.millisatoshis); /* Raw: uintmap */ -} - -static bool is_unvisited(const struct node *node, - const struct unvisited *unvisited, - costfn_t *costfn) -{ - struct node **arr; - struct amount_msat cost; - - /* If it's infinite, definitely unvisited */ - if (amount_msat_eq(node->dijkstra.total, INFINITE)) - return true; - - /* Shouldn't happen! */ - if (!costfn(&cost, node->dijkstra.total, node->dijkstra.risk)) - return false; - - arr = unvisited_get(unvisited, cost); - for (size_t i = 0; i < tal_count(arr); i++) { - if (arr[i] == node) - return true; - } - return false; -} - -static void unvisited_del_node(struct unvisited *unvisited, - struct amount_msat cost, - const struct node *node) -{ - struct node **arr; - - arr = unvisited_get(unvisited, cost); - for (size_t i = 0; i < tal_count(arr); i++) { - if (arr[i] == node) { - arr[i] = NULL; - return; - } - } - abort(); -} - -static void adjust_unvisited(struct node *node, - struct unvisited *unvisited, - struct amount_msat cost_before, - struct amount_msat total, - struct amount_msat risk, - struct amount_msat cost_after) -{ - struct node **arr; - - /* If it was in unvisited map, remove it. */ - if (!amount_msat_eq(node->dijkstra.total, INFINITE)) - unvisited_del_node(unvisited, cost_before, node); - - /* Update node */ - node->dijkstra.total = total; - node->dijkstra.risk = risk; - - SUPERVERBOSE("%s now cost %s", - type_to_string(tmpctx, struct node_id, &node->id), - type_to_string(tmpctx, struct amount_msat, &cost_after)); - - /* Update map of unvisited nodes */ - arr = unvisited_get(unvisited, cost_after); - if (arr) { - struct node **old_arr; - /* Try for empty slot */ - for (size_t i = 0; i < tal_count(arr); i++) { - if (arr[i] == NULL) { - arr[i] = node; - return; - } - } - /* Nope, expand */ - old_arr = arr; - tal_arr_expand(&arr, node); - if (arr == old_arr) - return; - - /* Realloc moved it; del and add again. */ - unvisited_del(unvisited, cost_after); - } else { - arr = tal_arr(unvisited, struct node *, 1); - arr[0] = node; - } - - unvisited_add(unvisited, cost_after, arr); -} - -static void remove_unvisited(struct node *node, struct unvisited *unvisited, - costfn_t *costfn) -{ - struct amount_msat cost; - - /* Shouldn't happen! */ - if (!costfn(&cost, node->dijkstra.total, node->dijkstra.risk)) - return; - - unvisited_del_node(unvisited, cost, node); -} - -static void update_unvisited_neighbors(struct routing_state *rstate, - struct node *cur, - const struct node *me, - double riskfactor, - u64 riskbias, - double fuzz, - const struct siphash_seed *base_seed, - struct unvisited *unvisited, - costfn_t *costfn) -{ - struct chan_map_iter i; - struct chan *chan; - - /* Consider all neighbors */ - for (chan = first_chan(cur, &i); chan; chan = next_chan(cur, &i)) { - struct amount_msat total, risk, cost_before, cost_after; - int idx = half_chan_to(cur, chan); - struct node *peer = chan->nodes[idx]; - - SUPERVERBOSE("CONSIDERING: %s -> %s (%s/%s)", - type_to_string(tmpctx, struct node_id, - &cur->id), - type_to_string(tmpctx, struct node_id, - &peer->id), - type_to_string(tmpctx, struct amount_msat, - &peer->dijkstra.total), - type_to_string(tmpctx, struct amount_msat, - &peer->dijkstra.risk)); - - if (!hc_is_routable(rstate, chan, idx)) { - SUPERVERBOSE("... not routable"); - continue; - } - - if (!is_unvisited(peer, unvisited, costfn)) { - SUPERVERBOSE("... already visited"); - continue; - } - - /* We're looking at channels *backwards*, so peer == me - * is the right test here for whether we don't charge fees. */ - if (!can_reach(&chan->half[idx], &chan->scid, peer == me, - cur->dijkstra.total, cur->dijkstra.risk, - riskfactor, riskbias, fuzz, base_seed, - &total, &risk)) { - SUPERVERBOSE("... can't reach"); - continue; - } - - /* This effectively adds it to the map if it was infinite */ - if (costs_less(total, risk, &cost_after, - peer->dijkstra.total, peer->dijkstra.risk, - &cost_before, - costfn)) { - SUPERVERBOSE("...%s can reach %s" - " total %s risk %s", - type_to_string(tmpctx, struct node_id, - &cur->id), - type_to_string(tmpctx, struct node_id, - &peer->id), - type_to_string(tmpctx, struct amount_msat, - &total), - type_to_string(tmpctx, struct amount_msat, - &risk)); - adjust_unvisited(peer, unvisited, - cost_before, total, risk, cost_after); - } - } -} - -static struct node *first_unvisited(struct unvisited *unvisited) -{ - struct node **arr; - - while ((arr = uintmap_after(&unvisited->map, &unvisited->min_index))) { - for (size_t i = 0; i < tal_count(arr); i++) { - if (arr[i]) { - unvisited->min_index--; - return arr[i]; - } - } - } - - return NULL; -} - -static void dijkstra(struct routing_state *rstate, - const struct node *dst, - const struct node *me, - double riskfactor, - u64 riskbias, - double fuzz, const struct siphash_seed *base_seed, - struct unvisited *unvisited, - costfn_t *costfn) -{ - struct node *cur; - - while ((cur = first_unvisited(unvisited)) != NULL) { - update_unvisited_neighbors(rstate, cur, me, - riskfactor, riskbias, - fuzz, base_seed, unvisited, costfn); - remove_unvisited(cur, unvisited, costfn); - if (cur == dst) - return; - } -} - -/* Note that we calculated route *backwards*, for fees. So "from" - * here has a high cost, "to" has a cost of exact amount sent. */ -static struct chan **build_route(const tal_t *ctx, - struct routing_state *rstate, - const struct node *from, - const struct node *to, - const struct node *me, - double riskfactor, - u64 riskbias, - double fuzz, - const struct siphash_seed *base_seed, - struct amount_msat *fee) -{ - const struct node *i; - struct chan **route, *chan; - - SUPERVERBOSE("Building route from %s (%s) -> %s (%s)", - type_to_string(tmpctx, struct node_id, &from->id), - type_to_string(tmpctx, struct amount_msat, - &from->dijkstra.total), - type_to_string(tmpctx, struct node_id, &to->id), - type_to_string(tmpctx, struct amount_msat, - &to->dijkstra.total)); - /* Never reached? */ - if (amount_msat_eq(from->dijkstra.total, INFINITE)) - return NULL; - - /* Walk to find which neighbors we used */ - route = tal_arr(ctx, struct chan *, 0); - for (i = from; i != to; i = other_node(i, chan)) { - struct chan_map_iter it; - - /* Consider all neighbors */ - for (chan = first_chan(i, &it); chan; chan = next_chan(i, &it)) { - struct node *peer = other_node(i, chan); - struct half_chan *hc = half_chan_from(i, chan); - struct amount_msat total, risk; - - SUPERVERBOSE("CONSIDER: %s -> %s (%s/%s)", - type_to_string(tmpctx, struct node_id, - &i->id), - type_to_string(tmpctx, struct node_id, - &peer->id), - type_to_string(tmpctx, struct amount_msat, - &peer->dijkstra.total), - type_to_string(tmpctx, struct amount_msat, - &peer->dijkstra.risk)); - - /* If traversing this wasn't possible, ignore */ - if (!hc_is_routable(rstate, chan, !half_chan_to(i, chan))) { - continue; - } - - if (!can_reach(hc, &chan->scid, i == me, - peer->dijkstra.total, peer->dijkstra.risk, - riskfactor, - riskbias, - fuzz, base_seed, - &total, &risk)) - continue; - - /* If this was the path we took, we're done (if there are - * two identical ones, it doesn't matter which) */ - if (amount_msat_eq(total, i->dijkstra.total) - && amount_msat_eq(risk, i->dijkstra.risk)) - break; - } - - if (!chan) { - status_broken("Could not find hop to %s", - type_to_string(tmpctx, struct node_id, - &i->id)); - return tal_free(route); - } - tal_arr_expand(&route, chan); - } - - /* We don't charge ourselves fees, so skip first hop */ - if (!amount_msat_sub(fee, - other_node(from, route[0])->dijkstra.total, - to->dijkstra.total)) { - status_broken("Could not subtract %s - %s for fee", - type_to_string(tmpctx, struct amount_msat, - &other_node(from, route[0]) - ->dijkstra.total), - type_to_string(tmpctx, struct amount_msat, - &to->dijkstra.total)); - return tal_free(route); - } - - return route; -} - -static struct unvisited *dijkstra_prepare(const tal_t *ctx, - struct routing_state *rstate, - struct node *src, - struct amount_msat msat, - costfn_t *costfn) -{ - struct node_map_iter it; - struct unvisited *unvisited; - struct node *n; - struct node **arr; - struct amount_msat cost; - - unvisited = tal(tmpctx, struct unvisited); - uintmap_init(&unvisited->map); - unvisited->min_index = UINT64_MAX; - - /* Reset all the information. */ - for (n = node_map_first(rstate->nodes, &it); - n; - n = node_map_next(rstate->nodes, &it)) { - if (n == src) - continue; - n->dijkstra.total = INFINITE; - n->dijkstra.risk = INFINITE; - } - - /* Mark start cost: place in unvisited map. */ - src->dijkstra.total = msat; - src->dijkstra.risk = AMOUNT_MSAT(0); - arr = tal_arr(unvisited, struct node *, 1); - arr[0] = src; - /* Adding 0 can never fail */ - if (!costfn(&cost, src->dijkstra.total, src->dijkstra.risk)) - abort(); - unvisited_add(unvisited, cost, arr); - - return unvisited; -} - -static void dijkstra_cleanup(struct unvisited *unvisited) -{ - struct node **arr; - u64 idx; - - /* uintmap uses malloc, so manual cleaning needed */ - while ((arr = uintmap_first(&unvisited->map, &idx)) != NULL) { - tal_free(arr); - uintmap_del(&unvisited->map, idx); - } - tal_free(unvisited); -} - -/* We need to start biassing against long routes. */ -static struct chan ** -find_shorter_route(const tal_t *ctx, struct routing_state *rstate, - struct node *src, struct node *dst, - const struct node *me, - struct amount_msat msat, - u32 max_hops, - double fuzz, const struct siphash_seed *base_seed, - struct chan **long_route, - struct amount_msat *fee) -{ - struct unvisited *unvisited; - struct chan **short_route = NULL; - struct amount_msat long_cost, short_cost, cost_diff; - u64 min_bias, max_bias; - double riskfactor; - - /* We traverse backwards, so dst has largest total */ - if (!amount_msat_sub(&long_cost, - dst->dijkstra.total, src->dijkstra.total)) - goto bad_total; - tal_free(long_route); - - /* FIXME: It's hard to juggle both the riskfactor and riskbias here, - * so we set our riskfactor to rougly equate to 1 millisatoshi - * per block delay, which is close enough to zero to not break - * this algorithm, but still provide some bias towards - * low-delay routes. */ - riskfactor = amount_msat_ratio(AMOUNT_MSAT(1), msat); - - /* First, figure out if a short route is even possible. - * We set the cost function to ignore total, riskbias 1 and riskfactor - * ~0 so risk simply operates as a simple hop counter. */ - unvisited = dijkstra_prepare(tmpctx, rstate, src, msat, - shortest_cost_function); - SUPERVERBOSE("Running shortest path from %s -> %s", - type_to_string(tmpctx, struct node_id, &dst->id), - type_to_string(tmpctx, struct node_id, &src->id)); - dijkstra(rstate, dst, NULL, riskfactor, 1, fuzz, base_seed, - unvisited, shortest_cost_function); - dijkstra_cleanup(unvisited); - - /* This will usually succeed, since we found a route before; however - * it's possible that it fails in corner cases. Consider that the reduced - * riskfactor may make us select a more fee-expensive route, which then - * makes us unable to complete the route due to htlc_max restrictions. */ - short_route = build_route(ctx, rstate, dst, src, me, riskfactor, 1, - fuzz, base_seed, fee); - if (!short_route) { - status_info("Could't find short enough route %s->%s", - type_to_string(tmpctx, struct node_id, &dst->id), - type_to_string(tmpctx, struct node_id, &src->id)); - goto out; - } - - if (!amount_msat_sub(&short_cost, - dst->dijkstra.total, src->dijkstra.total)) - goto bad_total; - - /* Still too long? Oh well. */ - if (tal_count(short_route) > max_hops) { - status_info("Minimal possible route %s->%s is %zu", - type_to_string(tmpctx, struct node_id, &dst->id), - type_to_string(tmpctx, struct node_id, &src->id), - tal_count(short_route)); - goto out; - } - - /* OK, so it's possible, just more expensive. */ - min_bias = 0; - - if (!amount_msat_sub(&cost_diff, short_cost, long_cost)) { - status_broken("Short cost %s < long cost %s?", - type_to_string(tmpctx, struct amount_msat, - &short_cost), - type_to_string(tmpctx, struct amount_msat, - &long_cost)); - goto out; - } - - /* This is a gross overestimate, but it works. */ - max_bias = cost_diff.millisatoshis; /* Raw: bias calc */ - - SUPERVERBOSE("maxbias %"PRIu64" gave rlen %zu", - max_bias, tal_count(short_route)); - - /* Now, binary search */ - while (min_bias < max_bias) { - struct chan **route; - struct amount_msat this_fee; - u64 riskbias = (min_bias + max_bias) / 2; - - unvisited = dijkstra_prepare(tmpctx, rstate, src, msat, - normal_cost_function); - dijkstra(rstate, dst, me, riskfactor, riskbias, fuzz, base_seed, - unvisited, normal_cost_function); - dijkstra_cleanup(unvisited); - - route = build_route(ctx, rstate, dst, src, me, - riskfactor, riskbias, - fuzz, base_seed, &this_fee); - - SUPERVERBOSE("riskbias %"PRIu64" rlen %zu", - riskbias, tal_count(route)); - /* Too long still? This is our new min_bias */ - if (tal_count(route) > max_hops) { - tal_free(route); - min_bias = riskbias + 1; - } else { - /* This route is acceptable. */ - tal_free(short_route); - short_route = route; - /* Save this fee in case we exit loop */ - *fee = this_fee; - max_bias = riskbias; - } - } - - return short_route; - -bad_total: - status_broken("dst total %s < src total %s?", - type_to_string(tmpctx, struct amount_msat, - &dst->dijkstra.total), - type_to_string(tmpctx, struct amount_msat, - &src->dijkstra.total)); -out: - tal_free(short_route); - return NULL; -} - -/* riskfactor is already scaled to per-block amount */ -static struct chan ** -find_route(const tal_t *ctx, struct routing_state *rstate, - const struct node_id *from, const struct node_id *to, - struct amount_msat msat, - double riskfactor, - double fuzz, const struct siphash_seed *base_seed, - u32 max_hops, - struct amount_msat *fee) -{ - struct node *src, *dst; - const struct node *me; - struct unvisited *unvisited; - struct chan **route; - - /* Note: we map backwards, since we know the amount of satoshi we want - * at the end, and need to derive how much we need to send. */ - src = get_node(rstate, to); - - /* If from is NULL, that's means it's us. */ - if (!from) - me = dst = get_node(rstate, &rstate->local_id); - else { - dst = get_node(rstate, from); - me = NULL; - } - - if (!src) { - status_info("find_route: cannot find %s", - type_to_string(tmpctx, struct node_id, to)); - return NULL; - } else if (!dst) { - status_info("find_route: cannot find source (%s)", - type_to_string(tmpctx, struct node_id, to)); - return NULL; - } else if (dst == src) { - status_info("find_route: this is %s, refusing to create empty route", - type_to_string(tmpctx, struct node_id, to)); - return NULL; - } - - unvisited = dijkstra_prepare(tmpctx, rstate, src, msat, - normal_cost_function); - dijkstra(rstate, dst, me, riskfactor, 1, fuzz, base_seed, - unvisited, normal_cost_function); - dijkstra_cleanup(unvisited); - - route = build_route(ctx, rstate, dst, src, me, riskfactor, 1, - fuzz, base_seed, fee); - if (tal_count(route) <= max_hops) - return route; - - /* This is the far more unlikely case */ - return find_shorter_route(ctx, rstate, src, dst, me, msat, - max_hops, fuzz, base_seed, route, fee); -} - /* Checks that key is valid, and signed this hash */ static bool check_signed_hash_nodeid(const struct sha256_double *hash, const secp256k1_ecdsa_signature *signature, @@ -1656,7 +896,6 @@ bool routing_add_channel_announcement(struct routing_state *rstate, uc = tal(rstate, struct unupdated_channel); uc->channel_announce = tal_dup_talarr(uc, u8, msg); - uc->features = tal_steal(uc, features); uc->added = gossip_time_now(rstate); uc->index = index; uc->sat = sat; @@ -1990,34 +1229,6 @@ static void update_pending(struct pending_cannouncement *pending, } } -static void set_connection_values(struct chan *chan, - int idx, - u32 base_fee, - u32 proportional_fee, - u32 delay, - u8 message_flags, - u8 channel_flags, - u32 timestamp, - struct amount_msat htlc_minimum, - struct amount_msat htlc_maximum) -{ - struct half_chan *c = &chan->half[idx]; - - c->delay = delay; - c->htlc_minimum = htlc_minimum; - c->htlc_maximum = htlc_maximum; - c->base_fee = base_fee; - c->proportional_fee = proportional_fee; - c->message_flags = message_flags; - c->channel_flags = channel_flags; - c->bcast.timestamp = timestamp; - assert((c->channel_flags & ROUTING_FLAGS_DIRECTION) == idx); - - SUPERVERBOSE("Channel %s/%d was updated.", - type_to_string(tmpctx, struct short_channel_id, &chan->scid), - idx); -} - bool routing_add_channel_update(struct routing_state *rstate, const u8 *update TAKES, u32 index, @@ -2106,7 +1317,7 @@ bool routing_add_channel_update(struct routing_state *rstate, if (uc) { assert(!chan); chan = new_chan(rstate, &short_channel_id, - &uc->id[0], &uc->id[1], sat, uc->features); + &uc->id[0], &uc->id[1], sat); } /* Discard older updates */ @@ -2155,16 +1366,7 @@ bool routing_add_channel_update(struct routing_state *rstate, } } - /* FIXME: https://github.com/lightningnetwork/lightning-rfc/pull/512 - * says we MUST NOT exceed 2^32-1, but c-lightning did, so just trim - * rather than rejecting. */ - if (amount_msat_greater(htlc_maximum, chainparams->max_payment)) - htlc_maximum = chainparams->max_payment; - - set_connection_values(chan, direction, fee_base_msat, - fee_proportional_millionths, expiry, - message_flags, channel_flags, - timestamp, htlc_minimum, htlc_maximum); + chan->half[direction].bcast.timestamp = timestamp; /* Safe even if was never added, but if it's a private channel it * would be a WIRE_GOSSIP_STORE_PRIVATE_UPDATE. */ @@ -2500,12 +1702,6 @@ bool routing_add_node_announcement(struct routing_state *rstate, && node->bcast.timestamp < time_now().ts.tv_sec) rstate->last_timestamp = node->bcast.timestamp; - if (feature_offered(features, OPT_VAR_ONION)) - node->hop_style = ROUTE_HOP_TLV; - else - /* Reset it in case they no longer offer the feature */ - node->hop_style = ROUTE_HOP_LEGACY; - if (index) node->bcast.index = index; else { @@ -2608,131 +1804,6 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann, return NULL; } -struct route_hop **get_route(const tal_t *ctx, struct routing_state *rstate, - const struct node_id *source, - const struct node_id *destination, - struct amount_msat msat, double riskfactor, - u32 final_cltv, - double fuzz, u64 seed, - struct exclude_entry **excluded, - u32 max_hops) -{ - struct chan **route; - struct amount_msat total_amount; - unsigned int total_delay; - struct amount_msat fee; - struct route_hop **hops; - struct node *n; - struct amount_msat *saved_capacity; - struct short_channel_id_dir *excluded_chan; - struct siphash_seed base_seed; - - saved_capacity = tal_arr(tmpctx, struct amount_msat, 0); - excluded_chan = tal_arr(tmpctx, struct short_channel_id_dir, 0); - - base_seed.u.u64[0] = base_seed.u.u64[1] = seed; - - if (amount_msat_eq(msat, AMOUNT_MSAT(0))) - return NULL; - - /* Temporarily set the capacity of the excluded channels and the incoming channels - * of excluded nodes to zero. */ - for (size_t i = 0; i < tal_count(excluded); i++) { - if (excluded[i]->type == EXCLUDE_CHANNEL) { - struct short_channel_id_dir *chan_id = &excluded[i]->u.chan_id; - struct chan *chan = get_channel(rstate, &chan_id->scid); - if (!chan) - continue; - tal_arr_expand(&saved_capacity, chan->half[chan_id->dir].htlc_maximum); - tal_arr_expand(&excluded_chan, *chan_id); - chan->half[chan_id->dir].htlc_maximum = AMOUNT_MSAT(0); - } else { - assert(excluded[i]->type == EXCLUDE_NODE); - - struct node *node = get_node(rstate, &excluded[i]->u.node_id); - if (!node) - continue; - - struct chan_map_iter i; - struct chan *chan; - for (chan = first_chan(node, &i); chan; chan = next_chan(node, &i)) { - int dir = half_chan_to(node, chan); - tal_arr_expand(&saved_capacity, chan->half[dir].htlc_maximum); - - struct short_channel_id_dir id; - id.scid = chan->scid; - id.dir = dir; - tal_arr_expand(&excluded_chan, id); - - chan->half[dir].htlc_maximum = AMOUNT_MSAT(0); - } - } - } - - route = find_route(ctx, rstate, source, destination, msat, - riskfactor / BLOCKS_PER_YEAR / 100, - fuzz, &base_seed, max_hops, &fee); - - /* Now restore the capacity. */ - /* Restoring is done in reverse order, in order to properly - * handle the case where a channel is indicated twice in - * our input. - * Entries in `saved_capacity` of that channel beyond the - * first entry will be 0, only the first entry of that - * channel will be the correct capacity. - * By restoring in reverse order we ensure we can restore - * the correct capacity. - */ - for (ssize_t i = tal_count(excluded_chan) - 1; i >= 0; i--) { - struct chan *chan = get_channel(rstate, &excluded_chan[i].scid); - if (!chan) - continue; - chan->half[excluded_chan[i].dir].htlc_maximum = saved_capacity[i]; - } - - if (!route) { - return NULL; - } - - /* Fees, delays need to be calculated backwards along route. */ - hops = tal_arr(ctx, struct route_hop *, tal_count(route)); - total_amount = msat; - total_delay = final_cltv; - - /* Start at destination node. */ - n = get_node(rstate, destination); - for (int i = tal_count(route) - 1; i >= 0; i--) { - const struct half_chan *c; - - int idx = half_chan_to(n, route[i]); - c = &route[i]->half[idx]; - hops[i] = tal(hops, struct route_hop); - hops[i]->scid = route[i]->scid; - hops[i]->node_id = n->id; - hops[i]->amount = total_amount; - hops[i]->delay = total_delay; - hops[i]->direction = idx; - hops[i]->style = n->hop_style; - hops[i]->blinding = NULL; - hops[i]->enctlv = NULL; - - /* Since we calculated this route, it should not overflow! */ - if (!amount_msat_add_fee(&total_amount, - c->base_fee, c->proportional_fee)) { - status_broken("Route overflow step %i: %s + %u/%u!?", - i, type_to_string(tmpctx, struct amount_msat, - &total_amount), - c->base_fee, c->proportional_fee); - return tal_free(hops); - } - total_delay += c->delay; - n = other_node(n, route[i]); - } - assert(node_id_eq(&n->id, source ? source : &rstate->local_id)); - - return hops; -} - void route_prune(struct routing_state *rstate) { u64 now = gossip_time_now(rstate).ts.tv_sec; @@ -2834,8 +1905,7 @@ bool routing_add_private_channel(struct routing_state *rstate, type_to_string(tmpctx, struct short_channel_id, &scid)); /* Create new (unannounced) channel */ - chan = new_chan(rstate, &scid, &node_id[0], &node_id[1], sat, - features); + chan = new_chan(rstate, &scid, &node_id[0], &node_id[1], sat); if (!index) index = gossip_store_add(rstate->gs, msg, 0, false, NULL); chan->bcast.index = index; diff --git a/gossipd/routing.h b/gossipd/routing.h index 5cc4d5e96f88..a0ec756f09fe 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -20,34 +20,11 @@ struct peer; struct routing_state; struct half_chan { - /* millisatoshi. */ - u32 base_fee; - /* millionths */ - u32 proportional_fee; - - /* Delay for HTLC in blocks.*/ - u32 delay; - /* Timestamp and index into store file */ struct broadcastable bcast; - /* Flags as specified by the `channel_update`s, among other - * things indicated direction wrt the `channel_id` */ - u8 channel_flags; - - /* Flags as specified by the `channel_update`s, indicates - * optional fields. */ - u8 message_flags; - /* Token bucket */ u8 tokens; - - /* Feature cache for parent chan: squeezed in here where it would - * otherwise simply be padding. */ - u8 any_features; - - /* Minimum and maximum number of msatoshi in an HTLC */ - struct amount_msat htlc_minimum, htlc_maximum; }; struct chan { @@ -96,11 +73,6 @@ static inline bool is_halfchan_defined(const struct half_chan *hc) return hc->bcast.index != 0; } -static inline bool is_halfchan_enabled(const struct half_chan *hc) -{ - return is_halfchan_defined(hc) && !(hc->channel_flags & ROUTING_FLAGS_DISABLED); -} - /* Container for per-node channel pointers. Better cache performance * than uintmap, and we don't need ordering. */ static inline const struct short_channel_id *chan_map_scid(const struct chan *c) @@ -152,22 +124,11 @@ struct node { /* Token bucket */ u8 tokens; - /* route_hop_style */ - enum route_hop_style hop_style; - /* Channels connecting us to other nodes */ union { struct chan_map map; struct chan *arr[NUM_IMMEDIATE_CHANS+1]; } chans; - - /* Temporary data for routefinding. */ - struct { - /* Total to get to here from target. */ - struct amount_msat total; - /* Total risk premium of this route. */ - struct amount_msat risk; - } dijkstra; }; const struct node_id *node_map_keyof_node(const struct node *n); @@ -319,19 +280,6 @@ get_channel(const struct routing_state *rstate, return uintmap_get(&rstate->chanmap, scid->u64); } -enum exclude_entry_type { - EXCLUDE_CHANNEL = 1, - EXCLUDE_NODE = 2 -}; - -struct exclude_entry { - enum exclude_entry_type type; - union { - struct short_channel_id_dir chan_id; - struct node_id node_id; - } u; -}; - struct routing_state *new_routing_state(const tal_t *ctx, const struct node_id *local_id, struct list_head *peers, @@ -350,8 +298,7 @@ struct chan *new_chan(struct routing_state *rstate, const struct short_channel_id *scid, const struct node_id *id1, const struct node_id *id2, - struct amount_sat sat, - const u8 *features); + struct amount_sat sat); /* Handlers for incoming messages */ @@ -400,17 +347,6 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node, struct node *get_node(struct routing_state *rstate, const struct node_id *id); -/* Compute a route to a destination, for a given amount and riskfactor. */ -struct route_hop **get_route(const tal_t *ctx, struct routing_state *rstate, - const struct node_id *source, - const struct node_id *destination, - const struct amount_msat msat, double riskfactor, - u32 final_cltv, - double fuzz, - u64 seed, - struct exclude_entry **excluded, - u32 max_hops); - void route_prune(struct routing_state *rstate); /** diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 6d1fb71d69b7..4063679e8a2e 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -134,14 +134,10 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) switch (t) { /* These are messages we send, not them. */ case WIRE_GOSSIPD_INIT: - case WIRE_GOSSIPD_GETNODES_REQUEST: - case WIRE_GOSSIPD_GETROUTE_REQUEST: - case WIRE_GOSSIPD_GETCHANNELS_REQUEST: case WIRE_GOSSIPD_PING: case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE: case WIRE_GOSSIPD_GET_TXOUT_REPLY: case WIRE_GOSSIPD_OUTPOINT_SPENT: - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS: case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: case WIRE_GOSSIPD_DEV_SUPPRESS: case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE: @@ -152,10 +148,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPD_SEND_ONIONMSG: case WIRE_GOSSIPD_ADDGOSSIP: /* This is a reply, so never gets through to here. */ - case WIRE_GOSSIPD_GETNODES_REPLY: - case WIRE_GOSSIPD_GETROUTE_REPLY: - case WIRE_GOSSIPD_GETCHANNELS_REPLY: - case WIRE_GOSSIPD_GET_INCOMING_CHANNELS_REPLY: case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY: case WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY: case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE_REPLY: @@ -235,347 +227,6 @@ void gossipd_notify_spend(struct lightningd *ld, subd_send_msg(ld->gossip, msg); } -static void json_getnodes_reply(struct subd *gossip UNUSED, const u8 *reply, - const int *fds UNUSED, - struct command *cmd) -{ - struct gossip_getnodes_entry **nodes; - struct json_stream *response; - size_t i, j; - - if (!fromwire_gossipd_getnodes_reply(reply, reply, &nodes)) { - was_pending(command_fail(cmd, LIGHTNINGD, - "Malformed gossip_getnodes response")); - return; - } - - response = json_stream_success(cmd); - json_array_start(response, "nodes"); - - for (i = 0; i < tal_count(nodes); i++) { - struct json_escape *esc; - - json_object_start(response, NULL); - json_add_node_id(response, "nodeid", &nodes[i]->nodeid); - if (nodes[i]->last_timestamp < 0) { - json_object_end(response); - continue; - } - esc = json_escape(NULL, - take(tal_strndup(NULL, - (const char *)nodes[i]->alias, - ARRAY_SIZE(nodes[i]->alias)))); - json_add_escaped_string(response, "alias", take(esc)); - json_add_hex(response, "color", - nodes[i]->color, ARRAY_SIZE(nodes[i]->color)); - json_add_u64(response, "last_timestamp", - nodes[i]->last_timestamp); - json_add_hex_talarr(response, "features", nodes[i]->features); - json_array_start(response, "addresses"); - for (j=0; jaddresses); j++) { - json_add_address(response, NULL, &nodes[i]->addresses[j]); - } - json_array_end(response); - json_object_end(response); - } - json_array_end(response); - was_pending(command_success(cmd, response)); -} - -static struct command_result *json_listnodes(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) -{ - u8 *req; - struct node_id *id; - - if (!param(cmd, buffer, params, - p_opt("id", param_node_id, &id), - NULL)) - return command_param_failed(); - - req = towire_gossipd_getnodes_request(cmd, id); - subd_req(cmd, cmd->ld->gossip, req, -1, 0, json_getnodes_reply, cmd); - return command_still_pending(cmd); -} - -static const struct json_command listnodes_command = { - "listnodesold", - "network", - json_listnodes, - "Show node {id} (or all, if no {id}), in our local network view" -}; -AUTODATA(json_command, &listnodes_command); - -static void json_add_route_hop_style(struct json_stream *response, - const char *fieldname, - enum route_hop_style style) -{ - switch (style) { - case ROUTE_HOP_LEGACY: - json_add_string(response, fieldname, "legacy"); - return; - case ROUTE_HOP_TLV: - json_add_string(response, fieldname, "tlv"); - return; - } - fatal("Unknown route_hop_style %u", style); -} - -/* Output a route hop */ -static void json_add_route_hop(struct json_stream *r, char const *n, - const struct route_hop *h) -{ - /* Imitate what getroute/sendpay use */ - json_object_start(r, n); - json_add_node_id(r, "id", &h->node_id); - json_add_short_channel_id(r, "channel", &h->scid); - json_add_num(r, "direction", h->direction); - json_add_amount_msat_compat(r, h->amount, "msatoshi", "amount_msat"); - json_add_num(r, "delay", h->delay); - json_add_route_hop_style(r, "style", h->style); - json_object_end(r); -} - -/* Output a route */ -static void json_add_route(struct json_stream *r, char const *n, - struct route_hop **hops, size_t hops_len) -{ - size_t i; - json_array_start(r, n); - for (i = 0; i < hops_len; ++i) { - json_add_route_hop(r, NULL, hops[i]); - } - json_array_end(r); -} - -static void json_getroute_reply(struct subd *gossip UNUSED, const u8 *reply, const int *fds UNUSED, - struct command *cmd) -{ - struct json_stream *response; - struct route_hop **hops; - - fromwire_gossipd_getroute_reply(reply, reply, &hops); - - if (tal_count(hops) == 0) { - was_pending(command_fail(cmd, PAY_ROUTE_NOT_FOUND, - "Could not find a route")); - return; - } - - response = json_stream_success(cmd); - json_add_route(response, "route", hops, tal_count(hops)); - was_pending(command_success(cmd, response)); -} - -static struct command_result *json_getroute(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) -{ - struct lightningd *ld = cmd->ld; - struct node_id *destination; - struct node_id *source; - const jsmntok_t *excludetok; - struct amount_msat *msat; - u32 *cltv; - /* risk factor 12.345% -> riskfactor_millionths = 12345000 */ - u64 *riskfactor_millionths; - const struct exclude_entry **excluded; - u32 *max_hops; - - /* Higher fuzz means that some high-fee paths can be discounted - * for an even larger value, increasing the scope for route - * randomization (the higher-fee paths become more likely to - * be selected) at the cost of increasing the probability of - * selecting the higher-fee paths. */ - u64 *fuzz_millionths; /* fuzz 12.345% -> fuzz_millionths = 12345000 */ - - if (!param( - cmd, buffer, params, p_req("id", param_node_id, &destination), - p_req("msatoshi", param_msat, &msat), - p_req("riskfactor", param_millionths, &riskfactor_millionths), - p_opt_def("cltv", param_number, &cltv, 9), - p_opt("fromid", param_node_id, &source), - p_opt_def("fuzzpercent", param_millionths, &fuzz_millionths, - 5000000), - p_opt("exclude", param_array, &excludetok), - p_opt_def("maxhops", param_number, &max_hops, ROUTING_MAX_HOPS), - NULL)) - return command_param_failed(); - - /* Convert from percentage */ - *fuzz_millionths /= 100; - - if (excludetok) { - const jsmntok_t *t; - size_t i; - - excluded = tal_arr(cmd, const struct exclude_entry *, 0); - - json_for_each_arr(i, t, excludetok) { - struct exclude_entry *entry = tal(excluded, struct exclude_entry); - struct short_channel_id_dir *chan_id = tal(tmpctx, struct short_channel_id_dir); - if (!short_channel_id_dir_from_str(buffer + t->start, - t->end - t->start, - chan_id)) { - struct node_id *node_id = tal(tmpctx, struct node_id); - - if (!json_to_node_id(buffer, t, node_id)) - return command_fail_badparam(cmd, "exclude", - buffer, t, - "should be short_channel_id or node_id"); - - entry->type = EXCLUDE_NODE; - entry->u.node_id = *node_id; - } else { - entry->type = EXCLUDE_CHANNEL; - entry->u.chan_id = *chan_id; - } - - tal_arr_expand(&excluded, entry); - } - } else { - excluded = NULL; - } - - u8 *req = towire_gossipd_getroute_request( - cmd, source, destination, *msat, *riskfactor_millionths, *cltv, - *fuzz_millionths, excluded, *max_hops); - subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd); - return command_still_pending(cmd); -} - -static const struct json_command getroute_command = { - "getrouteold", - "channels", - json_getroute, - "Show route to {id} for {msatoshi}, using {riskfactor} and optional {cltv} (default 9). " - "If specified search from {fromid} otherwise use this node as source. " - "Randomize the route with up to {fuzzpercent} (default 5.0). " - "{exclude} an array of short-channel-id/direction (e.g. [ '564334x877x1/0', '564195x1292x0/1' ]) " - "or node-id from consideration. " - "Set the {maxhops} the route can take (default 20)." -}; -AUTODATA(json_command, &getroute_command); - -static void json_add_halfchan(struct json_stream *response, - const struct gossip_getchannels_entry *e, - int idx) -{ - const struct gossip_halfchannel_entry *he = e->e[idx]; - if (!he) - return; - - json_object_start(response, NULL); - json_add_node_id(response, "source", &e->node[idx]); - json_add_node_id(response, "destination", &e->node[!idx]); - json_add_short_channel_id(response, "short_channel_id", - &e->short_channel_id); - json_add_bool(response, "public", e->public); - json_add_amount_sat_compat(response, e->sat, - "satoshis", "amount_msat"); - json_add_num(response, "message_flags", he->message_flags); - json_add_num(response, "channel_flags", he->channel_flags); - json_add_bool(response, "active", - !(he->channel_flags & ROUTING_FLAGS_DISABLED) - && !e->local_disabled); - json_add_num(response, "last_update", he->last_update_timestamp); - json_add_num(response, "base_fee_millisatoshi", he->base_fee_msat); - json_add_num(response, "fee_per_millionth", he->fee_per_millionth); - json_add_num(response, "delay", he->delay); - json_add_amount_msat_only(response, "htlc_minimum_msat", he->min); - json_add_amount_msat_only(response, "htlc_maximum_msat", he->max); - json_add_hex_talarr(response, "features", e->features); - json_object_end(response); -} - -struct listchannels_info { - struct command *cmd; - struct json_stream *response; - struct short_channel_id *id; - struct node_id *source; -}; - -/* Called upon receiving a getchannels_reply from `gossipd` */ -static void json_listchannels_reply(struct subd *gossip UNUSED, const u8 *reply, - const int *fds UNUSED, - struct listchannels_info *linfo) -{ - size_t i; - struct gossip_getchannels_entry **entries; - bool complete; - - if (!fromwire_gossipd_getchannels_reply(reply, reply, - &complete, &entries)) { - /* Shouldn't happen: just end json stream. */ - log_broken(linfo->cmd->ld->log, "Invalid reply from gossipd"); - was_pending(command_raw_complete(linfo->cmd, linfo->response)); - return; - } - - for (i = 0; i < tal_count(entries); i++) { - json_add_halfchan(linfo->response, entries[i], 0); - json_add_halfchan(linfo->response, entries[i], 1); - } - - /* More coming? Ask from this point on.. */ - if (!complete) { - u8 *req; - assert(tal_count(entries) != 0); - req = towire_gossipd_getchannels_request(linfo->cmd, - linfo->id, - linfo->source, - &entries[i-1] - ->short_channel_id); - subd_req(linfo->cmd->ld->gossip, linfo->cmd->ld->gossip, - req, -1, 0, json_listchannels_reply, linfo); - } else { - json_array_end(linfo->response); - was_pending(command_success(linfo->cmd, linfo->response)); - } -} - -static struct command_result *json_listchannels(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) -{ - u8 *req; - struct listchannels_info *linfo = tal(cmd, struct listchannels_info); - - linfo->cmd = cmd; - if (!param(cmd, buffer, params, - p_opt("short_channel_id", param_short_channel_id, &linfo->id), - p_opt("source", param_node_id, &linfo->source), - NULL)) - return command_param_failed(); - - if (linfo->id && linfo->source) - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Cannot specify both source and short_channel_id"); - - /* Start JSON response, then we stream. */ - linfo->response = json_stream_success(cmd); - json_array_start(linfo->response, "channels"); - - req = towire_gossipd_getchannels_request(cmd, linfo->id, linfo->source, - NULL); - subd_req(cmd->ld->gossip, cmd->ld->gossip, - req, -1, 0, json_listchannels_reply, linfo); - - return command_still_pending(cmd); -} - -static const struct json_command listchannels_command = { - "listchannelsold", - "channels", - json_listchannels, - "Show channel {short_channel_id} or {source} (or all known channels, if not specified)" -}; -AUTODATA(json_command, &listchannels_command); - /* Called upon receiving a addgossip_reply from `gossipd` */ static void json_addgossip_reply(struct subd *gossip UNUSED, const u8 *reply, const int *fds UNUSED, diff --git a/lightningd/gossip_msg.c b/lightningd/gossip_msg.c index bc827c938b91..47eb5bb93e2b 100644 --- a/lightningd/gossip_msg.c +++ b/lightningd/gossip_msg.c @@ -194,32 +194,3 @@ void towire_gossip_getchannels_entry(u8 **pptr, } else towire_bool(pptr, false); } - -struct exclude_entry *fromwire_exclude_entry(const tal_t *ctx, - const u8 **pptr, size_t *max) -{ - struct exclude_entry *entry = tal(ctx, struct exclude_entry); - entry->type = fromwire_u8(pptr, max); - switch (entry->type) { - case EXCLUDE_CHANNEL: - fromwire_short_channel_id_dir(pptr, max, &entry->u.chan_id); - return entry; - case EXCLUDE_NODE: - fromwire_node_id(pptr, max, &entry->u.node_id); - return entry; - default: - return fromwire_fail(pptr, max); - } -} - -void towire_exclude_entry(u8 **pptr, const struct exclude_entry *entry) -{ - assert(entry->type == EXCLUDE_CHANNEL || - entry->type == EXCLUDE_NODE); - - towire_u8(pptr, entry->type); - if (entry->type == EXCLUDE_CHANNEL) - towire_short_channel_id_dir(pptr, &entry->u.chan_id); - else - towire_node_id(pptr, &entry->u.node_id); -} diff --git a/lightningd/gossip_msg.h b/lightningd/gossip_msg.h index 5f405619212a..fe1f48eca82d 100644 --- a/lightningd/gossip_msg.h +++ b/lightningd/gossip_msg.h @@ -54,9 +54,4 @@ fromwire_gossip_getchannels_entry(const tal_t *ctx, void towire_gossip_getchannels_entry( u8 **pptr, const struct gossip_getchannels_entry *entry); -struct exclude_entry * -fromwire_exclude_entry(const tal_t *ctx, - const u8 **pptr, size_t *max); -void towire_exclude_entry(u8 **pptr, const struct exclude_entry *entry); - #endif /* LIGHTNING_LIGHTNINGD_GOSSIP_MSG_H */ diff --git a/lightningd/pay.c b/lightningd/pay.c index 62910de22770..7ce681c1f35b 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include