diff --git a/daemon/lightningd.c b/daemon/lightningd.c index b187c8591..bb8ba126b 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -32,6 +32,7 @@ static struct lightningd_state *lightningd_state(void) { struct lightningd_state *dstate = tal(NULL, struct lightningd_state); + struct sha256_double unused; dstate->log_book = new_log_book(dstate, 20*1024*1024, LOG_INFORM); dstate->base_log = new_log(dstate, dstate->log_book, @@ -45,7 +46,7 @@ static struct lightningd_state *lightningd_state(void) list_head_init(&dstate->wallet); list_head_init(&dstate->addresses); dstate->dev_never_routefail = false; - dstate->rstate = new_routing_state(dstate, dstate->base_log); + dstate->rstate = new_routing_state(dstate, dstate->base_log, &unused); dstate->reexec = NULL; dstate->external_ip = NULL; dstate->announce = NULL; @@ -89,6 +90,10 @@ int main(int argc, char *argv[]) register_opts(dstate); handle_opts(dstate, argc, argv); + /* Now we can set chain_hash properly. */ + dstate->rstate->chain_hash + = dstate->bitcoind->chainparams->genesis_blockhash; + /* Activate crash log now we're in the right place. */ crashlog_activate(dstate->base_log); diff --git a/daemon/p2p_announce.c b/daemon/p2p_announce.c index 33467652b..874a036e6 100644 --- a/daemon/p2p_announce.c +++ b/daemon/p2p_announce.c @@ -31,7 +31,9 @@ static void broadcast_channel_update(struct lightningd_state *dstate, struct pee /* Avoid triggering memcheck */ memset(&signature, 0, sizeof(signature)); - serialized = towire_channel_update(tmpctx, &signature, &short_channel_id, + serialized = towire_channel_update(tmpctx, &signature, + &dstate->rstate->chain_hash, + &short_channel_id, timestamp, pubkey_cmp(&dstate->id, peer->id) > 0, dstate->config.min_htlc_expiry, @@ -41,7 +43,9 @@ static void broadcast_channel_update(struct lightningd_state *dstate, struct pee dstate->config.fee_per_satoshi); privkey_sign(dstate, serialized + 66, tal_count(serialized) - 66, &signature); - serialized = towire_channel_update(tmpctx, &signature, &short_channel_id, + serialized = towire_channel_update(tmpctx, &signature, + &dstate->rstate->chain_hash, + &short_channel_id, timestamp, pubkey_cmp(&dstate->id, peer->id) > 0, dstate->config.min_htlc_expiry, @@ -148,6 +152,7 @@ static void broadcast_channel_announcement(struct lightningd_state *dstate, stru &bitcoin_signature[0], &bitcoin_signature[1], NULL, + &dstate->rstate->chain_hash, &short_channel_id, node_id[0], node_id[1], @@ -160,6 +165,7 @@ static void broadcast_channel_announcement(struct lightningd_state *dstate, stru &bitcoin_signature[0], &bitcoin_signature[1], NULL, + &dstate->rstate->chain_hash, &short_channel_id, node_id[0], node_id[1], diff --git a/daemon/routing.c b/daemon/routing.c index 76f68d28d..70b41901a 100644 --- a/daemon/routing.c +++ b/daemon/routing.c @@ -6,6 +6,7 @@ #include "routing.h" #include "wire/gen_peer_wire.h" #include +#include #include #include #include @@ -16,12 +17,15 @@ /* 365.25 * 24 * 60 / 10 */ #define BLOCKS_PER_YEAR 52596 -struct routing_state *new_routing_state(const tal_t *ctx, struct log *base_log) +struct routing_state *new_routing_state(const tal_t *ctx, + struct log *base_log, + const struct sha256_double *chain_hash) { struct routing_state *rstate = tal(ctx, struct routing_state); rstate->base_log = base_log; rstate->nodes = empty_node_map(rstate); rstate->broadcasts = new_broadcast_state(rstate); + rstate->chain_hash = *chain_hash; return rstate; } @@ -683,6 +687,7 @@ void handle_channel_announcement( struct pubkey node_id_2; struct pubkey bitcoin_key_1; struct pubkey bitcoin_key_2; + struct sha256_double chain_hash; const tal_t *tmpctx = tal_tmpctx(rstate); u8 *features; @@ -692,6 +697,7 @@ void handle_channel_announcement( &bitcoin_signature_1, &bitcoin_signature_2, &features, + &chain_hash, &short_channel_id, &node_id_1, &node_id_2, &bitcoin_key_1, &bitcoin_key_2)) { @@ -699,6 +705,20 @@ void handle_channel_announcement( return; } + /* BOLT #7: + * + * The receiving node MUST ignore the message if the specified + * `chain_hash` is unknown to the receiver. + */ + if (!structeq(&chain_hash, &rstate->chain_hash)) { + log_debug(rstate->base_log, + "Received channel_announcement for unknown chain %s", + type_to_string(tmpctx, struct sha256_double, + &chain_hash)); + tal_free(tmpctx); + return; + } + // FIXME: Check features! //FIXME(cdecker) Check chain topology for the anchor TX @@ -751,9 +771,11 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update, size_ u32 fee_base_msat; u32 fee_proportional_millionths; const tal_t *tmpctx = tal_tmpctx(rstate); + struct sha256_double chain_hash; serialized = tal_dup_arr(tmpctx, u8, update, len, 0); - if (!fromwire_channel_update(serialized, NULL, &signature, &short_channel_id, + if (!fromwire_channel_update(serialized, NULL, &signature, + &chain_hash, &short_channel_id, ×tamp, &flags, &expiry, &htlc_minimum_msat, &fee_base_msat, &fee_proportional_millionths)) { @@ -761,6 +783,19 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update, size_ return; } + /* BOLT #7: + * + * The receiving node MUST ignore the channel update if the specified + * `chain_hash` value is unknown, meaning it isn't active on the + * specified chain. */ + if (!structeq(&chain_hash, &rstate->chain_hash)) { + log_debug(rstate->base_log, + "Received channel_update for unknown chain %s", + type_to_string(tmpctx, struct sha256_double, + &chain_hash)); + tal_free(tmpctx); + return; + } log_debug(rstate->base_log, "Received channel_update for channel %d:%d:%d(%d)", short_channel_id.blocknum, diff --git a/daemon/routing.h b/daemon/routing.h index bfc57b491..1e124f199 100644 --- a/daemon/routing.h +++ b/daemon/routing.h @@ -86,6 +86,8 @@ struct routing_state { struct log *base_log; struct broadcast_state *broadcasts; + + struct sha256_double chain_hash; }; struct route_hop { @@ -96,7 +98,8 @@ struct route_hop { }; //FIXME(cdecker) The log will have to be replaced for the new subdaemon, keeping for now to keep changes small. -struct routing_state *new_routing_state(const tal_t *ctx, struct log *base_log); +struct routing_state *new_routing_state(const tal_t *ctx, struct log *base_log, + const struct sha256_double *chain_hash); struct node *new_node(struct routing_state *rstate, const struct pubkey *id); diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index 901f65342..4ee71a18b 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -226,7 +226,8 @@ static void send_channel_update(struct peer *peer, bool disabled) flags = peer->channel_direction | (disabled << 1); /* FIXME: Add configuration option to specify `htlc_minimum_msat` */ cupdate = towire_channel_update( - tmpctx, sig, &peer->short_channel_ids[LOCAL], timestamp, flags, + tmpctx, sig, &peer->chain_hash, + &peer->short_channel_ids[LOCAL], timestamp, flags, peer->cltv_delta, 1, peer->fee_base, peer->fee_per_satoshi); msg = towire_hsm_cupdate_sig_req(tmpctx, cupdate); @@ -267,6 +268,7 @@ static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer) &peer->announcement_bitcoin_sigs[first], &peer->announcement_bitcoin_sigs[second], features, + &peer->chain_hash, &peer->short_channel_ids[LOCAL], &peer->node_ids[first], &peer->node_ids[second], &peer->channel->funding_pubkey[first], &peer->channel->funding_pubkey[second]); diff --git a/lightningd/gossip/gossip.c b/lightningd/gossip/gossip.c index ae3cb0a87..89d3d23c7 100644 --- a/lightningd/gossip/gossip.c +++ b/lightningd/gossip/gossip.c @@ -667,7 +667,7 @@ static struct io_plan *gossip_init(struct daemon_conn *master, log_book = new_log_book(daemon, 2 * 1024 * 1024, LOG_BROKEN + 1); base_log = new_log(daemon, log_book, "lightningd_gossip(%u):", (int)getpid()); - daemon->rstate = new_routing_state(daemon, base_log); + daemon->rstate = new_routing_state(daemon, base_log, &chain_hash); return daemon_conn_read_next(master->conn, master); } diff --git a/lightningd/hsm/hsm.c b/lightningd/hsm/hsm.c index d5f6afe54..71669ef68 100644 --- a/lightningd/hsm/hsm.c +++ b/lightningd/hsm/hsm.c @@ -175,6 +175,7 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn, u32 timestamp, fee_base_msat, fee_proportional_mill; u64 htlc_minimum_msat; u16 flags, cltv_expiry_delta; + struct sha256_double chain_hash; u8 *cu; if (!fromwire_hsm_cupdate_sig_req(tmpctx, dc->msg_in, NULL, &cu)) { @@ -184,7 +185,8 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn, return io_close(conn); } - if (!fromwire_channel_update(cu, NULL, &sig, &scid, ×tamp, &flags, + if (!fromwire_channel_update(cu, NULL, &sig, &chain_hash, + &scid, ×tamp, &flags, &cltv_expiry_delta, &htlc_minimum_msat, &fee_base_msat, &fee_proportional_mill)) { status_trace("Failed to parse inner channel_update: %s", @@ -202,7 +204,8 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn, sign_hash(&node_pkey, &hash, &sig); - cu = towire_channel_update(tmpctx, &sig, &scid, timestamp, flags, + cu = towire_channel_update(tmpctx, &sig, &chain_hash, + &scid, timestamp, flags, cltv_expiry_delta, htlc_minimum_msat, fee_base_msat, fee_proportional_mill); diff --git a/wire/gen_peer_wire_csv b/wire/gen_peer_wire_csv index 2494e947e..a810f8465 100644 --- a/wire/gen_peer_wire_csv +++ b/wire/gen_peer_wire_csv @@ -114,11 +114,12 @@ channel_announcement,128,bitcoin_signature_1,64 channel_announcement,192,bitcoin_signature_2,64 channel_announcement,256,len,2 channel_announcement,258,features,len -channel_announcement,258+len,short_channel_id,8 -channel_announcement,266+len,node_id_1,33 -channel_announcement,299+len,node_id_2,33 -channel_announcement,332+len,bitcoin_key_1,33 -channel_announcement,365+len,bitcoin_key_2,33 +channel_announcement,258+len,chain_hash,32 +channel_announcement,290+len,short_channel_id,8 +channel_announcement,298+len,node_id_1,33 +channel_announcement,331+len,node_id_2,33 +channel_announcement,364+len,bitcoin_key_1,33 +channel_announcement,397+len,bitcoin_key_2,33 node_announcement,257 node_announcement,0,signature,64 node_announcement,64,flen,2 @@ -131,10 +132,11 @@ node_announcement,138+flen,addrlen,2 node_announcement,140+flen,addresses,addrlen channel_update,258 channel_update,0,signature,64 -channel_update,64,short_channel_id,8 -channel_update,72,timestamp,4 -channel_update,76,flags,2 -channel_update,78,cltv_expiry_delta,2 -channel_update,80,htlc_minimum_msat,8 -channel_update,88,fee_base_msat,4 -channel_update,92,fee_proportional_millionths,4 +channel_update,64,chain_hash,32 +channel_update,96,short_channel_id,8 +channel_update,104,timestamp,4 +channel_update,108,flags,2 +channel_update,110,cltv_expiry_delta,2 +channel_update,112,htlc_minimum_msat,8 +channel_update,120,fee_base_msat,4 +channel_update,124,fee_proportional_millionths,4 diff --git a/wire/test/run-peer-wire.c b/wire/test/run-peer-wire.c index 1b5ad7941..ad9d3d0c3 100644 --- a/wire/test/run-peer-wire.c +++ b/wire/test/run-peer-wire.c @@ -137,6 +137,7 @@ struct msg_channel_update { u64 htlc_minimum_msat; u32 fee_base_msat; u32 fee_proportional_millionths; + struct sha256_double chain_hash; struct short_channel_id short_channel_id; }; struct msg_funding_locked { @@ -193,6 +194,7 @@ struct msg_channel_announcement { secp256k1_ecdsa_signature bitcoin_signature_1; secp256k1_ecdsa_signature bitcoin_signature_2; u8 *features; + struct sha256_double chain_hash; struct short_channel_id short_channel_id; struct pubkey node_id_1; struct pubkey node_id_2; @@ -225,6 +227,7 @@ static void *towire_struct_channel_announcement(const tal_t *ctx, &s->bitcoin_signature_1, &s->bitcoin_signature_2, s->features, + &s->chain_hash, &s->short_channel_id, &s->node_id_1, &s->node_id_2, @@ -241,6 +244,7 @@ static struct msg_channel_announcement *fromwire_struct_channel_announcement(con &s->bitcoin_signature_1, &s->bitcoin_signature_2, &s->features, + &s->chain_hash, &s->short_channel_id, &s->node_id_1, &s->node_id_2, @@ -373,6 +377,7 @@ static void *towire_struct_channel_update(const tal_t *ctx, { return towire_channel_update(ctx, &s->signature, + &s->chain_hash, &s->short_channel_id, s->timestamp, s->flags, @@ -388,6 +393,7 @@ static struct msg_channel_update *fromwire_struct_channel_update(const tal_t *ct if (fromwire_channel_update(p, plen, &s->signature, + &s->chain_hash, &s->short_channel_id, &s->timestamp, &s->flags, @@ -700,6 +706,7 @@ static bool channel_announcement_eq(const struct msg_channel_announcement *a, { return eq_upto(a, b, features) && eq_var(a, b, features) + && eq_field(a, b, chain_hash) && short_channel_id_eq(&a->short_channel_id, &b->short_channel_id) && eq_between(a, b, node_id_1, bitcoin_key_2); }