Skip to content

Let gossipd automatically announce the node when a local channel_announcement is queued #413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Dec 17, 2017
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
98b1a66
gossip: Remove HSM_FD from handshake
cdecker Nov 24, 2017
37e9d14
routing: Make routing_state aware of its own ID
cdecker Dec 2, 2017
4c13032
opts: Change alias to be u8*, better matches the unicode nature
cdecker Nov 24, 2017
7427c8a
gossip: Passing alias, color and wireaddrs through to gossipd
cdecker Nov 24, 2017
abe9192
routing: Return boolean from handle_channel_announcement
cdecker Nov 24, 2017
dfc5a6e
routing: Add local and sigfail to trace when receiving cannounce
cdecker Dec 2, 2017
aa67236
gossip: Forward when we don't have a valid node_announcement yet
cdecker Dec 4, 2017
88218a0
routing: Do not set an empty channel_announcement if none is given
cdecker Dec 4, 2017
c1b4f41
json_fund_channel: give more details than "peer died".
rustyrussell Dec 5, 2017
e99f69e
subd: add transaction to subd exit corner case.
rustyrussell Dec 5, 2017
6793efe
wireaddr: marshal empty address properly.
rustyrussell Dec 5, 2017
139774c
openingd: return to master for more gossip when negotiation fails.
rustyrussell Dec 6, 2017
c984fb2
openingd: handle ERROR packets (if other end fails negotiation).
rustyrussell Dec 6, 2017
6889fe7
test_lightningd: add test for funding failures.
rustyrussell Dec 6, 2017
616bc26
daemon_conn: helper to release daemon_conn.
rustyrussell Dec 6, 2017
06a0188
gossipd: split peer structure to clearly separate local and remote fi…
rustyrussell Dec 6, 2017
62634e9
Makefile: make gossipd objects depend correctly on its own headers.
rustyrussell Dec 11, 2017
c552fa8
subd: if a required daemon exits, wait instead of killing it.
rustyrussell Dec 11, 2017
b9eddbe
gossipd: don't hand length to route code, it's implied.
rustyrussell Dec 11, 2017
09151fd
gossipd: hand back peer, don't hand a new peer.
rustyrussell Dec 11, 2017
a4512ea
gossipd: don't increment broadcast_index until *after* message sent.
rustyrussell Dec 11, 2017
2a2902b
gossipd: hand out gossip_index to other daemons.
rustyrussell Dec 11, 2017
a22d341
pytest: Fix a flaky channel_reenable test
cdecker Dec 12, 2017
c787e51
channel: Directly send announcements and updates to gossipd
cdecker Dec 12, 2017
234b412
pytest: Minor cleanup
cdecker Dec 13, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 72 additions & 7 deletions gossipd/gossip.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <gossipd/handshake.h>
#include <gossipd/routing.h>
#include <hsmd/client.h>
#include <hsmd/gen_hsm_client_wire.h>
#include <inttypes.h>
#include <lightningd/gossip_msg.h>
#include <netdb.h>
Expand All @@ -43,6 +44,7 @@
#include <unistd.h>
#include <wire/gen_peer_wire.h>
#include <wire/wire_io.h>
#include <wire/wire_sync.h>

#define HSM_FD 3

Expand Down Expand Up @@ -71,6 +73,10 @@ struct daemon {

/* Local and global features to offer to peers. */
u8 *localfeatures, *globalfeatures;

u8 alias[33];
u8 rgb[3];
struct wireaddr *wireaddrs;
};

/* Peers we're trying to reach. */
Expand Down Expand Up @@ -367,12 +373,69 @@ static struct io_plan *owner_msg_in(struct io_conn *conn,
static struct io_plan *nonlocal_dump_gossip(struct io_conn *conn,
struct daemon_conn *dc);

static void handle_gossip_msg(struct routing_state *rstate, u8 *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 typically 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 since that is
* the only thing that may change between the dummy creation and the
* call with a signature.*/
static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon,
secp256k1_ecdsa_signature *sig,
u32 timestamp)
{
u8 *features = NULL;
u8 *addresses = tal_arr(ctx, u8, 0);
u8 *announcement;
size_t i;
if (!sig) {
sig = tal(ctx, secp256k1_ecdsa_signature);
memset(sig, 0, sizeof(*sig));
}
for (i = 0; i < tal_count(daemon->wireaddrs); i++)
towire_wireaddr(&addresses, daemon->wireaddrs+i);

announcement =
towire_node_announcement(ctx, sig, features, timestamp,
&daemon->id, daemon->rgb, daemon->alias,
addresses);
return announcement;
}

static void send_node_announcement(struct daemon *daemon)
{
tal_t *tmpctx = tal_tmpctx(daemon);
u32 timestamp = time_now().ts.tv_sec;
secp256k1_ecdsa_signature sig;
u8 *msg, *nannounce = create_node_announcement(tmpctx, daemon, NULL, timestamp);

if (!wire_sync_write(HSM_FD, take(towire_hsm_node_announcement_sig_req(tmpctx, 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, NULL, &sig))
status_failed(STATUS_FAIL_MASTER_IO, "HSM returned an invalid node_announcement sig");

/* We got the signature for out 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(tmpctx, daemon, &sig, timestamp);
handle_node_announcement(daemon->rstate, take(nannounce), tal_len(nannounce));
tal_free(tmpctx);
}

static void handle_gossip_msg(struct daemon *daemon, u8 *msg)
{
struct routing_state *rstate = daemon->rstate;
int t = fromwire_peektype(msg);
switch(t) {
case WIRE_CHANNEL_ANNOUNCEMENT:
handle_channel_announcement(rstate, msg, tal_count(msg));
/* Add the channel_announcement to the routing state,
* it'll tell us whether this is local and signed, so
* we can hand in a node_announcement as well. */
if(handle_channel_announcement(rstate, msg, tal_count(msg))) {
send_node_announcement(daemon);
}
break;

case WIRE_NODE_ANNOUNCEMENT:
Expand Down Expand Up @@ -485,7 +548,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
case WIRE_CHANNEL_ANNOUNCEMENT:
case WIRE_NODE_ANNOUNCEMENT:
case WIRE_CHANNEL_UPDATE:
handle_gossip_msg(peer->daemon->rstate, msg);
handle_gossip_msg(peer->daemon, msg);
return peer_next_in(conn, peer);

case WIRE_PING:
Expand Down Expand Up @@ -657,7 +720,7 @@ static struct io_plan *owner_msg_in(struct io_conn *conn,
int type = fromwire_peektype(msg);
if (type == WIRE_CHANNEL_ANNOUNCEMENT || type == WIRE_CHANNEL_UPDATE ||
type == WIRE_NODE_ANNOUNCEMENT) {
handle_gossip_msg(peer->daemon->rstate, dc->msg_in);
handle_gossip_msg(peer->daemon, dc->msg_in);
} else if (type == WIRE_GOSSIP_GET_UPDATE) {
handle_get_update(peer, dc->msg_in);
}
Expand Down Expand Up @@ -1111,10 +1174,12 @@ static struct io_plan *gossip_init(struct daemon_conn *master,
&daemon->broadcast_interval,
&chain_hash, &daemon->id, &port,
&daemon->globalfeatures,
&daemon->localfeatures)) {
&daemon->localfeatures,
&daemon->wireaddrs,
daemon->rgb, daemon->alias)) {
master_badmsg(WIRE_GOSSIPCTL_INIT, msg);
}
daemon->rstate = new_routing_state(daemon, &chain_hash);
daemon->rstate = new_routing_state(daemon, &chain_hash, &daemon->id);

setup_listeners(daemon, port);
return daemon_conn_read_next(master->conn, master);
Expand Down Expand Up @@ -1155,7 +1220,7 @@ static void handle_forwarded_msg(struct io_conn *conn, struct daemon *daemon, co
if (!fromwire_gossip_forwarded_msg(msg, msg, NULL, &payload))
master_badmsg(WIRE_GOSSIP_FORWARDED_MSG, msg);

handle_gossip_msg(daemon->rstate, payload);
handle_gossip_msg(daemon, payload);
}

static struct io_plan *handshake_out_success(struct io_conn *conn,
Expand Down
4 changes: 4 additions & 0 deletions gossipd/gossip_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ gossipctl_init,,gflen,u16
gossipctl_init,,gfeatures,gflen*u8
gossipctl_init,,lflen,u16
gossipctl_init,,lfeatures,lflen*u8
gossipctl_init,,num_wireaddrs,u16
gossipctl_init,,wireaddrs,num_wireaddrs*struct wireaddr
gossipctl_init,,rgb,3*u8
gossipctl_init,,alias,32*u8

# Master -> gossipd: Optional hint for where to find peer.
gossipctl_peer_addrhint,3014
Expand Down
2 changes: 0 additions & 2 deletions gossipd/handshake.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
#include <unistd.h>
#include <wire/wire.h>

#define HSM_FD 3

#ifndef SUPERVERBOSE
#define SUPERVERBOSE(...)
#endif
Expand Down
66 changes: 43 additions & 23 deletions gossipd/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ static struct node_map *empty_node_map(const tal_t *ctx)
}

struct routing_state *new_routing_state(const tal_t *ctx,
const struct sha256_double *chain_hash)
const struct sha256_double *chain_hash,
const struct pubkey *local_id)
{
struct routing_state *rstate = tal(ctx, struct routing_state);
rstate->nodes = empty_node_map(rstate);
rstate->broadcasts = new_broadcast_state(rstate);
rstate->chain_hash = *chain_hash;
rstate->local_id = *local_id;
return rstate;
}

Expand Down Expand Up @@ -422,9 +424,11 @@ static bool add_channel_direction(struct routing_state *rstate,
c = half_add_connection(rstate, from, to, short_channel_id, direction);

/* Remember the announcement so we can forward it to new peers */
tal_free(c->channel_announcement);
c->channel_announcement = tal_dup_arr(c, u8, announcement,
tal_count(announcement), 0);
if (announcement) {
tal_free(c->channel_announcement);
c->channel_announcement = tal_dup_arr(c, u8, announcement,
tal_count(announcement), 0);
}
return true;
}

Expand Down Expand Up @@ -461,12 +465,12 @@ static bool check_channel_announcement(
check_signed_hash(&hash, bitcoin2_sig, bitcoin2_key);
}

void handle_channel_announcement(
bool handle_channel_announcement(
struct routing_state *rstate,
const u8 *announce, size_t len)
{
u8 *serialized;
bool forward = false;
bool forward = false, local, sigfail;
secp256k1_ecdsa_signature node_signature_1;
secp256k1_ecdsa_signature node_signature_2;
struct short_channel_id short_channel_id;
Expand All @@ -477,6 +481,7 @@ void handle_channel_announcement(
struct pubkey bitcoin_key_1;
struct pubkey bitcoin_key_2;
struct sha256_double chain_hash;
struct node_connection *c0, *c1;
const tal_t *tmpctx = tal_tmpctx(rstate);
u8 *features;

Expand All @@ -491,7 +496,7 @@ void handle_channel_announcement(
&node_id_1, &node_id_2,
&bitcoin_key_1, &bitcoin_key_2)) {
tal_free(tmpctx);
return;
return false;
}

/* BOLT #7:
Expand All @@ -505,34 +510,48 @@ void handle_channel_announcement(
type_to_string(tmpctx, struct sha256_double,
&chain_hash));
tal_free(tmpctx);
return;
return false;
}

// FIXME: Check features!
//FIXME(cdecker) Check chain topology for the anchor TX

status_trace("Received channel_announcement for channel %s",

local = pubkey_eq(&node_id_1, &rstate->local_id) ||
pubkey_eq(&node_id_2, &rstate->local_id);
sigfail = !check_channel_announcement(
&node_id_1, &node_id_2, &bitcoin_key_1, &bitcoin_key_2,
&node_signature_1, &node_signature_2, &bitcoin_signature_1,
&bitcoin_signature_2, serialized);

status_trace("Received channel_announcement for channel %s, local=%d, sigfail=%d",
type_to_string(trc, struct short_channel_id,
&short_channel_id));
&short_channel_id), local, sigfail);

if (!check_channel_announcement(&node_id_1, &node_id_2, &bitcoin_key_1,
&bitcoin_key_2, &node_signature_1,
&node_signature_2, &bitcoin_signature_1,
&bitcoin_signature_2, serialized)) {

if (sigfail && !local) {
status_trace(
"Signature verification of channel announcement failed");
"Signature verification of non-local channel announcement failed");
tal_free(tmpctx);
return;
return false;
}

forward |= add_channel_direction(rstate, &node_id_1, &node_id_2,
&short_channel_id, serialized);
forward |= add_channel_direction(rstate, &node_id_2, &node_id_1,
&short_channel_id, serialized);
if (!forward) {
status_trace("Not forwarding channel_announcement");
/* Is this a new connection? */
c0 = get_connection_by_scid(rstate, &short_channel_id, 0);
c1 = get_connection_by_scid(rstate, &short_channel_id, 1);
forward = !c0 || !c1 || !c0->channel_announcement || !c1->channel_announcement;

add_channel_direction(rstate, &node_id_1, &node_id_2, &short_channel_id,
sigfail ? NULL : serialized);
add_channel_direction(rstate, &node_id_2, &node_id_1, &short_channel_id,
sigfail ? NULL : serialized);

if (!forward || sigfail) {
status_trace("Not forwarding channel_announcement, forward=%d, sigfail=%d", forward, sigfail);
tal_free(tmpctx);
return;
/* This will not be forwarded so we do not want to
* announce the node either, others might drop it. */
return false;
}

u8 *tag = tal_arr(tmpctx, u8, 0);
Expand All @@ -541,6 +560,7 @@ void handle_channel_announcement(
tag, serialized);

tal_free(tmpctx);
return local;
}

void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len)
Expand Down
16 changes: 14 additions & 2 deletions gossipd/routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ struct routing_state {
struct broadcast_state *broadcasts;

struct sha256_double chain_hash;

/* Our own ID so we can identify local channels */
struct pubkey local_id;
};

struct route_hop {
Expand All @@ -93,7 +96,8 @@ struct route_hop {
};

struct routing_state *new_routing_state(const tal_t *ctx,
const struct sha256_double *chain_hash);
const struct sha256_double *chain_hash,
const struct pubkey *local_id);

/* msatoshi must be possible (< 21 million BTC), ie < 2^60.
* If it returns more than msatoshi, it overflowed. */
Expand All @@ -116,7 +120,15 @@ struct node_connection *get_connection_by_scid(const struct routing_state *rstat
const u8 direction);

/* Handlers for incoming messages */
void handle_channel_announcement(struct routing_state *rstate, const u8 *announce, size_t len);

/**
* handle_channel_announcement -- Add channel announcement to state
*
* Returns true if the channel was fully signed and is local. This
* means that if we haven't sent a node_announcement just yet, now
* would be a good time.
*/
bool handle_channel_announcement(struct routing_state *rstate, const u8 *announce, size_t len);
void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len);
void handle_node_announcement(struct routing_state *rstate, const u8 *node, size_t len);

Expand Down
3 changes: 1 addition & 2 deletions gossipd/test/run-find_route-specific.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ int main(void)
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN);

