|
|
@ -56,6 +56,7 @@ |
|
|
|
#include <wire/gen_peer_wire.h> |
|
|
|
#include <wire/wire_io.h> |
|
|
|
#include <wire/wire_sync.h> |
|
|
|
#include <zlib.h> |
|
|
|
|
|
|
|
#define GOSSIP_MAX_REACH_ATTEMPTS 10 |
|
|
|
|
|
|
@ -64,6 +65,18 @@ |
|
|
|
#define INITIAL_WAIT_SECONDS 1 |
|
|
|
#define MAX_WAIT_SECONDS 300 |
|
|
|
|
|
|
|
/* BOLT #7:
|
|
|
|
* |
|
|
|
* Encoding types: |
|
|
|
* * `0`: uncompressed array of `short_channel_id` types, in ascending order. |
|
|
|
* * `1`: array of `short_channel_id` types, in ascending order, compressed with |
|
|
|
* zlib<sup>[1](#reference-1)</sup> |
|
|
|
*/ |
|
|
|
enum scid_encode_types { |
|
|
|
SHORTIDS_UNCOMPRESSED = 0, |
|
|
|
SHORTIDS_ZLIB = 1 |
|
|
|
}; |
|
|
|
|
|
|
|
/* We put everything in this struct (redundantly) to pass it to timer cb */ |
|
|
|
struct important_peerid { |
|
|
|
struct daemon *daemon; |
|
|
@ -424,14 +437,8 @@ static void reached_peer(struct peer *peer, struct io_conn *conn) |
|
|
|
|
|
|
|
static u8 *encode_short_channel_ids_start(const tal_t *ctx) |
|
|
|
{ |
|
|
|
/* BOLT #7:
|
|
|
|
* |
|
|
|
* Encoding types: |
|
|
|
* * `0`: uncompressed array of `short_channel_id` types, in ascending |
|
|
|
* order. |
|
|
|
*/ |
|
|
|
u8 *encoded = tal_arr(tmpctx, u8, 0); |
|
|
|
towire_u8(&encoded, 0); |
|
|
|
towire_u8(&encoded, SHORTIDS_ZLIB); |
|
|
|
return encoded; |
|
|
|
} |
|
|
|
|
|
|
@ -441,8 +448,48 @@ static void encode_add_short_channel_id(u8 **encoded, |
|
|
|
towire_short_channel_id(encoded, scid); |
|
|
|
} |
|
|
|
|
|
|
|
static u8 *zencode_scids(const tal_t *ctx, const u8 *scids, size_t len) |
|
|
|
{ |
|
|
|
u8 *z; |
|
|
|
int err; |
|
|
|
unsigned long compressed_len = len; |
|
|
|
|
|
|
|
/* Prefer to fail if zlib makes it larger */ |
|
|
|
z = tal_arr(ctx, u8, len); |
|
|
|
err = compress2(z, &compressed_len, scids, len, Z_BEST_COMPRESSION); |
|
|
|
if (err == Z_OK) { |
|
|
|
status_trace("short_ids compressed %zu into %lu", |
|
|
|
len, compressed_len); |
|
|
|
tal_resize(&z, compressed_len); |
|
|
|
return z; |
|
|
|
} |
|
|
|
status_trace("short_ids compress %zu returned %i:" |
|
|
|
" not compresssing", len, err); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static bool encode_short_channel_ids_end(u8 **encoded, size_t max_bytes) |
|
|
|
{ |
|
|
|
u8 *z; |
|
|
|
|
|
|
|
switch ((enum scid_encode_types)(*encoded)[0]) { |
|
|
|
case SHORTIDS_ZLIB: |
|
|
|
z = zencode_scids(tmpctx, *encoded + 1, tal_len(*encoded) - 1); |
|
|
|
if (z) { |
|
|
|
tal_resize(encoded, 1 + tal_len(z)); |
|
|
|
memcpy((*encoded) + 1, z, tal_len(z)); |
|
|
|
goto check_length; |
|
|
|
} |
|
|
|
(*encoded)[0] = SHORTIDS_UNCOMPRESSED; |
|
|
|
/* Fall thru */ |
|
|
|
case SHORTIDS_UNCOMPRESSED: |
|
|
|
goto check_length; |
|
|
|
} |
|
|
|
|
|
|
|
status_failed(STATUS_FAIL_INTERNAL_ERROR, |
|
|
|
"Unknown short_ids encoding %u", (*encoded)[0]); |
|
|
|
|
|
|
|
check_length: |
|
|
|
#if DEVELOPER |
|
|
|
if (tal_len(*encoded) > max_scids_encode_bytes) |
|
|
|
return false; |
|
|
@ -792,33 +839,54 @@ static u8 *handle_gossip_msg(struct daemon *daemon, const u8 *msg, |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
/* BOLT #7:
|
|
|
|
* |
|
|
|
* the first byte indicates the encoding, the rest contains the data. |
|
|
|
* |
|
|
|
* Encoding types: |
|
|
|
* * `0`: uncompressed array of `short_channel_id` types, in ascending order. |
|
|
|
*/ |
|
|
|
static u8 *unzlib(const tal_t *ctx, const u8 *encoded, size_t len) |
|
|
|
{ |
|
|
|
/* http://www.zlib.net/zlib_tech.html gives 1032:1 as worst-case,
|
|
|
|
* which is 67632120 bytes for us. But they're not encoding zeroes, |
|
|
|
* and each scid must be unique. So 1MB is far more reasonable. */ |
|
|
|
unsigned long unclen = 1024*1024; |
|
|
|
int zerr; |
|
|
|
u8 *unc = tal_arr(ctx, u8, unclen); |
|
|
|
|
|
|
|
zerr = uncompress(unc, &unclen, encoded, len); |
|
|
|
if (zerr != Z_OK) { |
|
|
|
status_trace("unzlib: error %i", zerr); |
|
|
|
return tal_free(unc); |
|
|
|
} |
|
|
|
|
|
|
|
/* Truncate and return. */ |
|
|
|
tal_resize(&unc, unclen); |
|
|
|
return unc; |
|
|
|
} |
|
|
|
|
|
|
|
static struct short_channel_id *decode_short_ids(const tal_t *ctx, |
|
|
|
const u8 *encoded) |
|
|
|
{ |
|
|
|
struct short_channel_id *scids; |
|
|
|
size_t max = tal_len(encoded), n; |
|
|
|
u8 type; |
|
|
|
enum scid_encode_types type; |
|
|
|
|
|
|
|
/* BOLT #7:
|
|
|
|
* |
|
|
|
* The receiver: |
|
|
|
* - if the first byte of `encoded_short_ids` is not zero: |
|
|
|
* - if the first byte of `encoded_short_ids` is not a known encoding |
|
|
|
* type: |
|
|
|
* - MAY fail the connection |
|
|
|
* - if `encoded_short_ids` does not decode into a whole number of |
|
|
|
* `short_channel_id`: |
|
|
|
* - MAY fail the connection |
|
|
|
*/ |
|
|
|
type = fromwire_u8(&encoded, &max); |
|
|
|
if (type != 0) |
|
|
|
switch (type) { |
|
|
|
case SHORTIDS_ZLIB: |
|
|
|
encoded = unzlib(tmpctx, encoded, max); |
|
|
|
if (!encoded) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
status_trace("Uncompressed %zu into %zu bytes (%s)", |
|
|
|
max, tal_len(encoded), tal_hex(tmpctx, encoded)); |
|
|
|
max = tal_len(encoded); |
|
|
|
/* fall thru */ |
|
|
|
case SHORTIDS_UNCOMPRESSED: |
|
|
|
n = 0; |
|
|
|
scids = tal_arr(ctx, struct short_channel_id, n); |
|
|
|
while (max) { |
|
|
@ -831,6 +899,8 @@ static struct short_channel_id *decode_short_ids(const tal_t *ctx, |
|
|
|
return tal_free(scids); |
|
|
|
return scids; |
|
|
|
} |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static void handle_query_short_channel_ids(struct peer *peer, u8 *msg) |
|
|
|
{ |
|
|
|