diff --git a/channeld/channel.c b/channeld/channel.c index 813890ec4..b5632d9bf 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -299,51 +299,8 @@ static void enqueue_peer_msg(struct peer *peer, const u8 *msg TAKES) msg_enqueue(&peer->peer_out, msg); } -static u8 *create_channel_update(const tal_t *ctx, - struct peer *peer, - int disable_flag) -{ - u32 timestamp = time_now().ts.tv_sec; - u16 flags; - u8 *cupdate, *msg; - - /* We must have a channel id to send */ - assert(peer->short_channel_ids[LOCAL].u64); - - /* Identical timestamps will be ignored. */ - if (timestamp <= peer->last_update_timestamp) - timestamp = peer->last_update_timestamp + 1; - peer->last_update_timestamp = timestamp; - - /* Set the signature to empty so that valgrind doesn't complain */ - secp256k1_ecdsa_signature *sig = - talz(tmpctx, secp256k1_ecdsa_signature); - - flags = peer->channel_direction | disable_flag; - cupdate = towire_channel_update( - tmpctx, sig, &peer->chain_hash, - &peer->short_channel_ids[LOCAL], timestamp, flags, - peer->cltv_delta, peer->conf[REMOTE].htlc_minimum_msat, - peer->fee_base, peer->fee_per_satoshi); - - msg = towire_hsm_cupdate_sig_req(tmpctx, cupdate); - - if (!wire_sync_write(HSM_FD, msg)) - 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(ctx, msg, &cupdate)) - status_failed(STATUS_FAIL_HSM_IO, - "Reading cupdate_sig_req: %s", - strerror(errno)); - return cupdate; -} - /* Create and send channel_update to gossipd (and maybe peer) */ -static void send_channel_update(struct peer *peer, bool peer_too, - int disable_flag) +static void send_channel_update(struct peer *peer, int disable_flag) { u8 *msg; @@ -353,9 +310,16 @@ static void send_channel_update(struct peer *peer, bool peer_too, if (!peer->channel_local_active) return; - msg = create_channel_update(tmpctx, peer, disable_flag); - if (peer_too) - enqueue_peer_msg(peer, msg); + assert(peer->short_channel_ids[LOCAL].u64); + + msg = towire_gossip_local_channel_update(NULL, + &peer->short_channel_ids[LOCAL], + disable_flag + == ROUTING_FLAGS_DISABLED, + peer->cltv_delta, + peer->conf[REMOTE].htlc_minimum_msat, + peer->fee_base, + peer->fee_per_satoshi); wire_sync_write(GOSSIP_FD, take(msg)); } @@ -381,7 +345,7 @@ static void make_channel_local_active(struct peer *peer) /* Tell gossipd and the other side what parameters we expect should * they route through us */ - send_channel_update(peer, true, 0); + send_channel_update(peer, 0); } static void send_announcement_signatures(struct peer *peer) @@ -482,15 +446,14 @@ static void check_short_ids_match(struct peer *peer) static void announce_channel(struct peer *peer) { - u8 *cannounce, *cupdate; + u8 *cannounce; check_short_ids_match(peer); cannounce = create_channel_announcement(tmpctx, peer); - cupdate = create_channel_update(tmpctx, peer, 0); wire_sync_write(GOSSIP_FD, cannounce); - wire_sync_write(GOSSIP_FD, cupdate); + send_channel_update(peer, 0); } static void channel_announcement_negotiate(struct peer *peer) @@ -765,7 +728,7 @@ static void maybe_send_shutdown(struct peer *peer) /* Send a disable channel_update so others don't try to route * over us */ - send_channel_update(peer, true, ROUTING_FLAGS_DISABLED); + send_channel_update(peer, ROUTING_FLAGS_DISABLED); msg = towire_shutdown(NULL, &peer->channel_id, peer->final_scriptpubkey); enqueue_peer_msg(peer, take(msg)); @@ -1534,7 +1497,7 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) u8 *scriptpubkey; /* Disable the channel. */ - send_channel_update(peer, false, ROUTING_FLAGS_DISABLED); + send_channel_update(peer, ROUTING_FLAGS_DISABLED); if (!fromwire_shutdown(peer, shutdown, &channel_id, &scriptpubkey)) peer_failed(&peer->cs, @@ -1642,7 +1605,7 @@ static void peer_in(struct peer *peer, const u8 *msg) static void peer_conn_broken(struct peer *peer) { /* If we have signatures, send an update to say we're disabled. */ - send_channel_update(peer, false, ROUTING_FLAGS_DISABLED); + send_channel_update(peer, ROUTING_FLAGS_DISABLED); peer_failed_connection_lost(); } diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 433042903..514406e7b 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -927,6 +927,123 @@ static void handle_get_update(struct peer *peer, const u8 *msg) daemon_conn_send(peer->remote, take(msg)); } +static u8 *create_channel_update(const tal_t *ctx, + struct routing_state *rstate, + const struct chan *chan, + int direction, + bool disable, + u16 cltv_expiry_delta, + u64 htlc_minimum_msat, + u32 fee_base_msat, + u32 fee_proportional_millionths) +{ + secp256k1_ecdsa_signature dummy_sig; + u8 *update, *msg; + u32 timestamp = time_now().ts.tv_sec; + u16 flags; + + /* So valgrind doesn't complain */ + memset(&dummy_sig, 0, sizeof(dummy_sig)); + + /* Don't send duplicate timestamps. */ + if (is_halfchan_defined(&chan->half[direction]) + && timestamp == chan->half[direction].last_timestamp) + timestamp++; + + flags = direction; + if (disable) + flags |= ROUTING_FLAGS_DISABLED; + + update = towire_channel_update(tmpctx, &dummy_sig, + &rstate->chain_hash, + &chan->scid, + timestamp, + flags, cltv_expiry_delta, + htlc_minimum_msat, + fee_base_msat, + fee_proportional_millionths); + + 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(ctx, msg, &update)) { + status_failed(STATUS_FAIL_HSM_IO, + "Reading cupdate_sig_req: %s", + strerror(errno)); + } + + return update; +} + +static void handle_local_channel_update(struct peer *peer, const u8 *msg) +{ + struct short_channel_id scid; + u16 cltv_delta; + u64 htlc_minimum_msat; + u32 fee_base_msat, fee_proportional_millionths; + bool disable; + struct chan *chan; + int direction; + u8 *cupdate, *err; + const struct pubkey *my_id = &peer->daemon->rstate->local_id; + + if (!fromwire_gossip_local_channel_update(msg, &scid, &disable, + &cltv_delta, + &htlc_minimum_msat, + &fee_base_msat, + &fee_proportional_millionths)) { + status_broken("peer %s bad local_channel_update %s", + type_to_string(tmpctx, struct pubkey, &peer->id), + tal_hex(tmpctx, msg)); + return; + } + + /* Can theoretically happen if channel just closed. */ + chan = get_channel(peer->daemon->rstate, &scid); + if (!chan) { + status_trace("peer %s local_channel_update for unknown %s", + type_to_string(tmpctx, struct pubkey, &peer->id), + type_to_string(tmpctx, struct short_channel_id, + &scid)); + return; + } + + if (pubkey_eq(&chan->nodes[0]->id, my_id)) + direction = 0; + else if (pubkey_eq(&chan->nodes[1]->id, my_id)) + direction = 1; + else { + status_broken("peer %s bad local_channel_update for non-local %s", + type_to_string(tmpctx, struct pubkey, &peer->id), + type_to_string(tmpctx, struct short_channel_id, + &scid)); + return; + } + + cupdate = create_channel_update(tmpctx, peer->daemon->rstate, + chan, direction, + disable, cltv_delta, + htlc_minimum_msat, + fee_base_msat, + fee_proportional_millionths); + + err = handle_channel_update(peer->daemon->rstate, cupdate, + "local_channel_update"); + if (err) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Rejected local channel update %s: %s", + tal_hex(tmpctx, cupdate), + tal_hex(tmpctx, err)); + + /* We always tell peer, even if it's not public yet */ + if (!is_chan_public(chan)) + queue_peer_msg(peer, take(cupdate)); +} + /** * owner_msg_in - Called by the `peer->remote` upon receiving a * message @@ -950,6 +1067,8 @@ static struct io_plan *owner_msg_in(struct io_conn *conn, gossip_store_local_add_channel(peer->daemon->rstate->store, dc->msg_in); handle_local_add_channel(peer->daemon->rstate, dc->msg_in); + } else if (type == WIRE_GOSSIP_LOCAL_CHANNEL_UPDATE) { + handle_local_channel_update(peer, dc->msg_in); } else { status_broken("peer %s: send us unknown msg of type %s", type_to_string(tmpctx, struct pubkey, &peer->id), @@ -2579,6 +2698,7 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_GET_UPDATE_REPLY: case WIRE_GOSSIP_SEND_GOSSIP: case WIRE_GOSSIP_LOCAL_ADD_CHANNEL: + case WIRE_GOSSIP_LOCAL_CHANNEL_UPDATE: case WIRE_GOSSIP_GET_TXOUT: case WIRE_GOSSIPCTL_PEER_DISCONNECT_REPLY: case WIRE_GOSSIPCTL_PEER_DISCONNECT_REPLYFAIL: diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index 44d63a095..3a726a79d 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -198,6 +198,14 @@ gossip_local_add_channel,3017 gossip_local_add_channel,,short_channel_id,struct short_channel_id gossip_local_add_channel,,remote_node_id,struct pubkey +gossip_local_channel_update,3026 +gossip_local_channel_update,,short_channel_id,struct short_channel_id +gossip_local_channel_update,,disable,bool +gossip_local_channel_update,,cltv_expiry_delta,u16 +gossip_local_channel_update,,htlc_minimum_msat,u64 +gossip_local_channel_update,,fee_base_msat,u32 +gossip_local_channel_update,,fee_proportional_millionths,u32 + # Gossipd->master get this tx output please. gossip_get_txout,3018 gossip_get_txout,,short_channel_id,struct short_channel_id diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 881d974c8..c7153a1f9 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -154,6 +154,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPCTL_PEER_DISCONNECT_REPLYFAIL: /* These are inter-daemon messages, not received by us */ case WIRE_GOSSIP_LOCAL_ADD_CHANNEL: + case WIRE_GOSSIP_LOCAL_CHANNEL_UPDATE: break; case WIRE_GOSSIP_PEER_CONNECTED: