Browse Source

channeld: tell gossipd to generate channel_updates.

This resolves the problem where both channeld and gossipd can generate
updates, and they can have the same timestamp.  gossipd is always able
to generate them, so can ensure timestamp moves forward.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
fca5a9ef30
  1. 71
      channeld/channel.c
  2. 120
      gossipd/gossip.c
  3. 8
      gossipd/gossip_wire.csv
  4. 1
      lightningd/gossip_control.c

71
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();
}

120
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:

8
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

Can't render this file because it has a wrong number of fields in line 6.

1
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:

Loading…
Cancel
Save