mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-15 11:04:20 +01:00
gossipd: move gossip message generation into its own file.
gossipd.c is doing too many things: this is a start. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -15,10 +15,12 @@ LIGHTNINGD_GOSSIP_CONTROL_OBJS := $(LIGHTNINGD_GOSSIP_CONTROL_SRC:.c=.o)
|
||||
LIGHTNINGD_GOSSIP_HEADERS_WSRC := gossipd/gen_gossip_wire.h \
|
||||
gossipd/gen_gossip_peerd_wire.h \
|
||||
gossipd/gen_gossip_store.h \
|
||||
gossipd/gossipd.h \
|
||||
gossipd/gossip_store.h \
|
||||
gossipd/make_gossip.h \
|
||||
gossipd/routing.h
|
||||
LIGHTNINGD_GOSSIP_HEADERS := $(LIGHTNINGD_GOSSIP_HEADERS_WSRC) gossipd/broadcast.h
|
||||
LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS_WSRC:.h=.c) gossipd/gossipd.c
|
||||
LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS_WSRC:.h=.c)
|
||||
LIGHTNINGD_GOSSIP_OBJS := $(LIGHTNINGD_GOSSIP_SRC:.c=.o)
|
||||
|
||||
# Make sure these depend on everything.
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <ccan/fdpass/fdpass.h>
|
||||
#include <ccan/io/fdpass/fdpass.h>
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/list/list.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <ccan/noerr/noerr.h>
|
||||
#include <ccan/take/take.h>
|
||||
@@ -53,8 +52,9 @@
|
||||
#include <gossipd/broadcast.h>
|
||||
#include <gossipd/gen_gossip_peerd_wire.h>
|
||||
#include <gossipd/gen_gossip_wire.h>
|
||||
#include <gossipd/gossipd.h>
|
||||
#include <gossipd/make_gossip.h>
|
||||
#include <gossipd/routing.h>
|
||||
#include <hsmd/gen_hsm_wire.h>
|
||||
#include <inttypes.h>
|
||||
#include <lightningd/gossip_msg.h>
|
||||
#include <netdb.h>
|
||||
@@ -71,11 +71,6 @@
|
||||
#include <wire/wire_sync.h>
|
||||
#include <zlib.h>
|
||||
|
||||
/* We talk to `hsmd` to sign our gossip messages with the node key */
|
||||
#define HSM_FD 3
|
||||
/* connectd asks us for help finding nodes, and gossip fds for new peers */
|
||||
#define CONNECTD_FD 4
|
||||
|
||||
/* In developer mode we provide hooks for whitebox testing */
|
||||
#if DEVELOPER
|
||||
static u32 max_encoding_bytes = -1U;
|
||||
@@ -110,52 +105,6 @@ static void towire_channel_update_timestamps(u8 **p,
|
||||
}
|
||||
#endif
|
||||
|
||||
/*~ The core daemon structure: */
|
||||
struct daemon {
|
||||
/* Who am I? Helps us find ourself in the routing map. */
|
||||
struct node_id id;
|
||||
|
||||
/* Peers we are gossiping to: id is unique */
|
||||
struct list_head peers;
|
||||
|
||||
/* Connection to lightningd. */
|
||||
struct daemon_conn *master;
|
||||
|
||||
/* Connection to connect daemon. */
|
||||
struct daemon_conn *connectd;
|
||||
|
||||
/* Routing information */
|
||||
struct routing_state *rstate;
|
||||
|
||||
/* chainhash for checking/making gossip msgs */
|
||||
struct bitcoin_blkid chain_hash;
|
||||
|
||||
/* Timers: we batch gossip, and also refresh announcements */
|
||||
struct timers timers;
|
||||
|
||||
/* Minimum interval for generating updated gossip */
|
||||
u32 gossip_min_interval;
|
||||
|
||||
/* Global features to list in node_announcement. */
|
||||
u8 *globalfeatures;
|
||||
|
||||
/* Alias (not NUL terminated) and favorite color for node_announcement */
|
||||
u8 alias[32];
|
||||
u8 rgb[3];
|
||||
|
||||
/* What addresses we can actually announce. */
|
||||
struct wireaddr *announcable;
|
||||
|
||||
/* Do we think we're missing gossip? Contains timer to re-check */
|
||||
struct oneshot *gossip_missing;
|
||||
|
||||
/* Channels we've heard about, but don't know. */
|
||||
struct short_channel_id *unknown_scids;
|
||||
|
||||
/* Timer until we can send a new node_announcement */
|
||||
struct oneshot *node_announce_timer;
|
||||
};
|
||||
|
||||
/*~ How gossipy do we ask a peer to be? */
|
||||
enum gossip_level {
|
||||
/* Give us everything since epoch */
|
||||
@@ -264,7 +213,7 @@ static void destroy_peer(struct peer *peer)
|
||||
}
|
||||
|
||||
/* Search for a peer. */
|
||||
static struct peer *find_peer(struct daemon *daemon, const struct node_id *id)
|
||||
struct peer *find_peer(struct daemon *daemon, const struct node_id *id)
|
||||
{
|
||||
struct peer *peer;
|
||||
|
||||
@@ -276,7 +225,7 @@ static struct peer *find_peer(struct daemon *daemon, const struct node_id *id)
|
||||
|
||||
/* Queue a gossip message for the peer: the subdaemon on the other end simply
|
||||
* forwards it to the peer. */
|
||||
static void queue_peer_msg(struct peer *peer, const u8 *msg TAKES)
|
||||
void queue_peer_msg(struct peer *peer, const u8 *msg TAKES)
|
||||
{
|
||||
daemon_conn_send(peer->dc, msg);
|
||||
}
|
||||
@@ -459,194 +408,6 @@ static void setup_gossip_range(struct peer *peer)
|
||||
queue_peer_msg(peer, take(msg));
|
||||
}
|
||||
|
||||
/*~ Create a node_announcement with the given signature. It may be NULL in the
|
||||
* case we need to create a provisional announcement for the HSM to sign.
|
||||
* This is called twice: once with the dummy signature to get it signed and a
|
||||
* second time to build the full packet with the signature. The timestamp is
|
||||
* handed in rather than using time_now() internally, since that could change
|
||||
* between the dummy creation and the call with a signature. */
|
||||
static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon,
|
||||
const secp256k1_ecdsa_signature *sig,
|
||||
u32 timestamp)
|
||||
{
|
||||
u8 *addresses = tal_arr(tmpctx, u8, 0);
|
||||
u8 *announcement;
|
||||
size_t i;
|
||||
|
||||
if (!sig)
|
||||
sig = talz(tmpctx, secp256k1_ecdsa_signature);
|
||||
|
||||
for (i = 0; i < tal_count(daemon->announcable); i++)
|
||||
towire_wireaddr(&addresses, &daemon->announcable[i]);
|
||||
|
||||
announcement =
|
||||
towire_node_announcement(ctx, sig, daemon->globalfeatures, timestamp,
|
||||
&daemon->id, daemon->rgb, daemon->alias,
|
||||
addresses);
|
||||
return announcement;
|
||||
}
|
||||
|
||||
/* Helper to get non-signature, non-timestamp parts of (valid!) channel_update */
|
||||
static void get_cupdate_parts(const u8 *channel_update,
|
||||
const u8 *parts[2],
|
||||
size_t sizes[2])
|
||||
{
|
||||
/* BOLT #7:
|
||||
*
|
||||
* 1. type: 258 (`channel_update`)
|
||||
* 2. data:
|
||||
* * [`signature`:`signature`]
|
||||
* * [`chain_hash`:`chain_hash`]
|
||||
* * [`short_channel_id`:`short_channel_id`]
|
||||
* * [`u32`:`timestamp`]
|
||||
*...
|
||||
*/
|
||||
/* Note: 2 bytes for `type` field */
|
||||
/* We already checked it's valid before accepting */
|
||||
assert(tal_count(channel_update) > 2 + 64 + 32 + 8 + 4);
|
||||
parts[0] = channel_update + 2 + 64;
|
||||
sizes[0] = 32 + 8;
|
||||
parts[1] = channel_update + 2 + 64 + 32 + 8 + 4;
|
||||
sizes[1] = tal_count(channel_update) - (64 + 2 + 32 + 8 + 4);
|
||||
}
|
||||
|
||||
/*~ Is this channel_update different from prev (not sigs and timestamps)? */
|
||||
static bool cupdate_different(struct gossip_store *gs,
|
||||
const struct half_chan *hc,
|
||||
const u8 *cupdate)
|
||||
{
|
||||
const u8 *oparts[2], *nparts[2];
|
||||
size_t osizes[2], nsizes[2];
|
||||
const u8 *orig;
|
||||
|
||||
/* Get last one we have. */
|
||||
orig = gossip_store_get(tmpctx, gs, hc->bcast.index);
|
||||
get_cupdate_parts(orig, oparts, osizes);
|
||||
get_cupdate_parts(cupdate, nparts, nsizes);
|
||||
|
||||
return !memeq(oparts[0], osizes[0], nparts[0], nsizes[0])
|
||||
|| !memeq(oparts[1], osizes[1], nparts[1], nsizes[1]);
|
||||
}
|
||||
|
||||
/* Get non-signature, non-timestamp parts of (valid!) node_announcement */
|
||||
static void get_nannounce_parts(const u8 *node_announcement,
|
||||
const u8 *parts[2],
|
||||
size_t sizes[2])
|
||||
{
|
||||
size_t len;
|
||||
const u8 *flen;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* 1. type: 257 (`node_announcement`)
|
||||
* 2. data:
|
||||
* * [`signature`:`signature`]
|
||||
* * [`u16`:`flen`]
|
||||
* * [`flen*byte`:`features`]
|
||||
* * [`u32`:`timestamp`]
|
||||
*...
|
||||
*/
|
||||
/* Note: 2 bytes for `type` field */
|
||||
/* We already checked it's valid before accepting */
|
||||
assert(tal_count(node_announcement) > 2 + 64);
|
||||
parts[0] = node_announcement + 2 + 64;
|
||||
|
||||
/* Read flen to get size */
|
||||
flen = parts[0];
|
||||
len = tal_count(node_announcement) - (2 + 64);
|
||||
sizes[0] = 2 + fromwire_u16(&flen, &len);
|
||||
assert(flen != NULL && len >= 4);
|
||||
|
||||
parts[1] = node_announcement + 2 + 64 + sizes[0] + 4;
|
||||
sizes[1] = tal_count(node_announcement) - (2 + 64 + sizes[0] + 4);
|
||||
}
|
||||
|
||||
/*~ Is this node_announcement different from prev (not sigs and timestamps)? */
|
||||
static bool nannounce_different(struct gossip_store *gs,
|
||||
const struct node *node,
|
||||
const u8 *nannounce)
|
||||
{
|
||||
const u8 *oparts[2], *nparts[2];
|
||||
size_t osizes[2], nsizes[2];
|
||||
const u8 *orig;
|
||||
|
||||
/* Get last one we have. */
|
||||
orig = gossip_store_get(tmpctx, gs, node->bcast.index);
|
||||
get_nannounce_parts(orig, oparts, osizes);
|
||||
get_nannounce_parts(nannounce, nparts, nsizes);
|
||||
|
||||
return !memeq(oparts[0], osizes[0], nparts[0], nsizes[0])
|
||||
|| !memeq(oparts[1], osizes[1], nparts[1], nsizes[1]);
|
||||
}
|
||||
|
||||
/*~ This routine created a `node_announcement` for our node, and hands it to
|
||||
* the routing.c code like any other `node_announcement`. Such announcements
|
||||
* are only accepted if there is an announced channel associated with that node
|
||||
* (to prevent spam), so we only call this once we've announced a channel. */
|
||||
static void update_own_node_announcement(struct daemon *daemon)
|
||||
{
|
||||
u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
u8 *msg, *nannounce, *err;
|
||||
struct node *self = get_node(daemon->rstate, &daemon->id);
|
||||
|
||||
/* Discard existing timer. */
|
||||
daemon->node_announce_timer = tal_free(daemon->node_announce_timer);
|
||||
|
||||
/* Make unsigned announcement. */
|
||||
nannounce = create_node_announcement(tmpctx, daemon, NULL, timestamp);
|
||||
|
||||
/* If it's the same as the previous, nothing to do. */
|
||||
if (self && self->bcast.index) {
|
||||
u32 next;
|
||||
|
||||
if (!nannounce_different(daemon->rstate->gs, self, nannounce))
|
||||
return;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The origin node:
|
||||
* - MUST set `timestamp` to be greater than that of any
|
||||
* previous `node_announcement` it has previously created.
|
||||
*/
|
||||
/* We do better: never send them within more than 5 minutes. */
|
||||
next = self->bcast.timestamp + daemon->gossip_min_interval;
|
||||
|
||||
if (timestamp < next) {
|
||||
status_debug("node_announcement: delaying %u secs",
|
||||
next - timestamp);
|
||||
daemon->node_announce_timer
|
||||
= new_reltimer(&daemon->timers,
|
||||
daemon,
|
||||
time_from_sec(next - timestamp),
|
||||
update_own_node_announcement,
|
||||
daemon);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ask hsmd to sign it (synchronous) */
|
||||
if (!wire_sync_write(HSM_FD, take(towire_hsm_node_announcement_sig_req(NULL, nannounce))))
|
||||
status_failed(STATUS_FAIL_MASTER_IO, "Could not write to HSM: %s", strerror(errno));
|
||||
|
||||
msg = wire_sync_read(tmpctx, HSM_FD);
|
||||
if (!fromwire_hsm_node_announcement_sig_reply(msg, &sig))
|
||||
status_failed(STATUS_FAIL_MASTER_IO, "HSM returned an invalid node_announcement sig");
|
||||
|
||||
/* We got the signature for our provisional node_announcement back
|
||||
* from the HSM, create the real announcement and forward it to
|
||||
* gossipd so it can take care of forwarding it. */
|
||||
nannounce = create_node_announcement(NULL, daemon, &sig, timestamp);
|
||||
|
||||
/* This injects it into the routing code in routing.c; it should not
|
||||
* reject it! */
|
||||
err = handle_node_announcement(daemon->rstate, take(nannounce));
|
||||
if (err)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"rejected own node announcement: %s",
|
||||
tal_hex(tmpctx, err));
|
||||
}
|
||||
|
||||
/*~ We don't actually keep node_announcements in memory; we keep them in
|
||||
* a file called `gossip_store`. If we need some node details, we reload
|
||||
* and reparse. It's slow, but generally rare. */
|
||||
@@ -714,20 +475,6 @@ static bool get_node_announcement_by_id(const tal_t *ctx,
|
||||
features, wireaddrs);
|
||||
}
|
||||
|
||||
/* Should we announce our own node? Called at strategic places. */
|
||||
static void maybe_send_own_node_announce(struct daemon *daemon)
|
||||
{
|
||||
/* We keep an internal flag in the routing code to say we've announced
|
||||
* a local channel. The alternative would be to have it make a
|
||||
* callback, but when we start up we don't want to make multiple
|
||||
* announcments, so we use this approach for now. */
|
||||
if (!daemon->rstate->local_channel_announced)
|
||||
return;
|
||||
|
||||
update_own_node_announcement(daemon);
|
||||
daemon->rstate->local_channel_announced = false;
|
||||
}
|
||||
|
||||
/* Query this peer for these short-channel-ids. */
|
||||
static bool query_short_channel_ids(struct daemon *daemon,
|
||||
struct peer *peer,
|
||||
@@ -1702,198 +1449,6 @@ static void dump_gossip(struct peer *peer)
|
||||
maybe_create_next_scid_reply(peer);
|
||||
}
|
||||
|
||||
/*~ Our timer callbacks take a single argument, so we marshall everything
|
||||
* we need into this structure: */
|
||||
struct local_cupdate {
|
||||
struct daemon *daemon;
|
||||
struct local_chan *local_chan;
|
||||
|
||||
bool disable;
|
||||
bool even_if_identical;
|
||||
|
||||
u16 cltv_expiry_delta;
|
||||
struct amount_msat htlc_minimum, htlc_maximum;
|
||||
u32 fee_base_msat, fee_proportional_millionths;
|
||||
};
|
||||
|
||||
/*~ This generates a `channel_update` message for one of our channels. We do
|
||||
* this here, rather than in `channeld` because we (may) need to do it
|
||||
* ourselves anyway if channeld dies, or when we refresh it once a week,
|
||||
* and so we can avoid creating redundant ones. */
|
||||
static void update_local_channel(struct local_cupdate *lc /* frees! */)
|
||||
{
|
||||
struct daemon *daemon = lc->daemon;
|
||||
secp256k1_ecdsa_signature dummy_sig;
|
||||
u8 *update, *msg;
|
||||
u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec, next;
|
||||
u8 message_flags, channel_flags;
|
||||
struct chan *chan = lc->local_chan->chan;
|
||||
struct half_chan *hc;
|
||||
const int direction = lc->local_chan->direction;
|
||||
|
||||
/* Discard existing timer. */
|
||||
lc->local_chan->channel_update_timer
|
||||
= tal_free(lc->local_chan->channel_update_timer);
|
||||
|
||||
/* So valgrind doesn't complain */
|
||||
memset(&dummy_sig, 0, sizeof(dummy_sig));
|
||||
|
||||
/* Create an unsigned channel_update: we backdate enables, so
|
||||
* we can always send a disable in an emergency. */
|
||||
if (!lc->disable)
|
||||
timestamp -= daemon->gossip_min_interval;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The `channel_flags` bitfield is used to indicate the direction of
|
||||
* the channel: it identifies the node that this update originated
|
||||
* from and signals various options concerning the channel. The
|
||||
* following table specifies the meaning of its individual bits:
|
||||
*
|
||||
* | Bit Position | Name | Meaning |
|
||||
* | ------------- | ----------- | -------------------------------- |
|
||||
* | 0 | `direction` | Direction this update refers to. |
|
||||
* | 1 | `disable` | Disable the channel. |
|
||||
*/
|
||||
channel_flags = direction;
|
||||
if (lc->disable)
|
||||
channel_flags |= ROUTING_FLAGS_DISABLED;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The `message_flags` bitfield is used to indicate the presence of
|
||||
* optional fields in the `channel_update` message:
|
||||
*
|
||||
*| Bit Position | Name | Field |
|
||||
*...
|
||||
*| 0 | `option_channel_htlc_max` | `htlc_maximum_msat` |
|
||||
*/
|
||||
message_flags = 0 | ROUTING_OPT_HTLC_MAX_MSAT;
|
||||
|
||||
/* We create an update with a dummy signature, and hand to hsmd to get
|
||||
* it signed. */
|
||||
update = towire_channel_update_option_channel_htlc_max(tmpctx, &dummy_sig,
|
||||
&daemon->chain_hash,
|
||||
&chan->scid,
|
||||
timestamp,
|
||||
message_flags, channel_flags,
|
||||
lc->cltv_expiry_delta,
|
||||
lc->htlc_minimum,
|
||||
lc->fee_base_msat,
|
||||
lc->fee_proportional_millionths,
|
||||
lc->htlc_maximum);
|
||||
|
||||
hc = &chan->half[direction];
|
||||
if (is_halfchan_defined(hc)) {
|
||||
/* Suppress duplicates. */
|
||||
if (!lc->even_if_identical
|
||||
&& !cupdate_different(daemon->rstate->gs, hc, update)) {
|
||||
tal_free(lc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is it too soon to send another update? */
|
||||
next = hc->bcast.timestamp + daemon->gossip_min_interval;
|
||||
|
||||
if (timestamp < next) {
|
||||
status_debug("channel_update %s/%u: delaying %u secs",
|
||||
type_to_string(tmpctx,
|
||||
struct short_channel_id,
|
||||
&chan->scid),
|
||||
direction,
|
||||
next - timestamp);
|
||||
lc->local_chan->channel_update_timer
|
||||
= new_reltimer(&daemon->timers, lc,
|
||||
time_from_sec(next - timestamp),
|
||||
update_local_channel,
|
||||
lc);
|
||||
/* If local chan vanishes, so does update, and timer. */
|
||||
notleak(tal_steal(lc->local_chan, lc));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that we treat the hsmd as synchronous. This is simple (no
|
||||
* callback hell)!, but may need to change to async if we ever want
|
||||
* remote HSMs */
|
||||
if (!wire_sync_write(HSM_FD,
|
||||
towire_hsm_cupdate_sig_req(tmpctx, update))) {
|
||||
status_failed(STATUS_FAIL_HSM_IO, "Writing cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
msg = wire_sync_read(tmpctx, HSM_FD);
|
||||
if (!msg || !fromwire_hsm_cupdate_sig_reply(NULL, msg, &update)) {
|
||||
status_failed(STATUS_FAIL_HSM_IO,
|
||||
"Reading cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The origin node:
|
||||
* - MAY create a `channel_update` to communicate the channel parameters to the
|
||||
* channel peer, even though the channel has not yet been announced (i.e. the
|
||||
* `announce_channel` bit was not set).
|
||||
*/
|
||||
if (!is_chan_public(chan)) {
|
||||
/* handle_channel_update will not put private updates in the
|
||||
* broadcast list, but we send it direct to the peer (if we
|
||||
* have one connected) now */
|
||||
struct peer *peer = find_peer(daemon,
|
||||
&chan->nodes[!direction]->id);
|
||||
if (peer)
|
||||
queue_peer_msg(peer, update);
|
||||
}
|
||||
|
||||
/* We feed it into routing.c like any other channel_update; it may
|
||||
* discard it (eg. non-public channel), but it should not complain
|
||||
* about it being invalid! __func__ is a magic C constant which
|
||||
* expands to this function name. */
|
||||
msg = handle_channel_update(daemon->rstate, take(update), __func__,
|
||||
NULL);
|
||||
if (msg)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"%s: rejected local channel update %s: %s",
|
||||
__func__,
|
||||
/* Normally we must not touch something taken()
|
||||
* but we're in deep trouble anyway, and
|
||||
* handle_channel_update only tal_steals onto
|
||||
* tmpctx, so it's actually OK. */
|
||||
tal_hex(tmpctx, update),
|
||||
tal_hex(tmpctx, msg));
|
||||
tal_free(lc);
|
||||
}
|
||||
|
||||
/*~ This is a refresh of a local channel: sends an update if one is needed. */
|
||||
static void refresh_local_channel(struct daemon *daemon,
|
||||
struct local_chan *local_chan,
|
||||
bool even_if_identical)
|
||||
{
|
||||
const struct half_chan *hc;
|
||||
struct local_cupdate *lc;
|
||||
|
||||
hc = &local_chan->chan->half[local_chan->direction];
|
||||
|
||||
/* Don't generate a channel_update for an uninitialized channel. */
|
||||
if (!is_halfchan_defined(hc))
|
||||
return;
|
||||
|
||||
lc = tal(NULL, struct local_cupdate);
|
||||
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;
|
||||
|
||||
update_local_channel(lc);
|
||||
}
|
||||
|
||||
/*~ This is when channeld asks us for a channel_update for a local channel.
|
||||
* It does that to fill in the error field when lightningd fails an HTLC and
|
||||
* sets the UPDATE bit in the error type. lightningd is too important to
|
||||
@@ -1948,52 +1503,6 @@ out:
|
||||
return true;
|
||||
}
|
||||
|
||||
/*~ channeld asks us to update the local channel. */
|
||||
static bool handle_local_channel_update(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
struct short_channel_id scid;
|
||||
struct local_cupdate *lc = tal(tmpctx, struct local_cupdate);
|
||||
|
||||
lc->daemon = peer->daemon;
|
||||
lc->even_if_identical = false;
|
||||
|
||||
/* FIXME: We should get scid from lightningd when setting up the
|
||||
* connection, so no per-peer daemon can mess with channels other than
|
||||
* its own! */
|
||||
if (!fromwire_gossipd_local_channel_update(msg,
|
||||
&scid,
|
||||
&lc->disable,
|
||||
&lc->cltv_expiry_delta,
|
||||
&lc->htlc_minimum,
|
||||
&lc->fee_base_msat,
|
||||
&lc->fee_proportional_millionths,
|
||||
&lc->htlc_maximum)) {
|
||||
status_broken("peer %s bad local_channel_update %s",
|
||||
type_to_string(tmpctx, struct node_id, &peer->id),
|
||||
tal_hex(tmpctx, msg));
|
||||
return false;
|
||||
}
|
||||
|
||||
lc->local_chan = local_chan_map_get(&peer->daemon->rstate->local_chan_map,
|
||||
&scid);
|
||||
/* Can theoretically happen if channel just closed. */
|
||||
if (!lc->local_chan) {
|
||||
status_debug("peer %s local_channel_update for unknown %s",
|
||||
type_to_string(tmpctx, struct node_id, &peer->id),
|
||||
type_to_string(tmpctx, struct short_channel_id,
|
||||
&scid));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Remove soft local_disabled flag, if they're marking it enabled. */
|
||||
if (!lc->disable)
|
||||
local_enable_chan(peer->daemon->rstate, lc->local_chan->chan);
|
||||
|
||||
/* Apply the update they told us */
|
||||
update_local_channel(tal_steal(NULL, lc));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*~ This is where the per-peer daemons send us messages. It's either forwarded
|
||||
* gossip, or a request for information. We deliberately use non-overlapping
|
||||
* message types so we can distinguish them. */
|
||||
@@ -2069,7 +1578,7 @@ static struct io_plan *peer_msg_in(struct io_conn *conn,
|
||||
ok = handle_local_add_channel(peer->daemon->rstate, msg, 0);
|
||||
goto handled_cmd;
|
||||
case WIRE_GOSSIPD_LOCAL_CHANNEL_UPDATE:
|
||||
ok = handle_local_channel_update(peer, msg);
|
||||
ok = handle_local_channel_update(peer->daemon, &peer->id, msg);
|
||||
goto handled_cmd;
|
||||
|
||||
/* These are the ones we send, not them */
|
||||
|
||||
65
gossipd/gossipd.h
Normal file
65
gossipd/gossipd.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef LIGHTNING_GOSSIPD_GOSSIPD_H
|
||||
#define LIGHTNING_GOSSIPD_GOSSIPD_H
|
||||
#include "config.h"
|
||||
#include <ccan/list/list.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <common/node_id.h>
|
||||
|
||||
/* We talk to `hsmd` to sign our gossip messages with the node key */
|
||||
#define HSM_FD 3
|
||||
/* connectd asks us for help finding nodes, and gossip fds for new peers */
|
||||
#define CONNECTD_FD 4
|
||||
|
||||
/*~ The core daemon structure: */
|
||||
struct daemon {
|
||||
/* Who am I? Helps us find ourself in the routing map. */
|
||||
struct node_id id;
|
||||
|
||||
/* Peers we are gossiping to: id is unique */
|
||||
struct list_head peers;
|
||||
|
||||
/* Connection to lightningd. */
|
||||
struct daemon_conn *master;
|
||||
|
||||
/* Connection to connect daemon. */
|
||||
struct daemon_conn *connectd;
|
||||
|
||||
/* Routing information */
|
||||
struct routing_state *rstate;
|
||||
|
||||
/* chainhash for checking/making gossip msgs */
|
||||
struct bitcoin_blkid chain_hash;
|
||||
|
||||
/* Timers: we batch gossip, and also refresh announcements */
|
||||
struct timers timers;
|
||||
|
||||
/* Minimum interval for generating updated gossip */
|
||||
u32 gossip_min_interval;
|
||||
|
||||
/* Global features to list in node_announcement. */
|
||||
u8 *globalfeatures;
|
||||
|
||||
/* Alias (not NUL terminated) and favorite color for node_announcement */
|
||||
u8 alias[32];
|
||||
u8 rgb[3];
|
||||
|
||||
/* What addresses we can actually announce. */
|
||||
struct wireaddr *announcable;
|
||||
|
||||
/* Do we think we're missing gossip? Contains timer to re-check */
|
||||
struct oneshot *gossip_missing;
|
||||
|
||||
/* Channels we've heard about, but don't know. */
|
||||
struct short_channel_id *unknown_scids;
|
||||
|
||||
/* Timer until we can send a new node_announcement */
|
||||
struct oneshot *node_announce_timer;
|
||||
};
|
||||
|
||||
/* Search for a peer. */
|
||||
struct peer *find_peer(struct daemon *daemon, const struct node_id *id);
|
||||
|
||||
/* Queue a gossip message for the peer: the subdaemon on the other end simply
|
||||
* forwards it to the peer. */
|
||||
void queue_peer_msg(struct peer *peer, const u8 *msg TAKES);
|
||||
#endif /* LIGHTNING_GOSSIPD_GOSSIPD_H */
|
||||
456
gossipd/make_gossip.c
Normal file
456
gossipd/make_gossip.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/* Routines to make our own gossip messages */
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/timeout.h>
|
||||
#include <common/utils.h>
|
||||
#include <common/wireaddr.h>
|
||||
#include <errno.h>
|
||||
#include <gossipd/gen_gossip_peerd_wire.h>
|
||||
#include <gossipd/gossip_store.h>
|
||||
#include <gossipd/gossipd.h>
|
||||
#include <gossipd/make_gossip.h>
|
||||
#include <hsmd/gen_hsm_wire.h>
|
||||
#include <wire/gen_peer_wire.h>
|
||||
#include <wire/wire_sync.h>
|
||||
|
||||
/* Create a node_announcement with the given signature. It may be NULL in the
|
||||
* case we need to create a provisional announcement for the HSM to sign.
|
||||
* This is called twice: once with the dummy signature to get it signed and a
|
||||
* second time to build the full packet with the signature. The timestamp is
|
||||
* handed in rather than using time_now() internally, since that could change
|
||||
* between the dummy creation and the call with a signature. */
|
||||
static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon,
|
||||
const secp256k1_ecdsa_signature *sig,
|
||||
u32 timestamp)
|
||||
{
|
||||
u8 *addresses = tal_arr(tmpctx, u8, 0);
|
||||
u8 *announcement;
|
||||
size_t i;
|
||||
|
||||
if (!sig)
|
||||
sig = talz(tmpctx, secp256k1_ecdsa_signature);
|
||||
|
||||
for (i = 0; i < tal_count(daemon->announcable); i++)
|
||||
towire_wireaddr(&addresses, &daemon->announcable[i]);
|
||||
|
||||
announcement =
|
||||
towire_node_announcement(ctx, sig, daemon->globalfeatures, timestamp,
|
||||
&daemon->id, daemon->rgb, daemon->alias,
|
||||
addresses);
|
||||
return announcement;
|
||||
}
|
||||
|
||||
/* Helper to get non-signature, non-timestamp parts of (valid!) channel_update */
|
||||
void get_cupdate_parts(const u8 *channel_update,
|
||||
const u8 *parts[2],
|
||||
size_t sizes[2])
|
||||
{
|
||||
/* BOLT #7:
|
||||
*
|
||||
* 1. type: 258 (`channel_update`)
|
||||
* 2. data:
|
||||
* * [`signature`:`signature`]
|
||||
* * [`chain_hash`:`chain_hash`]
|
||||
* * [`short_channel_id`:`short_channel_id`]
|
||||
* * [`u32`:`timestamp`]
|
||||
*...
|
||||
*/
|
||||
/* Note: 2 bytes for `type` field */
|
||||
/* We already checked it's valid before accepting */
|
||||
assert(tal_count(channel_update) > 2 + 64 + 32 + 8 + 4);
|
||||
parts[0] = channel_update + 2 + 64;
|
||||
sizes[0] = 32 + 8;
|
||||
parts[1] = channel_update + 2 + 64 + 32 + 8 + 4;
|
||||
sizes[1] = tal_count(channel_update) - (64 + 2 + 32 + 8 + 4);
|
||||
}
|
||||
|
||||
/* Is this channel_update different from prev (not sigs and timestamps)? */
|
||||
bool cupdate_different(struct gossip_store *gs,
|
||||
const struct half_chan *hc,
|
||||
const u8 *cupdate)
|
||||
{
|
||||
const u8 *oparts[2], *nparts[2];
|
||||
size_t osizes[2], nsizes[2];
|
||||
const u8 *orig;
|
||||
|
||||
/* Get last one we have. */
|
||||
orig = gossip_store_get(tmpctx, gs, hc->bcast.index);
|
||||
get_cupdate_parts(orig, oparts, osizes);
|
||||
get_cupdate_parts(cupdate, nparts, nsizes);
|
||||
|
||||
return !memeq(oparts[0], osizes[0], nparts[0], nsizes[0])
|
||||
|| !memeq(oparts[1], osizes[1], nparts[1], nsizes[1]);
|
||||
}
|
||||
|
||||
/* Get non-signature, non-timestamp parts of (valid!) node_announcement */
|
||||
static void get_nannounce_parts(const u8 *node_announcement,
|
||||
const u8 *parts[2],
|
||||
size_t sizes[2])
|
||||
{
|
||||
size_t len;
|
||||
const u8 *flen;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* 1. type: 257 (`node_announcement`)
|
||||
* 2. data:
|
||||
* * [`signature`:`signature`]
|
||||
* * [`u16`:`flen`]
|
||||
* * [`flen*byte`:`features`]
|
||||
* * [`u32`:`timestamp`]
|
||||
*...
|
||||
*/
|
||||
/* Note: 2 bytes for `type` field */
|
||||
/* We already checked it's valid before accepting */
|
||||
assert(tal_count(node_announcement) > 2 + 64);
|
||||
parts[0] = node_announcement + 2 + 64;
|
||||
|
||||
/* Read flen to get size */
|
||||
flen = parts[0];
|
||||
len = tal_count(node_announcement) - (2 + 64);
|
||||
sizes[0] = 2 + fromwire_u16(&flen, &len);
|
||||
assert(flen != NULL && len >= 4);
|
||||
|
||||
parts[1] = node_announcement + 2 + 64 + sizes[0] + 4;
|
||||
sizes[1] = tal_count(node_announcement) - (2 + 64 + sizes[0] + 4);
|
||||
}
|
||||
|
||||
/* Is this node_announcement different from prev (not sigs and timestamps)? */
|
||||
bool nannounce_different(struct gossip_store *gs,
|
||||
const struct node *node,
|
||||
const u8 *nannounce)
|
||||
{
|
||||
const u8 *oparts[2], *nparts[2];
|
||||
size_t osizes[2], nsizes[2];
|
||||
const u8 *orig;
|
||||
|
||||
/* Get last one we have. */
|
||||
orig = gossip_store_get(tmpctx, gs, node->bcast.index);
|
||||
get_nannounce_parts(orig, oparts, osizes);
|
||||
get_nannounce_parts(nannounce, nparts, nsizes);
|
||||
|
||||
return !memeq(oparts[0], osizes[0], nparts[0], nsizes[0])
|
||||
|| !memeq(oparts[1], osizes[1], nparts[1], nsizes[1]);
|
||||
}
|
||||
|
||||
/* This routine created a `node_announcement` for our node, and hands it to
|
||||
* the routing.c code like any other `node_announcement`. Such announcements
|
||||
* are only accepted if there is an announced channel associated with that node
|
||||
* (to prevent spam), so we only call this once we've announced a channel. */
|
||||
static void update_own_node_announcement(struct daemon *daemon)
|
||||
{
|
||||
u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
u8 *msg, *nannounce, *err;
|
||||
struct node *self = get_node(daemon->rstate, &daemon->id);
|
||||
|
||||
/* Discard existing timer. */
|
||||
daemon->node_announce_timer = tal_free(daemon->node_announce_timer);
|
||||
|
||||
/* Make unsigned announcement. */
|
||||
nannounce = create_node_announcement(tmpctx, daemon, NULL, timestamp);
|
||||
|
||||
/* If it's the same as the previous, nothing to do. */
|
||||
if (self && self->bcast.index) {
|
||||
u32 next;
|
||||
|
||||
if (!nannounce_different(daemon->rstate->gs, self, nannounce))
|
||||
return;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The origin node:
|
||||
* - MUST set `timestamp` to be greater than that of any
|
||||
* previous `node_announcement` it has previously created.
|
||||
*/
|
||||
/* We do better: never send them within more than 5 minutes. */
|
||||
next = self->bcast.timestamp + daemon->gossip_min_interval;
|
||||
|
||||
if (timestamp < next) {
|
||||
status_debug("node_announcement: delaying %u secs",
|
||||
next - timestamp);
|
||||
daemon->node_announce_timer
|
||||
= new_reltimer(&daemon->timers,
|
||||
daemon,
|
||||
time_from_sec(next - timestamp),
|
||||
update_own_node_announcement,
|
||||
daemon);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ask hsmd to sign it (synchronous) */
|
||||
if (!wire_sync_write(HSM_FD, take(towire_hsm_node_announcement_sig_req(NULL, nannounce))))
|
||||
status_failed(STATUS_FAIL_MASTER_IO, "Could not write to HSM: %s", strerror(errno));
|
||||
|
||||
msg = wire_sync_read(tmpctx, HSM_FD);
|
||||
if (!fromwire_hsm_node_announcement_sig_reply(msg, &sig))
|
||||
status_failed(STATUS_FAIL_MASTER_IO, "HSM returned an invalid node_announcement sig");
|
||||
|
||||
/* We got the signature for our provisional node_announcement back
|
||||
* from the HSM, create the real announcement and forward it to
|
||||
* gossipd so it can take care of forwarding it. */
|
||||
nannounce = create_node_announcement(NULL, daemon, &sig, timestamp);
|
||||
|
||||
/* This injects it into the routing code in routing.c; it should not
|
||||
* reject it! */
|
||||
err = handle_node_announcement(daemon->rstate, take(nannounce));
|
||||
if (err)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"rejected own node announcement: %s",
|
||||
tal_hex(tmpctx, err));
|
||||
}
|
||||
|
||||
/* Should we announce our own node? Called at strategic places. */
|
||||
void maybe_send_own_node_announce(struct daemon *daemon)
|
||||
{
|
||||
/* We keep an internal flag in the routing code to say we've announced
|
||||
* a local channel. The alternative would be to have it make a
|
||||
* callback, but when we start up we don't want to make multiple
|
||||
* announcments, so we use this approach for now. */
|
||||
if (!daemon->rstate->local_channel_announced)
|
||||
return;
|
||||
|
||||
update_own_node_announcement(daemon);
|
||||
daemon->rstate->local_channel_announced = false;
|
||||
}
|
||||
|
||||
/* Our timer callbacks take a single argument, so we marshall everything
|
||||
* we need into this structure: */
|
||||
struct local_cupdate {
|
||||
struct daemon *daemon;
|
||||
struct local_chan *local_chan;
|
||||
|
||||
bool disable;
|
||||
bool even_if_identical;
|
||||
|
||||
u16 cltv_expiry_delta;
|
||||
struct amount_msat htlc_minimum, htlc_maximum;
|
||||
u32 fee_base_msat, fee_proportional_millionths;
|
||||
};
|
||||
|
||||
/* This generates a `channel_update` message for one of our channels. We do
|
||||
* this here, rather than in `channeld` because we (may) need to do it
|
||||
* ourselves anyway if channeld dies, or when we refresh it once a week,
|
||||
* and so we can avoid creating redundant ones. */
|
||||
static void update_local_channel(struct local_cupdate *lc /* frees! */)
|
||||
{
|
||||
struct daemon *daemon = lc->daemon;
|
||||
secp256k1_ecdsa_signature dummy_sig;
|
||||
u8 *update, *msg;
|
||||
u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec, next;
|
||||
u8 message_flags, channel_flags;
|
||||
struct chan *chan = lc->local_chan->chan;
|
||||
struct half_chan *hc;
|
||||
const int direction = lc->local_chan->direction;
|
||||
|
||||
/* Discard existing timer. */
|
||||
lc->local_chan->channel_update_timer
|
||||
= tal_free(lc->local_chan->channel_update_timer);
|
||||
|
||||
/* So valgrind doesn't complain */
|
||||
memset(&dummy_sig, 0, sizeof(dummy_sig));
|
||||
|
||||
/* Create an unsigned channel_update: we backdate enables, so
|
||||
* we can always send a disable in an emergency. */
|
||||
if (!lc->disable)
|
||||
timestamp -= daemon->gossip_min_interval;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The `channel_flags` bitfield is used to indicate the direction of
|
||||
* the channel: it identifies the node that this update originated
|
||||
* from and signals various options concerning the channel. The
|
||||
* following table specifies the meaning of its individual bits:
|
||||
*
|
||||
* | Bit Position | Name | Meaning |
|
||||
* | ------------- | ----------- | -------------------------------- |
|
||||
* | 0 | `direction` | Direction this update refers to. |
|
||||
* | 1 | `disable` | Disable the channel. |
|
||||
*/
|
||||
channel_flags = direction;
|
||||
if (lc->disable)
|
||||
channel_flags |= ROUTING_FLAGS_DISABLED;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The `message_flags` bitfield is used to indicate the presence of
|
||||
* optional fields in the `channel_update` message:
|
||||
*
|
||||
*| Bit Position | Name | Field |
|
||||
*...
|
||||
*| 0 | `option_channel_htlc_max` | `htlc_maximum_msat` |
|
||||
*/
|
||||
message_flags = 0 | ROUTING_OPT_HTLC_MAX_MSAT;
|
||||
|
||||
/* We create an update with a dummy signature, and hand to hsmd to get
|
||||
* it signed. */
|
||||
update = towire_channel_update_option_channel_htlc_max(tmpctx, &dummy_sig,
|
||||
&daemon->chain_hash,
|
||||
&chan->scid,
|
||||
timestamp,
|
||||
message_flags, channel_flags,
|
||||
lc->cltv_expiry_delta,
|
||||
lc->htlc_minimum,
|
||||
lc->fee_base_msat,
|
||||
lc->fee_proportional_millionths,
|
||||
lc->htlc_maximum);
|
||||
|
||||
hc = &chan->half[direction];
|
||||
if (is_halfchan_defined(hc)) {
|
||||
/* Suppress duplicates. */
|
||||
if (!lc->even_if_identical
|
||||
&& !cupdate_different(daemon->rstate->gs, hc, update)) {
|
||||
tal_free(lc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is it too soon to send another update? */
|
||||
next = hc->bcast.timestamp + daemon->gossip_min_interval;
|
||||
|
||||
if (timestamp < next) {
|
||||
status_debug("channel_update %s/%u: delaying %u secs",
|
||||
type_to_string(tmpctx,
|
||||
struct short_channel_id,
|
||||
&chan->scid),
|
||||
direction,
|
||||
next - timestamp);
|
||||
lc->local_chan->channel_update_timer
|
||||
= new_reltimer(&daemon->timers, lc,
|
||||
time_from_sec(next - timestamp),
|
||||
update_local_channel,
|
||||
lc);
|
||||
/* If local chan vanishes, so does update, and timer. */
|
||||
notleak(tal_steal(lc->local_chan, lc));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that we treat the hsmd as synchronous. This is simple (no
|
||||
* callback hell)!, but may need to change to async if we ever want
|
||||
* remote HSMs */
|
||||
if (!wire_sync_write(HSM_FD,
|
||||
towire_hsm_cupdate_sig_req(tmpctx, update))) {
|
||||
status_failed(STATUS_FAIL_HSM_IO, "Writing cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
msg = wire_sync_read(tmpctx, HSM_FD);
|
||||
if (!msg || !fromwire_hsm_cupdate_sig_reply(NULL, msg, &update)) {
|
||||
status_failed(STATUS_FAIL_HSM_IO,
|
||||
"Reading cupdate_sig_req: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The origin node:
|
||||
* - MAY create a `channel_update` to communicate the channel parameters to the
|
||||
* channel peer, even though the channel has not yet been announced (i.e. the
|
||||
* `announce_channel` bit was not set).
|
||||
*/
|
||||
if (!is_chan_public(chan)) {
|
||||
/* handle_channel_update will not put private updates in the
|
||||
* broadcast list, but we send it direct to the peer (if we
|
||||
* have one connected) now */
|
||||
struct peer *peer = find_peer(daemon,
|
||||
&chan->nodes[!direction]->id);
|
||||
if (peer)
|
||||
queue_peer_msg(peer, update);
|
||||
}
|
||||
|
||||
/* We feed it into routing.c like any other channel_update; it may
|
||||
* discard it (eg. non-public channel), but it should not complain
|
||||
* about it being invalid! __func__ is a magic C constant which
|
||||
* expands to this function name. */
|
||||
msg = handle_channel_update(daemon->rstate, take(update), __func__,
|
||||
NULL);
|
||||
if (msg)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"%s: rejected local channel update %s: %s",
|
||||
__func__,
|
||||
/* Normally we must not touch something taken()
|
||||
* but we're in deep trouble anyway, and
|
||||
* handle_channel_update only tal_steals onto
|
||||
* tmpctx, so it's actually OK. */
|
||||
tal_hex(tmpctx, update),
|
||||
tal_hex(tmpctx, msg));
|
||||
tal_free(lc);
|
||||
}
|
||||
|
||||
/* This is a refresh of a local channel: sends an update if one is needed. */
|
||||
void refresh_local_channel(struct daemon *daemon,
|
||||
struct local_chan *local_chan,
|
||||
bool even_if_identical)
|
||||
{
|
||||
const struct half_chan *hc;
|
||||
struct local_cupdate *lc;
|
||||
|
||||
hc = &local_chan->chan->half[local_chan->direction];
|
||||
|
||||
/* Don't generate a channel_update for an uninitialized channel. */
|
||||
if (!is_halfchan_defined(hc))
|
||||
return;
|
||||
|
||||
lc = tal(NULL, struct local_cupdate);
|
||||
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;
|
||||
|
||||
update_local_channel(lc);
|
||||
}
|
||||
|
||||
/* channeld asks us to update the local channel. */
|
||||
bool handle_local_channel_update(struct daemon *daemon,
|
||||
const struct node_id *src,
|
||||
const u8 *msg)
|
||||
{
|
||||
struct short_channel_id scid;
|
||||
struct local_cupdate *lc = tal(tmpctx, struct local_cupdate);
|
||||
|
||||
lc->daemon = daemon;
|
||||
lc->even_if_identical = false;
|
||||
|
||||
/* FIXME: We should get scid from lightningd when setting up the
|
||||
* connection, so no per-peer daemon can mess with channels other than
|
||||
* its own! */
|
||||
if (!fromwire_gossipd_local_channel_update(msg,
|
||||
&scid,
|
||||
&lc->disable,
|
||||
&lc->cltv_expiry_delta,
|
||||
&lc->htlc_minimum,
|
||||
&lc->fee_base_msat,
|
||||
&lc->fee_proportional_millionths,
|
||||
&lc->htlc_maximum)) {
|
||||
status_broken("peer %s bad local_channel_update %s",
|
||||
type_to_string(tmpctx, struct node_id, src),
|
||||
tal_hex(tmpctx, msg));
|
||||
return false;
|
||||
}
|
||||
|
||||
lc->local_chan = local_chan_map_get(&daemon->rstate->local_chan_map,
|
||||
&scid);
|
||||
/* Can theoretically happen if channel just closed. */
|
||||
if (!lc->local_chan) {
|
||||
status_debug("peer %s local_channel_update for unknown %s",
|
||||
type_to_string(tmpctx, struct node_id, src),
|
||||
type_to_string(tmpctx, struct short_channel_id,
|
||||
&scid));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Remove soft local_disabled flag, if they're marking it enabled. */
|
||||
if (!lc->disable)
|
||||
local_enable_chan(daemon->rstate, lc->local_chan->chan);
|
||||
|
||||
/* Apply the update they told us */
|
||||
update_local_channel(tal_steal(NULL, lc));
|
||||
return true;
|
||||
}
|
||||
47
gossipd/make_gossip.h
Normal file
47
gossipd/make_gossip.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef LIGHTNING_GOSSIPD_MAKE_GOSSIP_H
|
||||
#define LIGHTNING_GOSSIPD_MAKE_GOSSIP_H
|
||||
#include "config.h"
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct chan;
|
||||
struct daemon;
|
||||
struct half_chan;
|
||||
struct local_chan;
|
||||
struct gossip_store;
|
||||
struct peer;
|
||||
struct node;
|
||||
|
||||
/* Helper to get non-signature, non-timestamp parts of (valid!) channel_update */
|
||||
void get_cupdate_parts(const u8 *channel_update,
|
||||
const u8 *parts[2],
|
||||
size_t sizes[2]);
|
||||
|
||||
|
||||
/* Is this channel_update different from prev (not sigs and timestamps)?
|
||||
* is_halfchan_defined(hc) must be true! */
|
||||
bool cupdate_different(struct gossip_store *gs,
|
||||
const struct half_chan *hc,
|
||||
const u8 *cupdate);
|
||||
|
||||
/* Is this node_announcement different from prev (not sigs and timestamps)?
|
||||
* node->bcast.index must be non-zero! */
|
||||
bool nannounce_different(struct gossip_store *gs,
|
||||
const struct node *node,
|
||||
const u8 *nannounce);
|
||||
|
||||
/* Should we announce our own node? Called at strategic places. */
|
||||
void maybe_send_own_node_announce(struct daemon *daemon);
|
||||
|
||||
/* This is a refresh of a local channel: sends an update if one is needed. */
|
||||
void refresh_local_channel(struct daemon *daemon,
|
||||
struct local_chan *local_chan,
|
||||
bool even_if_identical);
|
||||
|
||||
/* channeld asks us to update the local channel. */
|
||||
bool handle_local_channel_update(struct daemon *daemon,
|
||||
const struct node_id *src,
|
||||
const u8 *msg);
|
||||
|
||||
#endif /* LIGHTNING_GOSSIPD_MAKE_GOSSIP_H */
|
||||
@@ -68,9 +68,6 @@ bool fromwire_gossip_dev_suppress(const void *p UNNEEDED)
|
||||
/* Generated stub for fromwire_gossipd_get_update */
|
||||
bool fromwire_gossipd_get_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossipd_get_update called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossipd_local_channel_update */
|
||||
bool fromwire_gossipd_local_channel_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, bool *disable UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, struct amount_msat *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, struct amount_msat *htlc_maximum_msat UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossipd_local_channel_update called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_get_addrs */
|
||||
bool fromwire_gossip_get_addrs(const void *p UNNEEDED, struct node_id *id UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_get_addrs called!\n"); abort(); }
|
||||
@@ -116,18 +113,17 @@ bool fromwire_gossip_query_scids(const tal_t *ctx UNNEEDED, const void *p UNNEED
|
||||
/* Generated stub for fromwire_gossip_send_timestamp_filter */
|
||||
bool fromwire_gossip_send_timestamp_filter(const void *p UNNEEDED, struct node_id *id UNNEEDED, u32 *first_timestamp UNNEEDED, u32 *timestamp_range UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_send_timestamp_filter called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_hsm_cupdate_sig_reply */
|
||||
bool fromwire_hsm_cupdate_sig_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **cu UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_hsm_cupdate_sig_reply called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_hsm_node_announcement_sig_reply */
|
||||
bool fromwire_hsm_node_announcement_sig_reply(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_hsm_node_announcement_sig_reply called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_incorrect_cltv_expiry */
|
||||
bool fromwire_incorrect_cltv_expiry(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u32 *cltv_expiry UNNEEDED, u8 **channel_update UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_incorrect_cltv_expiry called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_temporary_channel_failure */
|
||||
bool fromwire_temporary_channel_failure(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **channel_update UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_temporary_channel_failure called!\n"); abort(); }
|
||||
/* Generated stub for get_cupdate_parts */
|
||||
void get_cupdate_parts(const u8 *channel_update UNNEEDED,
|
||||
const u8 *parts[2] UNNEEDED,
|
||||
size_t sizes[2])
|
||||
{ fprintf(stderr, "get_cupdate_parts called!\n"); abort(); }
|
||||
/* Generated stub for get_node */
|
||||
struct node *get_node(struct routing_state *rstate UNNEEDED,
|
||||
const struct node_id *id UNNEEDED)
|
||||
@@ -180,6 +176,11 @@ u8 *handle_channel_update(struct routing_state *rstate UNNEEDED, const u8 *updat
|
||||
bool handle_local_add_channel(struct routing_state *rstate UNNEEDED, const u8 *msg UNNEEDED,
|
||||
u64 index UNNEEDED)
|
||||
{ fprintf(stderr, "handle_local_add_channel called!\n"); abort(); }
|
||||
/* Generated stub for handle_local_channel_update */
|
||||
bool handle_local_channel_update(struct daemon *daemon UNNEEDED,
|
||||
const struct node_id *src UNNEEDED,
|
||||
const u8 *msg UNNEEDED)
|
||||
{ fprintf(stderr, "handle_local_channel_update called!\n"); abort(); }
|
||||
/* Generated stub for handle_node_announcement */
|
||||
u8 *handle_node_announcement(struct routing_state *rstate UNNEEDED, const u8 *node UNNEEDED)
|
||||
{ fprintf(stderr, "handle_node_announcement called!\n"); abort(); }
|
||||
@@ -195,6 +196,9 @@ u8 *make_ping(const tal_t *ctx UNNEEDED, u16 num_pong_bytes UNNEEDED, u16 padlen
|
||||
/* Generated stub for master_badmsg */
|
||||
void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)
|
||||
{ fprintf(stderr, "master_badmsg called!\n"); abort(); }
|
||||
/* Generated stub for maybe_send_own_node_announce */
|
||||
void maybe_send_own_node_announce(struct daemon *daemon UNNEEDED)
|
||||
{ fprintf(stderr, "maybe_send_own_node_announce called!\n"); abort(); }
|
||||
/* Generated stub for memleak_enter_allocations */
|
||||
struct htable *memleak_enter_allocations(const tal_t *ctx UNNEEDED,
|
||||
const void *exclude1 UNNEEDED,
|
||||
@@ -215,7 +219,7 @@ struct routing_state *new_routing_state(const tal_t *ctx UNNEEDED,
|
||||
const struct node_id *local_id UNNEEDED,
|
||||
u32 prune_timeout UNNEEDED,
|
||||
struct list_head *peers UNNEEDED,
|
||||
const u32 *dev_gossip_time UNNEEDED)
|
||||
const u32 *dev_gossip_time TAKES UNNEEDED)
|
||||
{ fprintf(stderr, "new_routing_state called!\n"); abort(); }
|
||||
/* Generated stub for next_chan */
|
||||
struct chan *next_chan(const struct node *node UNNEEDED, struct chan_map_iter *i UNNEEDED)
|
||||
@@ -226,6 +230,11 @@ void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
|
||||
/* Generated stub for read_addresses */
|
||||
struct wireaddr *read_addresses(const tal_t *ctx UNNEEDED, const u8 *ser UNNEEDED)
|
||||
{ fprintf(stderr, "read_addresses called!\n"); abort(); }
|
||||
/* Generated stub for refresh_local_channel */
|
||||
void refresh_local_channel(struct daemon *daemon UNNEEDED,
|
||||
struct local_chan *local_chan UNNEEDED,
|
||||
bool even_if_identical UNNEEDED)
|
||||
{ fprintf(stderr, "refresh_local_channel called!\n"); abort(); }
|
||||
/* Generated stub for remove_channel_from_store */
|
||||
void remove_channel_from_store(struct routing_state *rstate UNNEEDED,
|
||||
struct chan *chan UNNEEDED)
|
||||
@@ -308,21 +317,6 @@ u8 *towire_gossip_query_channel_range_reply(const tal_t *ctx UNNEEDED, u32 final
|
||||
/* Generated stub for towire_gossip_scids_reply */
|
||||
u8 *towire_gossip_scids_reply(const tal_t *ctx UNNEEDED, bool ok UNNEEDED, bool complete UNNEEDED)
|
||||
{ fprintf(stderr, "towire_gossip_scids_reply called!\n"); abort(); }
|
||||
/* Generated stub for towire_hsm_cupdate_sig_req */
|
||||
u8 *towire_hsm_cupdate_sig_req(const tal_t *ctx UNNEEDED, const u8 *cu UNNEEDED)
|
||||
{ fprintf(stderr, "towire_hsm_cupdate_sig_req called!\n"); abort(); }
|
||||
/* Generated stub for towire_hsm_node_announcement_sig_req */
|
||||
u8 *towire_hsm_node_announcement_sig_req(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
||||
{ fprintf(stderr, "towire_hsm_node_announcement_sig_req called!\n"); abort(); }
|
||||
/* Generated stub for towire_wireaddr */
|
||||
void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED)
|
||||
{ fprintf(stderr, "towire_wireaddr called!\n"); abort(); }
|
||||
/* Generated stub for wire_sync_read */
|
||||
u8 *wire_sync_read(const tal_t *ctx UNNEEDED, int fd UNNEEDED)
|
||||
{ fprintf(stderr, "wire_sync_read called!\n"); abort(); }
|
||||
/* Generated stub for wire_sync_write */
|
||||
bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED)
|
||||
{ fprintf(stderr, "wire_sync_write called!\n"); abort(); }
|
||||
/* AUTOGENERATED MOCKS END */
|
||||
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
|
||||
@@ -91,9 +91,6 @@ bool fromwire_gossip_dev_suppress(const void *p UNNEEDED)
|
||||
/* Generated stub for fromwire_gossipd_get_update */
|
||||
bool fromwire_gossipd_get_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossipd_get_update called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossipd_local_channel_update */
|
||||
bool fromwire_gossipd_local_channel_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, bool *disable UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, struct amount_msat *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, struct amount_msat *htlc_maximum_msat UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossipd_local_channel_update called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_get_addrs */
|
||||
bool fromwire_gossip_get_addrs(const void *p UNNEEDED, struct node_id *id UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_get_addrs called!\n"); abort(); }
|
||||
@@ -139,18 +136,17 @@ bool fromwire_gossip_query_scids(const tal_t *ctx UNNEEDED, const void *p UNNEED
|
||||
/* Generated stub for fromwire_gossip_send_timestamp_filter */
|
||||
bool fromwire_gossip_send_timestamp_filter(const void *p UNNEEDED, struct node_id *id UNNEEDED, u32 *first_timestamp UNNEEDED, u32 *timestamp_range UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_send_timestamp_filter called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_hsm_cupdate_sig_reply */
|
||||
bool fromwire_hsm_cupdate_sig_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **cu UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_hsm_cupdate_sig_reply called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_hsm_node_announcement_sig_reply */
|
||||
bool fromwire_hsm_node_announcement_sig_reply(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_hsm_node_announcement_sig_reply called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_incorrect_cltv_expiry */
|
||||
bool fromwire_incorrect_cltv_expiry(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u32 *cltv_expiry UNNEEDED, u8 **channel_update UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_incorrect_cltv_expiry called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_temporary_channel_failure */
|
||||
bool fromwire_temporary_channel_failure(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **channel_update UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_temporary_channel_failure called!\n"); abort(); }
|
||||
/* Generated stub for get_cupdate_parts */
|
||||
void get_cupdate_parts(const u8 *channel_update UNNEEDED,
|
||||
const u8 *parts[2] UNNEEDED,
|
||||
size_t sizes[2])
|
||||
{ fprintf(stderr, "get_cupdate_parts called!\n"); abort(); }
|
||||
/* Generated stub for get_node */
|
||||
struct node *get_node(struct routing_state *rstate UNNEEDED,
|
||||
const struct node_id *id UNNEEDED)
|
||||
@@ -203,6 +199,11 @@ u8 *handle_channel_update(struct routing_state *rstate UNNEEDED, const u8 *updat
|
||||
bool handle_local_add_channel(struct routing_state *rstate UNNEEDED, const u8 *msg UNNEEDED,
|
||||
u64 index UNNEEDED)
|
||||
{ fprintf(stderr, "handle_local_add_channel called!\n"); abort(); }
|
||||
/* Generated stub for handle_local_channel_update */
|
||||
bool handle_local_channel_update(struct daemon *daemon UNNEEDED,
|
||||
const struct node_id *src UNNEEDED,
|
||||
const u8 *msg UNNEEDED)
|
||||
{ fprintf(stderr, "handle_local_channel_update called!\n"); abort(); }
|
||||
/* Generated stub for handle_node_announcement */
|
||||
u8 *handle_node_announcement(struct routing_state *rstate UNNEEDED, const u8 *node UNNEEDED)
|
||||
{ fprintf(stderr, "handle_node_announcement called!\n"); abort(); }
|
||||
@@ -218,6 +219,9 @@ u8 *make_ping(const tal_t *ctx UNNEEDED, u16 num_pong_bytes UNNEEDED, u16 padlen
|
||||
/* Generated stub for master_badmsg */
|
||||
void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)
|
||||
{ fprintf(stderr, "master_badmsg called!\n"); abort(); }
|
||||
/* Generated stub for maybe_send_own_node_announce */
|
||||
void maybe_send_own_node_announce(struct daemon *daemon UNNEEDED)
|
||||
{ fprintf(stderr, "maybe_send_own_node_announce called!\n"); abort(); }
|
||||
/* Generated stub for memleak_enter_allocations */
|
||||
struct htable *memleak_enter_allocations(const tal_t *ctx UNNEEDED,
|
||||
const void *exclude1 UNNEEDED,
|
||||
@@ -238,7 +242,7 @@ struct routing_state *new_routing_state(const tal_t *ctx UNNEEDED,
|
||||
const struct node_id *local_id UNNEEDED,
|
||||
u32 prune_timeout UNNEEDED,
|
||||
struct list_head *peers UNNEEDED,
|
||||
const u32 *dev_gossip_time UNNEEDED)
|
||||
const u32 *dev_gossip_time TAKES UNNEEDED)
|
||||
{ fprintf(stderr, "new_routing_state called!\n"); abort(); }
|
||||
/* Generated stub for next_chan */
|
||||
struct chan *next_chan(const struct node *node UNNEEDED, struct chan_map_iter *i UNNEEDED)
|
||||
@@ -249,6 +253,11 @@ void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
|
||||
/* Generated stub for read_addresses */
|
||||
struct wireaddr *read_addresses(const tal_t *ctx UNNEEDED, const u8 *ser UNNEEDED)
|
||||
{ fprintf(stderr, "read_addresses called!\n"); abort(); }
|
||||
/* Generated stub for refresh_local_channel */
|
||||
void refresh_local_channel(struct daemon *daemon UNNEEDED,
|
||||
struct local_chan *local_chan UNNEEDED,
|
||||
bool even_if_identical UNNEEDED)
|
||||
{ fprintf(stderr, "refresh_local_channel called!\n"); abort(); }
|
||||
/* Generated stub for remove_channel_from_store */
|
||||
void remove_channel_from_store(struct routing_state *rstate UNNEEDED,
|
||||
struct chan *chan UNNEEDED)
|
||||
@@ -327,21 +336,6 @@ u8 *towire_gossip_query_channel_range_reply(const tal_t *ctx UNNEEDED, u32 final
|
||||
/* Generated stub for towire_gossip_scids_reply */
|
||||
u8 *towire_gossip_scids_reply(const tal_t *ctx UNNEEDED, bool ok UNNEEDED, bool complete UNNEEDED)
|
||||
{ fprintf(stderr, "towire_gossip_scids_reply called!\n"); abort(); }
|
||||
/* Generated stub for towire_hsm_cupdate_sig_req */
|
||||
u8 *towire_hsm_cupdate_sig_req(const tal_t *ctx UNNEEDED, const u8 *cu UNNEEDED)
|
||||
{ fprintf(stderr, "towire_hsm_cupdate_sig_req called!\n"); abort(); }
|
||||
/* Generated stub for towire_hsm_node_announcement_sig_req */
|
||||
u8 *towire_hsm_node_announcement_sig_req(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
||||
{ fprintf(stderr, "towire_hsm_node_announcement_sig_req called!\n"); abort(); }
|
||||
/* Generated stub for towire_wireaddr */
|
||||
void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED)
|
||||
{ fprintf(stderr, "towire_wireaddr called!\n"); abort(); }
|
||||
/* Generated stub for wire_sync_read */
|
||||
u8 *wire_sync_read(const tal_t *ctx UNNEEDED, int fd UNNEEDED)
|
||||
{ fprintf(stderr, "wire_sync_read called!\n"); abort(); }
|
||||
/* Generated stub for wire_sync_write */
|
||||
bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED)
|
||||
{ fprintf(stderr, "wire_sync_write called!\n"); abort(); }
|
||||
/* AUTOGENERATED MOCKS END */
|
||||
|
||||
#if DEVELOPER
|
||||
|
||||
Reference in New Issue
Block a user