/* Routines to make our own gossip messages. Not as in "we're the gossip * generation, man!" */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* 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->nodefeatures, 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); /* If we ever use set-based propagation, ensuring the toggle the lower * bit in consecutive timestamps makes it more robust. */ if (self && self->bcast.index && (timestamp & 1) == (self->bcast.timestamp & 1)) timestamp++; /* 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 + GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); 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), NULL, NULL); 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 -= GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); /* 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; /* Convenience variable. */ hc = &chan->half[direction]; /* If we ever use set-based propagation, ensuring the toggle * the lower bit in consecutive timestamps makes it more * robust. */ if (is_halfchan_defined(hc) && (timestamp & 1) == (hc->bcast.timestamp & 1)) timestamp++; /* 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); 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 + GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); 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(tmpctx, 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, update, find_peer(daemon, &chan->nodes[!direction]->id), 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; }