Skip to content
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

Add network to init message #3300

Merged
merged 4 commits into from
Nov 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions bitcoin/chainparams.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "chainparams.h"
#include <ccan/array_size/array_size.h>
#include <ccan/str/str.h>
#include <common/utils.h>
#include <string.h>

/* Version codes for BIP32 extended keys in libwally-core.
Expand Down Expand Up @@ -220,6 +221,14 @@ const struct chainparams *chainparams_for_network(const char *network_name)
return NULL;
}

const struct chainparams **chainparams_for_networks(const tal_t *ctx)
{
const struct chainparams **params = tal_arr(ctx, const struct chainparams*, 0);
for (size_t i = 0; i < ARRAY_SIZE(networks); i++)
tal_arr_expand(&params, &networks[i]);
return params;
}

const struct chainparams *chainparams_by_chainhash(const struct bitcoin_blkid *chain_hash)
{
for (size_t i = 0; i < ARRAY_SIZE(networks); i++) {
Expand Down
6 changes: 6 additions & 0 deletions bitcoin/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ struct chainparams {
*/
const struct chainparams *chainparams_for_network(const char *network_name);

/**
* chainparams_for_networks - Get blockchain parameters for all known networks,
* as a tal array.
*/
const struct chainparams **chainparams_for_networks(const tal_t *ctx);