rstate = new_routing_state(ctx, &zerohash);

pubkey_from_hexstr("03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf",
strlen("03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf"),
&a);
Expand All @@ -79,6 +77,7 @@ int main(void)
strlen("02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06"),
&c);

rstate = new_routing_state(ctx, &zerohash, &a);

/* [{'active': True, 'short_id': '6990:2:1/1', 'fee_per_kw': 10, 'delay': 5, 'flags': 1, 'destination': '0230ad0e74ea03976b28fda587bb75bdd357a1938af4424156a18265167f5e40ae', 'source': '02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06', 'last_update': 1504064344}, */
nc = get_or_make_connection(rstate, &c, &b);
Expand Down
4 changes: 2 additions & 2 deletions gossipd/test/run-find_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ int main(void)
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN);

rstate = new_routing_state(ctx, &zerohash);

memset(&tmp, 'a', sizeof(tmp));
rstate = new_routing_state(ctx, &zerohash, &a);

pubkey_from_privkey(&tmp, &a);
new_node(rstate, &a);

Expand Down
3 changes: 2 additions & 1 deletion lightningd/gossip_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ void gossip_init(struct lightningd *ld)
&get_chainparams(ld)->genesis_blockhash,
&ld->id, ld->portnum,
get_supported_global_features(tmpctx),
get_supported_local_features(tmpctx));
get_supported_local_features(tmpctx),
ld->wireaddrs, ld->rgb, ld->alias);
subd_send_msg(ld->gossip, msg);
tal_free(tmpctx);
}
Expand Down
2 changes: 1 addition & 1 deletion lightningd/lightningd.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ struct lightningd {
struct pubkey id;

/* My name is... my favorite color is... */
char *alias; /* At least 32 bytes (zero-filled) */
u8 *alias; /* At least 32 bytes (zero-filled) */
u8 *rgb; /* tal_len() == 3. */

/* Any pending timers. */
Expand Down
Loading