lightningd/channel_gossip: new file for handing and generating gossip for our channels.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -6,6 +6,7 @@ LIGHTNINGD_SRC := \
|
||||
lightningd/chaintopology.c \
|
||||
lightningd/channel.c \
|
||||
lightningd/channel_control.c \
|
||||
lightningd/channel_gossip.c \
|
||||
lightningd/closing_control.c \
|
||||
lightningd/coin_mvts.c \
|
||||
lightningd/dual_open_control.c \
|
||||
|
||||
@@ -141,6 +141,9 @@ struct channel {
|
||||
/* Is there a single subdaemon responsible for us? */
|
||||
struct subd *owner;
|
||||
|
||||
/* Telling the world (or just our peer) about us */
|
||||
struct channel_gossip *channel_gossip;
|
||||
|
||||
/* History */
|
||||
struct logger *log;
|
||||
struct billboard billboard;
|
||||
|
||||
970
lightningd/channel_gossip.c
Normal file
970
lightningd/channel_gossip.c
Normal file
@@ -0,0 +1,970 @@
|
||||
#include "config.h"
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/timeout.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <common/wire_error.h>
|
||||
#include <connectd/connectd_wiregen.h>
|
||||
#include <hsmd/hsmd_wiregen.h>
|
||||
#include <lightningd/chaintopology.h>
|
||||
#include <lightningd/channel.h>
|
||||
#include <lightningd/channel_gossip.h>
|
||||
#include <lightningd/gossip_generation.h>
|
||||
#include <lightningd/hsm_control.h>
|
||||
#include <lightningd/lightningd.h>
|
||||
#include <lightningd/peer_control.h>
|
||||
#include <lightningd/subd.h>
|
||||
|
||||
enum channel_gossip_state {
|
||||
/* Not a public channel */
|
||||
CGOSSIP_PRIVATE,
|
||||
/* We can't yet send (non-forwardable) channel_update. */
|
||||
CGOSSIP_NOT_USABLE,
|
||||
/* Not yet in at announcable depth. */
|
||||
CGOSSIP_NOT_DEEP_ENOUGH,
|
||||
/* We want the peer's announcement_signatures. */
|
||||
CGOSSIP_NEED_PEER_SIGS,
|
||||
/* We have received sigs, and announced. */
|
||||
CGOSSIP_ANNOUNCED,
|
||||
};
|
||||
|
||||
struct remote_announce_sigs {
|
||||
struct short_channel_id scid;
|
||||
secp256k1_ecdsa_signature node_sig;
|
||||
secp256k1_ecdsa_signature bitcoin_sig;
|
||||
};
|
||||
|
||||
struct channel_gossip {
|
||||
enum channel_gossip_state state;
|
||||
|
||||
/* Cached update info */
|
||||
const u8 *cupdate;
|
||||
|
||||
/* Remote channel_announcement sigs we've received (but not
|
||||
* necessarily committed!) */
|
||||
struct remote_announce_sigs *remote_sigs;
|
||||
|
||||
/* Timer to refresh public channels every 13 days */
|
||||
struct oneshot *refresh_timer;
|
||||
|
||||
/* Details of latest channel_update sent by peer */
|
||||
const struct peer_update *peer_update;
|
||||
};
|
||||
|
||||
/* FIXME: this is a hack! We should wait 1 minute after connectd has
|
||||
* tried to connect to all peers. */
|
||||
static bool starting_up = true;
|
||||
|
||||
/* We send non-forwardable channel updates if we can. */
|
||||
static bool can_send_channel_update(const struct channel *channel)
|
||||
{
|
||||
/* Can't send if we can't talk about it. */
|
||||
if (!channel->scid && !channel->alias[REMOTE])
|
||||
return false;
|
||||
if (channel_state_pre_open(channel->state))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We send start the channel announcement signatures if we can.
|
||||
* Caller must check it's not CGOSSIP_PRIVATE, but this is used
|
||||
* to set up state so we cannot assert here!
|
||||
*/
|
||||
static bool channel_announceable(const struct channel *channel,
|
||||
u32 block_height)
|
||||
{
|
||||
if (!channel->scid)
|
||||
return false;
|
||||
return is_scid_depth_announceable(channel->scid, block_height);
|
||||
}
|
||||
|
||||
static void check_channel_gossip(const struct channel *channel)
|
||||
{
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
/* Note: we can't assert is_scid_depth_announceable, for two reasons:
|
||||
* 1. on restart and rescan, block numbers can go backwards.'
|
||||
* 2. We don't get notified via channel_gossip_notify_new_block until
|
||||
* there are no new blocks to add, not on every block.
|
||||
*/
|
||||
switch (cg->state) {
|
||||
case CGOSSIP_PRIVATE:
|
||||
assert(!(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL));
|
||||
assert(!cg->remote_sigs);
|
||||
assert(!cg->refresh_timer);
|
||||
return;
|
||||
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
assert(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL);
|
||||
assert(!can_send_channel_update(channel));
|
||||
assert(!cg->refresh_timer);
|
||||
return;
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
assert(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL);
|
||||
assert(can_send_channel_update(channel));
|
||||
assert(!cg->refresh_timer);
|
||||
return;
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
assert(can_send_channel_update(channel));
|
||||
assert(channel->scid);
|
||||
/* If we have sigs, they don't match */
|
||||
if (cg->remote_sigs)
|
||||
assert(!channel->scid || !short_channel_id_eq(&cg->remote_sigs->scid, channel->scid));
|
||||
assert(!cg->refresh_timer);
|
||||
return;
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
assert(can_send_channel_update(channel));
|
||||
assert(channel->scid);
|
||||
assert(cg->remote_sigs);
|
||||
return;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", cg->state);
|
||||
}
|
||||
|
||||
/* Recursion */
|
||||
static void cupdate_timer_refresh(struct channel *channel);
|
||||
|
||||
static void set_public_cupdate(struct channel *channel,
|
||||
const u8 *cupdate TAKES)
|
||||
{
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
u32 timestamp;
|
||||
bool enabled;
|
||||
struct timeabs now, due;
|
||||
|
||||
if (!channel_update_details(cupdate, ×tamp, &enabled)) {
|
||||
log_broken(channel->log, "Invalid channel_update %s: ignoring",
|
||||
tal_hex(tmpctx, cupdate));
|
||||
if (taken(cupdate))
|
||||
tal_free(cupdate);
|
||||
return;
|
||||
}
|
||||
|
||||
tal_free(cg->cupdate);
|
||||
cg->cupdate = tal_dup_talarr(cg, u8, cupdate);
|
||||
|
||||
cg->refresh_timer = tal_free(cg->refresh_timer);
|
||||
|
||||
/* If enabled, we refresh, based on old timestamp */
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
due.ts.tv_sec = timestamp;
|
||||
due.ts.tv_nsec = 0;
|
||||
due = timeabs_add(due,
|
||||
time_from_sec(GOSSIP_PRUNE_INTERVAL(ld->dev_fast_gossip_prune)
|
||||
- GOSSIP_BEFORE_DEADLINE(ld->dev_fast_gossip_prune)));
|
||||
|
||||
/* In case it's passed, timer should be zero */
|
||||
now = time_now();
|
||||
if (time_after(now, due))
|
||||
due = now;
|
||||
|
||||
cg->refresh_timer = new_reltimer(ld->timers, cg,
|
||||
time_between(due, now),
|
||||
cupdate_timer_refresh,
|
||||
channel);
|
||||
}
|
||||
|
||||
static void msg_to_peer(const struct channel *channel, const u8 *msg TAKES)
|
||||
{
|
||||
struct peer *peer = channel->peer;
|
||||
struct lightningd *ld = peer->ld;
|
||||
|
||||
/* Shutting down, or peer not connected? */
|
||||
if (ld->connectd && peer->connected == PEER_CONNECTED) {
|
||||
subd_send_msg(ld->connectd,
|
||||
take(towire_connectd_peer_send_msg(NULL,
|
||||
&peer->id,
|
||||
peer->connectd_counter,
|
||||
msg)));
|
||||
}
|
||||
|
||||
if (taken(msg))
|
||||
tal_free(msg);
|
||||
}
|
||||
|
||||
static enum channel_gossip_state init_public_state(struct channel *channel,
|
||||
const struct remote_announce_sigs *remote_sigs)
|
||||
{
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
|
||||
if (!can_send_channel_update(channel))
|
||||
return CGOSSIP_NOT_USABLE;
|
||||
|
||||
/* Note: depth when we startup is not actually reliable, since
|
||||
* we step one block back. We'll fix this up when gossipd
|
||||
* tells us it's announced, or, when we add the block. */
|
||||
if (!channel_announceable(channel, get_block_height(ld->topology)))
|
||||
return CGOSSIP_NOT_DEEP_ENOUGH;
|
||||
|
||||
if (!remote_sigs) {
|
||||
return CGOSSIP_NEED_PEER_SIGS;
|
||||
}
|
||||
|
||||
return CGOSSIP_ANNOUNCED;
|
||||
}
|
||||
|
||||
static u8 *sign_update(const tal_t *ctx,
|
||||
struct lightningd *ld,
|
||||
const u8 *unsigned_cupdate)
|
||||
{
|
||||
const u8 *msg;
|
||||
u8 *signed_update;
|
||||
|
||||
/* Sign it please! */
|
||||
msg = hsm_sync_req(tmpctx, ld,
|
||||
take(towire_hsmd_cupdate_sig_req(NULL, unsigned_cupdate)));
|
||||
|
||||
if (!fromwire_hsmd_cupdate_sig_reply(ctx, msg, &signed_update))
|
||||
fatal("Reading cupdate_sig_reply: %s", tal_hex(tmpctx, msg));
|
||||
return signed_update;
|
||||
}
|
||||
|
||||
/* Try to send a channel_update direct to peer, unless redundant */
|
||||
static void send_private_cupdate(struct channel *channel, bool even_if_redundant)
|
||||
{
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
const u8 *cupdate;
|
||||
const struct short_channel_id *scid;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* - 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).
|
||||
* - MUST set the `short_channel_id` to either an `alias` it has
|
||||
* received from the peer, or the real channel `short_channel_id`.
|
||||
* - MUST set `dont_forward` to 1 in `message_flags`
|
||||
*/
|
||||
/* We prefer their alias, if possible: they might not have seen the block which
|
||||
* mined the funding tx yet, so the scid would be meaningless to them. */
|
||||
if (channel->alias[REMOTE])
|
||||
scid = channel->alias[REMOTE];
|
||||
else
|
||||
scid = channel->scid;
|
||||
|
||||
/* Only useful channels: not if closing */
|
||||
if (!channel_state_can_add_htlc(channel->state))
|
||||
return;
|
||||
|
||||
/* We always set "enabled" on unannounced channels, since if peer
|
||||
* receives it, that's what it means */
|
||||
cupdate = unsigned_channel_update(tmpctx, channel, scid,
|
||||
NULL, false, true);
|
||||
|
||||
/* Suppress redundant ones (except on reconnect, in case it's
|
||||
* lost) */
|
||||
if (cg->cupdate) {
|
||||
if (!even_if_redundant
|
||||
&& channel_update_same(cg->cupdate, cupdate)) {
|
||||
return;
|
||||
}
|
||||
tal_free(cg->cupdate);
|
||||
}
|
||||
|
||||
cg->cupdate = sign_update(cg, channel->peer->ld, cupdate);
|
||||
msg_to_peer(channel, cg->cupdate);
|
||||
}
|
||||
|
||||
static void broadcast_public_cupdate_addgossip_reply(struct subd *gossip UNUSED,
|
||||
const u8 *reply,
|
||||
const int *fds UNUSED,
|
||||
struct channel *channel)
|
||||
{
|
||||
char *err;
|
||||
|
||||
if (!fromwire_gossipd_addgossip_reply(reply, reply, &err))
|
||||
fatal("Reading broadcast_public_cupdate_addgossip_reply: %s",
|
||||
tal_hex(tmpctx, reply));
|
||||
|
||||
if (strlen(err))
|
||||
log_broken(channel->log, "gossipd rejected our channel update: %s", err);
|
||||
}
|
||||
|
||||
/* Send gossipd a channel_update, if not redundant. */
|
||||
static void broadcast_public_cupdate(struct channel *channel,
|
||||
bool ok_if_disconnected)
|
||||
{
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
const u8 *cupdate;
|
||||
u32 old_timestamp;
|
||||
bool enable, have_old;
|
||||
|
||||
/* If we have no previous channel_update, this fails */
|
||||
have_old = channel_update_details(cg->cupdate,
|
||||
&old_timestamp, &enable);
|
||||
|
||||
if (!channel_state_can_add_htlc(channel->state)) {
|
||||
/* If it's (no longer) usable, it's a simply courtesy
|
||||
* to disable */
|
||||
enable = false;
|
||||
} else if (channel->owner) {
|
||||
/* If it's live, it's enabled */
|
||||
enable = true;
|
||||
} else if (starting_up) {
|
||||
/* If we are starting up, don't change it! */
|
||||
if (!have_old)
|
||||
/* Assume the best if we don't have an updated */
|
||||
enable = true;
|
||||
} else {
|
||||
enable = ok_if_disconnected;
|
||||
}
|
||||
|
||||
cupdate = unsigned_channel_update(tmpctx, channel, channel->scid,
|
||||
have_old ? &old_timestamp : NULL,
|
||||
true,
|
||||
enable);
|
||||
|
||||
/* Suppress redundant ones */
|
||||
if (cg->cupdate && channel_update_same(cg->cupdate, cupdate))
|
||||
return;
|
||||
|
||||
set_public_cupdate(channel,
|
||||
take(sign_update(NULL, channel->peer->ld, cupdate)));
|
||||
|
||||
subd_req(ld->gossip, ld->gossip,
|
||||
take(towire_gossipd_addgossip(NULL, cg->cupdate)),
|
||||
-1, 0, broadcast_public_cupdate_addgossip_reply, channel);
|
||||
}
|
||||
|
||||
static void cupdate_timer_refresh(struct channel *channel)
|
||||
{
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
/* Don't try to free this again if set_public_cupdate called later */
|
||||
cg->refresh_timer = NULL;
|
||||
|
||||
log_debug(channel->log, "Sending keepalive channel_update for %s",
|
||||
short_channel_id_to_str(tmpctx, channel->scid));
|
||||
|
||||
/* Free old cupdate to force a new one to be generated */
|
||||
cg->cupdate = tal_free(cg->cupdate);
|
||||
broadcast_public_cupdate(channel, true);
|
||||
}
|
||||
|
||||
static void stash_remote_announce_sigs(struct channel *channel,
|
||||
struct short_channel_id scid,
|
||||
const secp256k1_ecdsa_signature *node_sig,
|
||||
const secp256k1_ecdsa_signature *bitcoin_sig)
|
||||
{
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
tal_free(cg->remote_sigs);
|
||||
cg->remote_sigs = tal(cg, struct remote_announce_sigs);
|
||||
cg->remote_sigs->scid = scid;
|
||||
cg->remote_sigs->node_sig = *node_sig;
|
||||
cg->remote_sigs->bitcoin_sig = *bitcoin_sig;
|
||||
log_debug(channel->log,
|
||||
"channel_gossip: received announcement sigs for %s (we have %s)",
|
||||
short_channel_id_to_str(tmpctx, &scid),
|
||||
channel->scid ? short_channel_id_to_str(tmpctx, channel->scid) : "none");
|
||||
}
|
||||
|
||||
static bool apply_remote_sigs(struct channel *channel)
|
||||
{
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
if (!cg->remote_sigs)
|
||||
return false;
|
||||
|
||||
if (!short_channel_id_eq(&cg->remote_sigs->scid, channel->scid)) {
|
||||
log_debug(channel->log, "We have remote sigs, but wrong scid!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* FIXME: check sigs are valid! */
|
||||
wallet_announcement_save(channel->peer->ld->wallet,
|
||||
channel->dbid,
|
||||
&cg->remote_sigs->node_sig,
|
||||
&cg->remote_sigs->bitcoin_sig);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void send_channel_announce_sigs(struct channel *channel)
|
||||
{
|
||||
/* First 2 + 256 byte are the signatures and msg type, skip them */
|
||||
const size_t offset = 258;
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
struct sha256_double hash;
|
||||
secp256k1_ecdsa_signature local_node_sig, local_bitcoin_sig;
|
||||
struct pubkey mykey;
|
||||
const u8 *ca, *msg;
|
||||
|
||||
/* If it's already closing, don't bother. */
|
||||
if (!channel_state_can_add_htlc(channel->state))
|
||||
return;
|
||||
|
||||
ca = create_channel_announcement(tmpctx, channel,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
msg = hsm_sync_req(tmpctx, ld,
|
||||
take(towire_hsmd_sign_any_cannouncement_req(NULL,
|
||||
ca,
|
||||
&channel->peer->id,
|
||||
channel->dbid)));
|
||||
if (!fromwire_hsmd_sign_any_cannouncement_reply(msg, &local_node_sig, &local_bitcoin_sig))
|
||||
fatal("Reading hsmd_sign_any_cannouncement_reply: %s", tal_hex(tmpctx, msg));
|
||||
|
||||
/* Double-check that HSM gave valid signatures. */
|
||||
sha256_double(&hash, ca + offset, tal_count(ca) - offset);
|
||||
if (!pubkey_from_node_id(&mykey, &ld->id))
|
||||
fatal("Could not convert own public key");
|
||||
|
||||
if (!check_signed_hash(&hash, &local_node_sig, &mykey)) {
|
||||
channel_internal_error(channel,
|
||||
"HSM returned an invalid node signature");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!check_signed_hash(&hash, &local_bitcoin_sig, &channel->local_funding_pubkey)) {
|
||||
channel_internal_error(channel,
|
||||
"HSM returned an invalid bitcoin signature");
|
||||
return;
|
||||
}
|
||||
|
||||
msg = towire_announcement_signatures(NULL,
|
||||
&channel->cid, channel->scid,
|
||||
&local_node_sig, &local_bitcoin_sig);
|
||||
msg_to_peer(channel, take(msg));
|
||||
}
|
||||
|
||||
static void send_channel_announce_addgossip_reply(struct subd *gossip UNUSED,
|
||||
const u8 *reply,
|
||||
const int *fds UNUSED,
|
||||
struct channel *channel)
|
||||
{
|
||||
char *err;
|
||||
|
||||
if (!fromwire_gossipd_addgossip_reply(reply, reply, &err))
|
||||
fatal("Reading send_channel_announce_addgossip_reply: %s",
|
||||
tal_hex(tmpctx, reply));
|
||||
|
||||
if (strlen(err))
|
||||
log_broken(channel->log, "gossipd rejected our channel announcement: %s", err);
|
||||
}
|
||||
|
||||
static void send_channel_announcement(struct channel *channel)
|
||||
{
|
||||
secp256k1_ecdsa_signature local_node_sig, local_bitcoin_sig;
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
const u8 *ca, *msg;
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
ca = create_channel_announcement(tmpctx, channel,
|
||||
NULL, NULL,
|
||||
&cg->remote_sigs->node_sig,
|
||||
&cg->remote_sigs->bitcoin_sig);
|
||||
|
||||
msg = hsm_sync_req(tmpctx, ld,
|
||||
take(towire_hsmd_sign_any_cannouncement_req(NULL, ca,
|
||||
&channel->peer->id,
|
||||
channel->dbid)));
|
||||
if (!fromwire_hsmd_sign_any_cannouncement_reply(msg,
|
||||
&local_node_sig,
|
||||
&local_bitcoin_sig))
|
||||
fatal("Reading hsmd_sign_any_cannouncement_reply: %s", tal_hex(tmpctx, msg));
|
||||
|
||||
/* Don't crash if shutting down */
|
||||
if (!ld->gossip)
|
||||
return;
|
||||
|
||||
ca = create_channel_announcement(tmpctx, channel,
|
||||
&local_node_sig,
|
||||
&local_bitcoin_sig,
|
||||
&cg->remote_sigs->node_sig,
|
||||
&cg->remote_sigs->bitcoin_sig);
|
||||
|
||||
subd_req(ld->gossip, ld->gossip,
|
||||
take(towire_gossipd_addgossip(NULL, ca)),
|
||||
-1, 0, send_channel_announce_addgossip_reply, channel);
|
||||
/* We can also send our first public channel_update now */
|
||||
broadcast_public_cupdate(channel, true);
|
||||
}
|
||||
|
||||
static void set_gossip_state(struct channel *channel,
|
||||
enum channel_gossip_state state)
|
||||
{
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
cg->state = state;
|
||||
|
||||
switch (cg->state) {
|
||||
case CGOSSIP_PRIVATE:
|
||||
abort();
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
return;
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
/* But it exists, so try sending private channel_update */
|
||||
send_private_cupdate(channel, false);
|
||||
return;
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
send_channel_announce_sigs(channel);
|
||||
/* We may already have remote signatures */
|
||||
if (!apply_remote_sigs(channel))
|
||||
return;
|
||||
cg->state = CGOSSIP_ANNOUNCED;
|
||||
/* fall thru */
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
/* Any previous update was private, so clear. */
|
||||
cg->cupdate = tal_free(cg->cupdate);
|
||||
send_channel_announcement(channel);
|
||||
return;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", cg->state);
|
||||
}
|
||||
|
||||
/* Initialize channel->channel_gossip state */
|
||||
void channel_gossip_init(struct channel *channel,
|
||||
const struct peer_update *remote_update)
|
||||
{
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
struct channel_gossip *cg;
|
||||
bool public = (channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL);
|
||||
|
||||
cg = channel->channel_gossip = tal(channel, struct channel_gossip);
|
||||
cg->cupdate = NULL;
|
||||
cg->refresh_timer = NULL;
|
||||
cg->peer_update = tal_dup_or_null(channel, struct peer_update, remote_update);
|
||||
cg->remote_sigs = NULL;
|
||||
|
||||
/* If we have an scid, we might have announcement signatures
|
||||
* saved in the db already. */
|
||||
if (channel->scid && public) {
|
||||
cg->remote_sigs = tal(cg, struct remote_announce_sigs);
|
||||
cg->remote_sigs->scid = *channel->scid;
|
||||
if (!wallet_remote_ann_sigs_load(ld->wallet,
|
||||
channel,
|
||||
&cg->remote_sigs->node_sig,
|
||||
&cg->remote_sigs->bitcoin_sig)) {
|
||||
cg->remote_sigs = tal_free(cg->remote_sigs);
|
||||
}
|
||||
}
|
||||
|
||||
if (public)
|
||||
cg->state = init_public_state(channel, cg->remote_sigs);
|
||||
else
|
||||
cg->state = CGOSSIP_PRIVATE;
|
||||
|
||||
check_channel_gossip(channel);
|
||||
}
|
||||
|
||||
/* Something about channel changed: update if required */
|
||||
void channel_gossip_update(struct channel *channel)
|
||||
{
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
/* Ignore unsaved channels */
|
||||
if (!cg)
|
||||
return;
|
||||
|
||||
switch (cg->state) {
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
/* Change might make it usable */
|
||||
if (!can_send_channel_update(channel)) {
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
}
|
||||
set_gossip_state(channel, CGOSSIP_NOT_DEEP_ENOUGH);
|
||||
/* fall thru */
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
/* Now we can send at non-forwardable update */
|
||||
send_private_cupdate(channel, false);
|
||||
/* Might have gotten straight from not-usable to announceable
|
||||
* if we have a flurry of blocks, or minconf >= 6. */
|
||||
if (!channel_announceable(channel, get_block_height(ld->topology))) {
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
}
|
||||
set_gossip_state(channel, CGOSSIP_NEED_PEER_SIGS);
|
||||
/* Could have actually already had sigs! */
|
||||
if (cg->state == CGOSSIP_ANNOUNCED)
|
||||
goto announced;
|
||||
/* fall thru */
|
||||
case CGOSSIP_PRIVATE:
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
send_private_cupdate(channel, false);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
announced:
|
||||
/* We don't penalize disconnected clients normally: we only
|
||||
* do that if we actually try to send an htlc through */
|
||||
broadcast_public_cupdate(channel, true);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", channel->channel_gossip->state);
|
||||
}
|
||||
|
||||
void channel_gossip_got_announcement_sigs(struct channel *channel,
|
||||
struct short_channel_id scid,
|
||||
const secp256k1_ecdsa_signature *node_sig,
|
||||
const secp256k1_ecdsa_signature *bitcoin_sig)
|
||||
{
|
||||
/* Ignore unsaved channels */
|
||||
if (!channel->channel_gossip) {
|
||||
log_broken(channel->log, "They sent an announcement_signatures message for a unsaved channel? Ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (channel->channel_gossip->state) {
|
||||
case CGOSSIP_PRIVATE:
|
||||
log_unusual(channel->log, "They sent an announcement_signatures message for a private channel? Ignoring.");
|
||||
u8 *warning = towire_warningfmt(NULL,
|
||||
&channel->cid,
|
||||
"You sent announcement_signatures for private channel");
|
||||
msg_to_peer(channel, take(warning));
|
||||
return;
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
/* They're early? */
|
||||
stash_remote_announce_sigs(channel,
|
||||
scid, node_sig, bitcoin_sig);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
stash_remote_announce_sigs(channel,
|
||||
scid, node_sig, bitcoin_sig);
|
||||
if (apply_remote_sigs(channel))
|
||||
set_gossip_state(channel, CGOSSIP_ANNOUNCED);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
/* BOLT #7:
|
||||
* - upon reconnection (once the above timing requirements
|
||||
* have been met):
|
||||
* - MUST respond to the first `announcement_signatures`
|
||||
* message with its own `announcement_signatures` message.
|
||||
*/
|
||||
send_channel_announce_sigs(channel);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", channel->channel_gossip->state);
|
||||
}
|
||||
|
||||
/* Short channel id changed (splice, or reorg). */
|
||||
void channel_gossip_scid_changed(struct channel *channel)
|
||||
{
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
/* Ignore unsaved channels */
|
||||
if (!cg)
|
||||
return;
|
||||
|
||||
/* Clear any cached update, we'll need a new one! */
|
||||
cg->cupdate = tal_free(cg->cupdate);
|
||||
|
||||
/* Any announcement signatures we received for old scid are no longer
|
||||
* valid. */
|
||||
wallet_remote_ann_sigs_clear(ld->wallet, channel);
|
||||
|
||||
switch (cg->state) {
|
||||
case CGOSSIP_PRIVATE:
|
||||
/* Still private, just send new channel_update */
|
||||
send_private_cupdate(channel, false);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
/* Shouldn't happen. */
|
||||
return;
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
log_debug(channel->log, "channel_gossip: scid now %s",
|
||||
short_channel_id_to_str(tmpctx, channel->scid));
|
||||
/* Start again. */
|
||||
/* Maybe remote announcement signatures now apply? If not,
|
||||
* free them */
|
||||
if (cg->remote_sigs
|
||||
&& !short_channel_id_eq(&cg->remote_sigs->scid,
|
||||
channel->scid)) {
|
||||
cg->remote_sigs = tal_free(cg->remote_sigs);
|
||||
}
|
||||
|
||||
/* Stop refresh timer, we're not announcing the old one. */
|
||||
cg->refresh_timer = tal_free(cg->refresh_timer);
|
||||
|
||||
set_gossip_state(channel,
|
||||
init_public_state(channel, cg->remote_sigs));
|
||||
send_channel_announce_sigs(channel);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", cg->state);
|
||||
}
|
||||
|
||||
/* Block height changed */
|
||||
static void new_blockheight(struct lightningd *ld,
|
||||
struct channel *channel,
|
||||
u32 block_height)
|
||||
{
|
||||
switch (channel->channel_gossip->state) {
|
||||
case CGOSSIP_PRIVATE:
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
return;
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
if (!channel_announceable(channel, block_height)) {
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
}
|
||||
set_gossip_state(channel, CGOSSIP_NEED_PEER_SIGS);
|
||||
check_channel_gossip(channel);
|
||||
return;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", channel->channel_gossip->state);
|
||||
}
|
||||
|
||||
void channel_gossip_notify_new_block(struct lightningd *ld,
|
||||
u32 block_height)
|
||||
{
|
||||
struct peer *peer;
|
||||
struct channel *channel;
|
||||
struct peer_node_id_map_iter it;
|
||||
|
||||
for (peer = peer_node_id_map_first(ld->peers, &it);
|
||||
peer;
|
||||
peer = peer_node_id_map_next(ld->peers, &it)) {
|
||||
list_for_each(&peer->channels, channel, list) {
|
||||
/* Ignore unsaved channels */
|
||||
if (!channel->channel_gossip)
|
||||
continue;
|
||||
|
||||
new_blockheight(ld, channel, block_height);
|
||||
check_channel_gossip(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Gossipd told us about a channel update on one of our channels (on loading) */
|
||||
void channel_gossip_update_from_gossipd(struct channel *channel,
|
||||
const u8 *channel_update TAKES)
|
||||
{
|
||||
if (!channel->channel_gossip) {
|
||||
log_broken(channel->log,
|
||||
"gossipd gave channel_update for unsaved channel? update=%s",
|
||||
tal_hex(tmpctx, channel_update));
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we didn't think it was announced already, it is now! */
|
||||
switch (channel->channel_gossip->state) {
|
||||
case CGOSSIP_PRIVATE:
|
||||
log_broken(channel->log,
|
||||
"gossipd gave channel_update for private channel? update=%s",
|
||||
tal_hex(tmpctx, channel_update));
|
||||
return;
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
set_gossip_state(channel, CGOSSIP_ANNOUNCED);
|
||||
break;
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
break;
|
||||
}
|
||||
|
||||
set_public_cupdate(channel, channel_update);
|
||||
check_channel_gossip(channel);
|
||||
}
|
||||
|
||||
static void set_not_starting_up(struct lightningd *ld)
|
||||
{
|
||||
starting_up = false;
|
||||
log_debug(ld->log, "channel_gossip: no longer in startup mode");
|
||||
}
|
||||
|
||||
/* Gossipd init is done: if you expected a channel_update, be
|
||||
* disappointed. */
|
||||
void channel_gossip_init_done(struct lightningd *ld)
|
||||
{
|
||||
struct peer *peer;
|
||||
struct channel *channel;
|
||||
struct peer_node_id_map_iter it;
|
||||
|
||||
for (peer = peer_node_id_map_first(ld->peers, &it);
|
||||
peer;
|
||||
peer = peer_node_id_map_next(ld->peers, &it)) {
|
||||
list_for_each(&peer->channels, channel, list) {
|
||||
/* Ignore unsaved channels */
|
||||
if (!channel->channel_gossip)
|
||||
continue;
|
||||
|
||||
check_channel_gossip(channel);
|
||||
if (channel->channel_gossip->cupdate)
|
||||
continue;
|
||||
if (channel->channel_gossip->state != CGOSSIP_ANNOUNCED)
|
||||
continue;
|
||||
/* gossipd lost announcement: re-create */
|
||||
log_unusual(channel->log,
|
||||
"gossipd lost track of announced channel: re-announcing!");
|
||||
check_channel_gossip(channel);
|
||||
send_channel_announcement(channel);
|
||||
}
|
||||
}
|
||||
|
||||
notleak(new_reltimer(ld->timers, ld,
|
||||
time_from_sec(60),
|
||||
set_not_starting_up, ld));
|
||||
}
|
||||
|
||||
/* Peer has connected. */
|
||||
/* FIXME: We really want "peer has reestablished */
|
||||
void channel_gossip_peer_connected(struct peer *peer)
|
||||
{
|
||||
struct channel *channel;
|
||||
|
||||
list_for_each(&peer->channels, channel, list) {
|
||||
/* Ignore unsaved channels */
|
||||
if (!channel->channel_gossip)
|
||||
continue;
|
||||
|
||||
switch (channel->channel_gossip->state) {
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
continue;
|
||||
case CGOSSIP_PRIVATE:
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
send_private_cupdate(channel, true);
|
||||
check_channel_gossip(channel);
|
||||
continue;
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
/* BOLT #7:
|
||||
* - upon reconnection (once the above timing
|
||||
* requirements have been met):
|
||||
* ...
|
||||
* - if it has NOT received an
|
||||
* `announcement_signatures` message:
|
||||
* - SHOULD retransmit the
|
||||
* `announcement_signatures` message.
|
||||
*/
|
||||
send_private_cupdate(channel, true);
|
||||
send_channel_announce_sigs(channel);
|
||||
check_channel_gossip(channel);
|
||||
continue;
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
check_channel_gossip(channel);
|
||||
continue;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", channel->channel_gossip->state);
|
||||
}
|
||||
}
|
||||
|
||||
/* We *could* send channel_updates for private channels, or
|
||||
* unannounced. We do not */
|
||||
const u8 *channel_gossip_update_for_error(const tal_t *ctx,
|
||||
struct channel *channel)
|
||||
{
|
||||
/* We cannot ask this about unsaved channels. */
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
switch (cg->state) {
|
||||
case CGOSSIP_PRIVATE:
|
||||
case CGOSSIP_NOT_USABLE:
|
||||
case CGOSSIP_NOT_DEEP_ENOUGH:
|
||||
case CGOSSIP_NEED_PEER_SIGS:
|
||||
return NULL;
|
||||
case CGOSSIP_ANNOUNCED:
|
||||
broadcast_public_cupdate(channel, false);
|
||||
check_channel_gossip(channel);
|
||||
return cg->cupdate;
|
||||
}
|
||||
fatal("Bad channel_gossip_state %u", cg->state);
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
* - MUST set the `short_channel_id` to either an `alias` it has
|
||||
* received from the peer, or the real channel `short_channel_id`.
|
||||
*/
|
||||
/* But we used to get this wrong! Sot this is the only place where we
|
||||
* look up by *remote* id. It's not unique, but it is unique for a
|
||||
* specific peer. */
|
||||
static struct channel *lookup_by_peer_remote_alias(struct lightningd *ld,
|
||||
const struct node_id *source,
|
||||
struct short_channel_id scid)
|
||||
{
|
||||
const struct peer *p;
|
||||
struct channel *chan;
|
||||
|
||||
if (!source)
|
||||
return NULL;
|
||||
|
||||
p = peer_by_id(ld, source);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
list_for_each(&p->channels, chan, list) {
|
||||
if (chan->alias[REMOTE]
|
||||
&& short_channel_id_eq(&scid, chan->alias[REMOTE])) {
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* A peer sent gossipd an update_channel message for one of our channels.
|
||||
* Gossipd checked the signature.
|
||||
*/
|
||||
void channel_gossip_set_remote_update(struct lightningd *ld,
|
||||
const struct peer_update *update TAKES,
|
||||
const struct node_id *source)
|
||||
{
|
||||
struct channel *channel;
|
||||
struct channel_gossip *cg;
|
||||
|
||||
channel = any_channel_by_scid(ld, &update->scid, true);
|
||||
if (!channel) {
|
||||
channel = lookup_by_peer_remote_alias(ld, source, update->scid);
|
||||
if (channel)
|
||||
log_debug(channel->log,
|
||||
"Bad gossip order: peer sent update using their own alias!");
|
||||
}
|
||||
if (!channel) {
|
||||
log_unusual(ld->log, "Bad gossip order: could not find channel %s for peer's "
|
||||
"channel update",
|
||||
short_channel_id_to_str(tmpctx, &update->scid));
|
||||
return;
|
||||
}
|
||||
|
||||
cg = channel->channel_gossip;
|
||||
|
||||
if (!cg) {
|
||||
log_broken(ld->log, "Peer sent update_channel for unsaved channel");
|
||||
return;
|
||||
}
|
||||
|
||||
/* For public channels, it could come from anywhere. Private
|
||||
* channels must come from gossipd itself (the old store
|
||||
* migration!) or the correct peer. */
|
||||
if (cg->state == CGOSSIP_PRIVATE
|
||||
&& source
|
||||
&& !node_id_eq(source, &channel->peer->id)) {
|
||||
log_unusual(ld->log, "Bad gossip order: %s sent us a channel update for a "
|
||||
"channel owned by %s (%s)",
|
||||
type_to_string(tmpctx, struct node_id, source),
|
||||
type_to_string(tmpctx, struct node_id,
|
||||
&channel->peer->id),
|
||||
type_to_string(tmpctx, struct short_channel_id, &update->scid));
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug(ld->log, "updating channel %s with inbound settings",
|
||||
type_to_string(tmpctx, struct short_channel_id, &update->scid));
|
||||
tal_free(cg->peer_update);
|
||||
cg->peer_update = tal_dup(cg, struct peer_update, update);
|
||||
wallet_channel_save(ld->wallet, channel);
|
||||
}
|
||||
|
||||
const struct peer_update *channel_gossip_get_remote_update(const struct channel *channel)
|
||||
{
|
||||
struct channel_gossip *cg = channel->channel_gossip;
|
||||
|
||||
if (!cg)
|
||||
return NULL;
|
||||
return cg->peer_update;
|
||||
}
|
||||
55
lightningd/channel_gossip.h
Normal file
55
lightningd/channel_gossip.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef LIGHTNING_LIGHTNINGD_CHANNEL_GOSSIP_H
|
||||
#define LIGHTNING_LIGHTNINGD_CHANNEL_GOSSIP_H
|
||||
#include "config.h"
|
||||
#include <bitcoin/short_channel_id.h>
|
||||
#include <bitcoin/signature.h>
|
||||
|
||||
struct channel;
|
||||
struct lightningd;
|
||||
struct peer;
|
||||
struct peer_update;
|
||||
|
||||
/* Initialize channel->channel_gossip state */
|
||||
void channel_gossip_init(struct channel *channel,
|
||||
const struct peer_update *remote_update TAKES);
|
||||
|
||||
/* Something about channel/blockchain changed: update if required */
|
||||
void channel_gossip_update(struct channel *channel);
|
||||
|
||||
/* Short channel id changed (splice, or reorg). */
|
||||
void channel_gossip_scid_changed(struct channel *channel);
|
||||
|
||||
/* Block height changed */
|
||||
void channel_gossip_notify_new_block(struct lightningd *ld,
|
||||
u32 block_height);
|
||||
|
||||
/* Got announcement_signatures from peer */
|
||||
void channel_gossip_got_announcement_sigs(struct channel *channel,
|
||||
struct short_channel_id scid,
|
||||
const secp256k1_ecdsa_signature *node_sig,
|
||||
const secp256k1_ecdsa_signature *bitcoin_sig);
|
||||
|
||||
/* Gossipd told us about a channel update on one of our channels (on loading) */
|
||||
void channel_gossip_update_from_gossipd(struct channel *channel,
|
||||
const u8 *channel_update TAKES);
|
||||
|
||||
/* Gossipd init is done: if you expected a channel_update, be
|
||||
* disappointed. */
|
||||
void channel_gossip_init_done(struct lightningd *ld);
|
||||
|
||||
/* Peer has connected. */
|
||||
void channel_gossip_peer_connected(struct peer *peer);
|
||||
|
||||
/* Gossipd sent us this channel_update about the peer's side of the channle */
|
||||
void channel_gossip_set_remote_update(struct lightningd *ld,
|
||||
const struct peer_update *update TAKES,
|
||||
const struct node_id *source);
|
||||
|
||||
/* Get channel_update to send in an error onion reply (can give NULL!) */
|
||||
const u8 *channel_gossip_update_for_error(const tal_t *ctx,
|
||||
struct channel *channel);
|
||||
|
||||
/* Get the peer's last-sent channel_update info, if any. */
|
||||
const struct peer_update *channel_gossip_get_remote_update(const struct channel *channel);
|
||||
|
||||
#endif /* LIGHTNING_LIGHTNINGD_CHANNEL_GOSSIP_H */
|
||||
Reference in New Issue
Block a user