/**
* chainparams_by_bip173 - Helper to get a network by its bip173 name
*
Expand Down
1 change: 1 addition & 0 deletions connectd/connect_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <lightningd/gossip_msg.h>

msgtype,connectctl_init,2000
msgdata,connectctl_init,chainparams,chainparams,
msgdata,connectctl_init,id,node_id,
msgdata,connectctl_init,num_wireaddrs,u16,
msgdata,connectctl_init,wireaddrs,wireaddr_internal,num_wireaddrs
Expand Down
1 change: 1 addition & 0 deletions connectd/connectd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,7 @@ static struct io_plan *connect_init(struct io_conn *conn,
/* Fields which require allocation are allocated off daemon */
if (!fromwire_connectctl_init(
daemon, msg,
&chainparams,
&daemon->id,
&proposed_wireaddr,
&proposed_listen_announce,
Expand Down
47 changes: 44 additions & 3 deletions connectd/peer_exchange_initmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ struct peer {
u8 *msg;
};

static bool contains_common_chain(struct bitcoin_blkid *chains)
{
for (size_t i = 0; i < tal_count(chains); i++) {
if (bitcoin_blkid_eq(&chains[0], &chainparams->genesis_blockhash))
return true;
}
return false;
}

/* Here in case we need to read another message. */
static struct io_plan *read_init(struct io_conn *conn, struct peer *peer);

Expand All @@ -36,6 +45,7 @@ static struct io_plan *peer_init_received(struct io_conn *conn,
u8 *msg = cryptomsg_decrypt_body(tmpctx, &peer->cs, peer->msg);
u8 *globalfeatures, *features;
int unsup;
struct tlv_init_tlvs *tlvs = tlv_init_tlvs_new(msg);

if (!msg)
return io_close(conn);
Expand All @@ -51,13 +61,34 @@ static struct io_plan *peer_init_received(struct io_conn *conn,
if (unlikely(is_unknown_msg_discardable(msg)))
return read_init(conn, peer);

if (!fromwire_init(tmpctx, msg, &globalfeatures, &features)) {
if (!fromwire_init(tmpctx, msg, &globalfeatures, &features, tlvs)) {
status_peer_debug(&peer->id,
"bad fromwire_init '%s', closing",
tal_hex(tmpctx, msg));
return io_close(conn);
}

/* BOLT-ef7c97c02b6fa67a1df1af30b3843eb576100ebd #1:
* The receiving node:
* ...
* - upon receiving `networks` containing no common chains
* - MAY fail the connection.
*/
if (tlvs->networks) {
if (!tlvs->networks->chains) {
status_peer_debug(&peer->id,
"bad networks TLV in init '%s', closing",
tal_hex(tmpctx, msg));
return io_close(conn);
Comment on lines +78 to +82
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note this is technically redundant, since it's covered elegently by the next part anyway.

}
darosior marked this conversation as resolved.
Show resolved Hide resolved
if (!contains_common_chain(tlvs->networks->chains)) {
status_peer_debug(&peer->id,
"No common chain with this peer '%s', closing",
tal_hex(tmpctx, msg));
return io_close(conn);
}
}

/* The globalfeatures field is now unused, but there was a
* window where it was: combine the two. */
for (size_t i = 0; i < tal_bytelen(globalfeatures) * 8; i++) {
Expand Down Expand Up @@ -136,18 +167,27 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
/* If conn is closed, forget peer */
struct peer *peer = tal(conn, struct peer);
struct io_plan *(*next)(struct io_conn *, struct peer *);
struct tlv_init_tlvs *tlvs;

peer->daemon = daemon;
peer->id = *id;
peer->addr = *addr;
peer->cs = *cs;

/* BOLT #1:
/* BOLT-ef7c97c02b6fa67a1df1af30b3843eb576100ebd #1:
*
* The sending node:
* - MUST send `init` as the first Lightning message for any
* connection.
* ...
* - SHOULD set `networks` to all chains it will gossip or open
* channels for.
*/
tlvs = tlv_init_tlvs_new(tmpctx);
tlvs->networks = tal(tlvs, struct tlv_init_tlvs_networks);
tlvs->networks->chains = tal_arr(tlvs->networks, struct bitcoin_blkid, 1);
tlvs->networks->chains[0] = chainparams->genesis_blockhash;

/* Initially, there were two sets of feature bits: global and local.
* Local affected peer nodes only, global affected everyone. Both were
* sent in the `init` message, but node_announcement only advertized
Expand All @@ -167,7 +207,8 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
* from now on they'll all go in initfeatures. */
peer->msg = towire_init(NULL,
get_offered_globalinitfeatures(tmpctx),
get_offered_initfeatures(tmpctx));
get_offered_initfeatures(tmpctx),
tlvs);
status_peer_io(LOG_IO_OUT, &peer->id, peer->msg);
peer->msg = cryptomsg_encrypt_msg(peer, &peer->cs, take(peer->msg));

Expand Down
32 changes: 31 additions & 1 deletion devtools/gossipwith.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* Simple tool to route gossip from a peer. */
#include <bitcoin/block.h>
#include <bitcoin/chainparams.h>
#include <ccan/array_size/array_size.h>
#include <ccan/err/err.h>
#include <ccan/io/io.h>
Expand Down Expand Up @@ -81,6 +83,22 @@ enum dev_disconnect dev_disconnect(int pkt_type)
}
#endif

static char *opt_set_network(const char *arg, void *unused)
{
assert(arg != NULL);

/* Set the global chainparams instance */
chainparams = chainparams_for_network(arg);
if (!chainparams)
return tal_fmt(NULL, "Unknown network name '%s'", arg);
return NULL;
}

static void opt_show_network(char buf[OPT_SHOW_LEN], const void *unused)
{
snprintf(buf, OPT_SHOW_LEN, "%s", chainparams->network_name);
}

void peer_failed_connection_lost(void)
{
exit(0);
Expand Down Expand Up @@ -137,11 +155,19 @@ static struct io_plan *handshake_success(struct io_conn *conn,
OPTIONAL_FEATURE(OPT_INITIAL_ROUTING_SYNC));

if (!no_init) {
msg = towire_init(NULL, NULL, features);
struct tlv_init_tlvs *tlvs = NULL;
if (chainparams) {
tlvs = tlv_init_tlvs_new(NULL);
tlvs->networks = tal(tlvs, struct tlv_init_tlvs_networks);
tlvs->networks->chains = tal_arr(tlvs->networks, struct bitcoin_blkid, 1);
tlvs->networks->chains[0] = chainparams->genesis_blockhash;
}
msg = towire_init(NULL, NULL, features, tlvs);

sync_crypto_write(pps, take(msg));
/* Ignore their init message. */
tal_free(sync_crypto_read(NULL, pps));
tal_free(tlvs);
}

if (stream_stdin)
Expand Down Expand Up @@ -254,6 +280,10 @@ int main(int argc, char *argv[])
"Print out messages in hex");
opt_register_arg("--features=<hex>", opt_set_features, NULL,
&features, "Send these features in init");
opt_register_arg("--network", opt_set_network, opt_show_network,
NULL,
"Select the network parameters (bitcoin, testnet, regtest"
" liquid, liquid-regtest, litecoin or litecoin-testnet)");
opt_register_noarg("--help|-h", opt_usage_and_exit,
"id@addr[:port] [hex-msg-tosend...]\n"
"Connect to a lightning peer and relay gossip messages from it",
Expand Down
3 changes: 2 additions & 1 deletion lightningd/connect_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,8 @@ int connectd_init(struct lightningd *ld)
}

msg = towire_connectctl_init(
tmpctx, &ld->id,
tmpctx, chainparams,
&ld->id,
wireaddrs,
listen_announce,
ld->proxyaddr, ld->use_proxy_always || ld->pure_tor_setup,
Expand Down
3 changes: 3 additions & 0 deletions wire/extracted_peer_wire_csv
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ msgdata,init,gflen,u16,
msgdata,init,globalfeatures,byte,gflen
msgdata,init,lflen,u16,
msgdata,init,localfeatures,byte,lflen
msgdata,init,tlvs,init_tlvs,
tlvtype,init_tlvs,networks,1
tlvdata,init_tlvs,networks,chains,chain_hash,...
msgtype,error,17
msgdata,error,channel_id,channel_id,
msgdata,error,len,u16,
Expand Down
1 change: 1 addition & 0 deletions wire/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ ALL_TEST_PROGRAMS += $(WIRE_TEST_PROGRAMS)

wire-tests: $(WIRE_TEST_PROGRAMS:%=unittest/%)

wire/test/run-peer-wire: wire/gen_peer_wire.o wire/tlvstream.o common/bigsize.o
62 changes: 30 additions & 32 deletions wire/test/run-peer-wire.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#include "../gen_peer_wire.c"

#include "../towire.c"
#include "../fromwire.c"
#include "../peer_wire.c"

#include <assert.h>
#include <stdio.h>

#include <ccan/str/hex/hex.h>
#include <common/amount.h>
#include <common/bigsize.h>
#include <bitcoin/chainparams.h>
#include <common/sphinx.h>
#include <wire/gen_peer_wire.h>

secp256k1_context *secp256k1_ctx;

Expand All @@ -31,24 +34,6 @@ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
struct amount_sat a UNNEEDED,
struct amount_sat b UNNEEDED)
{ fprintf(stderr, "amount_sat_sub called!\n"); abort(); }
/* Generated stub for bigsize_get */
size_t bigsize_get(const u8 *p UNNEEDED, size_t max UNNEEDED, bigsize_t *val UNNEEDED)
{ fprintf(stderr, "bigsize_get called!\n"); abort(); }
/* Generated stub for bigsize_put */
size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED)
{ fprintf(stderr, "bigsize_put called!\n"); abort(); }
/* Generated stub for fromwire_tlvs */
bool fromwire_tlvs(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
const struct tlv_record_type types[] UNNEEDED,
size_t num_types UNNEEDED,
void *record UNNEEDED)
{ fprintf(stderr, "fromwire_tlvs called!\n"); abort(); }
/* Generated stub for towire_tlvs */
void towire_tlvs(u8 **pptr UNNEEDED,
const struct tlv_record_type types[] UNNEEDED,
size_t num_types UNNEEDED,
const void *record UNNEEDED)
{ fprintf(stderr, "towire_tlvs called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */

/* memsetting pubkeys doesn't work */
Expand Down Expand Up @@ -236,6 +221,7 @@ struct msg_channel_announcement {
struct msg_init {
u8 *globalfeatures;
u8 *localfeatures;
struct tlv_init_tlvs *tlvs;
};
struct msg_update_add_htlc {
struct channel_id channel_id;
Expand Down Expand Up @@ -761,16 +747,19 @@ static void *towire_struct_init(const tal_t *ctx,
{
return towire_init(ctx,
s->globalfeatures,
s->localfeatures);
s->localfeatures,
s->tlvs);
}

static struct msg_init *fromwire_struct_init(const tal_t *ctx, const void *p)
{
struct msg_init *s = tal(ctx, struct msg_init);
s->tlvs = tlv_init_tlvs_new(s);

if (!fromwire_init(s, p,
&s->globalfeatures,
&s->localfeatures))
&s->localfeatures,
s->tlvs))
return tal_free(s);

return s;
Expand Down Expand Up @@ -844,6 +833,9 @@ static bool error_eq(const struct msg_error *a,
static bool init_eq(const struct msg_init *a,
const struct msg_init *b)
{
for (size_t i = 0; i < tal_count(a->tlvs->networks->chains); i++)
assert(bitcoin_blkid_eq(&a->tlvs->networks->chains[i],
&b->tlvs->networks->chains[i]));
return eq_var(a, b, globalfeatures)
&& eq_var(a, b, localfeatures);
}
Expand Down Expand Up @@ -959,6 +951,7 @@ int main(void)
void *ctx = tal(NULL, char);
size_t i;
u8 *msg;
const struct chainparams **chains;

secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN);
Expand Down Expand Up @@ -1039,16 +1032,21 @@ int main(void)
assert(error_eq(&e, e2));
test_corruption(&e, e2, error);

memset(&init, 2, sizeof(init));
init.globalfeatures = tal_arr(ctx, u8, 2);
memset(init.globalfeatures, 2, 2);
init.localfeatures = tal_arr(ctx, u8, 2);
memset(init.localfeatures, 2, 2);

msg = towire_struct_init(ctx, &init);
init2 = fromwire_struct_init(ctx, msg);
assert(init_eq(&init, init2));
test_corruption(&init, init2, init);
chains = chainparams_for_networks(ctx);
for (i = 0; i < tal_count(chains); i++) {
memset(&init, 2, sizeof(init));
init.globalfeatures = tal_arr(ctx, u8, 2);
memset(init.globalfeatures, 2, 2);
init.localfeatures = tal_arr(ctx, u8, 2);
memset(init.localfeatures, 2, 2);
init.tlvs = tlv_init_tlvs_new(ctx);
init.tlvs->networks = tal(init.tlvs, struct tlv_init_tlvs_networks);
init.tlvs->networks->chains = tal_arr(ctx, struct bitcoin_blkid, 1);
init.tlvs->networks->chains[0] = chains[i]->genesis_blockhash;
msg = towire_struct_init(ctx, &init);
init2 = fromwire_struct_init(ctx, msg);
assert(init_eq(&init, init2));
}

memset(&uf, 2, sizeof(uf));

Expand Down