mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-23 17:14:22 +01:00
gossipd: generalize encoding functions
We're about to use the for gossip extended info too, which *don't* put the encoding byte at the beginning of the data stream. So this removes some "scids" from function names and separates out the "prepend a byte" case from the "external encoding_type" case. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -77,7 +77,7 @@
|
|||||||
|
|
||||||
/* In developer mode we provide hooks for whitebox testing */
|
/* In developer mode we provide hooks for whitebox testing */
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
static u32 max_scids_encode_bytes = -1U;
|
static u32 max_encoding_bytes = -1U;
|
||||||
static bool suppress_gossip = false;
|
static bool suppress_gossip = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -261,16 +261,14 @@ static void queue_peer_from_store(struct peer *peer,
|
|||||||
* simple compression scheme: the first byte indicates the encoding, the
|
* simple compression scheme: the first byte indicates the encoding, the
|
||||||
* rest contains the data.
|
* rest contains the data.
|
||||||
*/
|
*/
|
||||||
static u8 *encode_short_channel_ids_start(const tal_t *ctx)
|
static u8 *encoding_start(const tal_t *ctx)
|
||||||
{
|
{
|
||||||
u8 *encoded = tal_arr(ctx, u8, 0);
|
return tal_arr(ctx, u8, 0);
|
||||||
towire_u8(&encoded, SHORTIDS_ZLIB);
|
|
||||||
return encoded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Marshal a single short_channel_id */
|
/* Marshal a single short_channel_id */
|
||||||
static void encode_add_short_channel_id(u8 **encoded,
|
static void encoding_add_short_channel_id(u8 **encoded,
|
||||||
const struct short_channel_id *scid)
|
const struct short_channel_id *scid)
|
||||||
{
|
{
|
||||||
towire_short_channel_id(encoded, scid);
|
towire_short_channel_id(encoded, scid);
|
||||||
}
|
}
|
||||||
@@ -281,7 +279,7 @@ static void encode_add_short_channel_id(u8 **encoded,
|
|||||||
* more complex and use separate streams. The upside is that it's between
|
* more complex and use separate streams. The upside is that it's between
|
||||||
* 2 and 5 times smaller (assuming optimal Rice encoding + gzip). We can add
|
* 2 and 5 times smaller (assuming optimal Rice encoding + gzip). We can add
|
||||||
* that later. */
|
* that later. */
|
||||||
static u8 *zencode_scids(const tal_t *ctx, const u8 *scids, size_t len)
|
static u8 *zencode(const tal_t *ctx, const u8 *scids, size_t len)
|
||||||
{
|
{
|
||||||
u8 *z;
|
u8 *z;
|
||||||
int err;
|
int err;
|
||||||
@@ -291,50 +289,73 @@ static u8 *zencode_scids(const tal_t *ctx, const u8 *scids, size_t len)
|
|||||||
z = tal_arr(ctx, u8, len);
|
z = tal_arr(ctx, u8, len);
|
||||||
err = compress2(z, &compressed_len, scids, len, Z_BEST_COMPRESSION);
|
err = compress2(z, &compressed_len, scids, len, Z_BEST_COMPRESSION);
|
||||||
if (err == Z_OK) {
|
if (err == Z_OK) {
|
||||||
status_trace("short_ids compressed %zu into %lu",
|
status_trace("compressed %zu into %lu",
|
||||||
len, compressed_len);
|
len, compressed_len);
|
||||||
tal_resize(&z, compressed_len);
|
tal_resize(&z, compressed_len);
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
status_trace("short_ids compress %zu returned %i:"
|
status_trace("compress %zu returned %i:"
|
||||||
" not compresssing", len, err);
|
" not compresssing", len, err);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Once we've assembled */
|
/* Try compressing *encoded: fails if result would be longer.
|
||||||
static bool encode_short_channel_ids_end(u8 **encoded, size_t max_bytes)
|
* @off is offset to place result in *encoded.
|
||||||
|
*/
|
||||||
|
static bool encoding_end_zlib(u8 **encoded, size_t off)
|
||||||
{
|
{
|
||||||
u8 *z;
|
u8 *z;
|
||||||
|
size_t len = tal_count(*encoded);
|
||||||
|
|
||||||
/* First byte says what encoding we want. */
|
z = zencode(tmpctx, *encoded, len);
|
||||||
switch ((enum scid_encode_types)(*encoded)[0]) {
|
if (!z)
|
||||||
case SHORTIDS_ZLIB:
|
return false;
|
||||||
/* compress */
|
|
||||||
z = zencode_scids(tmpctx, *encoded + 1, tal_count(*encoded) - 1);
|
/* Successful: copy over and trim */
|
||||||
if (z) {
|
tal_resize(encoded, off + tal_count(z));
|
||||||
/* If successful, copy over and trimp */
|
memcpy(*encoded + off, z, tal_count(z));
|
||||||
tal_resize(encoded, 1 + tal_count(z));
|
return true;
|
||||||
memcpy((*encoded) + 1, z, tal_count(z));
|
}
|
||||||
goto check_length;
|
|
||||||
}
|
static void encoding_end_no_compress(u8 **encoded, size_t off)
|
||||||
/* Otherwise, change first byte to 'uncompressed' */
|
{
|
||||||
(*encoded)[0] = SHORTIDS_UNCOMPRESSED;
|
size_t len = tal_count(*encoded);
|
||||||
/* Fall thru */
|
|
||||||
case SHORTIDS_UNCOMPRESSED:
|
tal_resize(encoded, off + len);
|
||||||
goto check_length;
|
memmove(*encoded + off, *encoded, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Once we've assembled it, try compressing.
|
||||||
|
* Prepends encoding type to @encoding. */
|
||||||
|
static bool encoding_end_prepend_type(u8 **encoded, size_t max_bytes)
|
||||||
|
{
|
||||||
|
if (encoding_end_zlib(encoded, 1))
|
||||||
|
**encoded = SHORTIDS_ZLIB;
|
||||||
|
else {
|
||||||
|
encoding_end_no_compress(encoded, 1);
|
||||||
|
**encoded = SHORTIDS_UNCOMPRESSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
|
||||||
"Unknown short_ids encoding %u", (*encoded)[0]);
|
|
||||||
|
|
||||||
check_length:
|
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
if (tal_count(*encoded) > max_scids_encode_bytes)
|
if (tal_count(*encoded) > max_encoding_bytes)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
return tal_count(*encoded) <= max_bytes;
|
return tal_count(*encoded) <= max_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try compressing, leaving type external */
|
||||||
|
static UNNEEDED bool encoding_end_external_type(u8 **encoded, u8 *type, size_t max_bytes)
|
||||||
|
{
|
||||||
|
if (encoding_end_zlib(encoded, 0))
|
||||||
|
*type = SHORTIDS_ZLIB;
|
||||||
|
else {
|
||||||
|
encoding_end_no_compress(encoded, 0);
|
||||||
|
*type = SHORTIDS_UNCOMPRESSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tal_count(*encoded) <= max_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/*~ We have different levels of gossipiness, depending on our needs. */
|
/*~ We have different levels of gossipiness, depending on our needs. */
|
||||||
static u32 gossip_start(enum gossip_level gossip_level)
|
static u32 gossip_start(enum gossip_level gossip_level)
|
||||||
{
|
{
|
||||||
@@ -609,11 +630,11 @@ static bool query_short_channel_ids(struct daemon *daemon,
|
|||||||
if (peer->scid_query_outstanding)
|
if (peer->scid_query_outstanding)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
encoded = encode_short_channel_ids_start(tmpctx);
|
encoded = encoding_start(tmpctx);
|
||||||
for (size_t i = 0; i < tal_count(scids); i++)
|
for (size_t i = 0; i < tal_count(scids); i++)
|
||||||
encode_add_short_channel_id(&encoded, &scids[i]);
|
encoding_add_short_channel_id(&encoded, &scids[i]);
|
||||||
|
|
||||||
if (!encode_short_channel_ids_end(&encoded, max_encoded_bytes)) {
|
if (!encoding_end_prepend_type(&encoded, max_encoded_bytes)) {
|
||||||
status_broken("query_short_channel_ids: %zu is too many",
|
status_broken("query_short_channel_ids: %zu is too many",
|
||||||
tal_count(scids));
|
tal_count(scids));
|
||||||
return false;
|
return false;
|
||||||
@@ -892,7 +913,7 @@ static bool queue_channel_ranges(struct peer *peer,
|
|||||||
u32 tail_blocks)
|
u32 tail_blocks)
|
||||||
{
|
{
|
||||||
struct routing_state *rstate = peer->daemon->rstate;
|
struct routing_state *rstate = peer->daemon->rstate;
|
||||||
u8 *encoded = encode_short_channel_ids_start(tmpctx);
|
u8 *encoded_scids = encoding_start(tmpctx);
|
||||||
struct short_channel_id scid;
|
struct short_channel_id scid;
|
||||||
bool scid_ok;
|
bool scid_ok;
|
||||||
|
|
||||||
@@ -930,14 +951,14 @@ static bool queue_channel_ranges(struct peer *peer,
|
|||||||
if (blocknum >= first_blocknum + number_of_blocks)
|
if (blocknum >= first_blocknum + number_of_blocks)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
encode_add_short_channel_id(&encoded, &scid);
|
encoding_add_short_channel_id(&encoded_scids, &scid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we can encode that, fine: send it */
|
/* If we can encode that, fine: send it */
|
||||||
if (encode_short_channel_ids_end(&encoded, max_encoded_bytes)) {
|
if (encoding_end_prepend_type(&encoded_scids, max_encoded_bytes)) {
|
||||||
reply_channel_range(peer, first_blocknum,
|
reply_channel_range(peer, first_blocknum,
|
||||||
number_of_blocks + tail_blocks,
|
number_of_blocks + tail_blocks,
|
||||||
encoded);
|
encoded_scids);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2790,10 +2811,10 @@ static struct io_plan *dev_set_max_scids_encode_size(struct io_conn *conn,
|
|||||||
const u8 *msg)
|
const u8 *msg)
|
||||||
{
|
{
|
||||||
if (!fromwire_gossip_dev_set_max_scids_encode_size(msg,
|
if (!fromwire_gossip_dev_set_max_scids_encode_size(msg,
|
||||||
&max_scids_encode_bytes))
|
&max_encoding_bytes))
|
||||||
master_badmsg(WIRE_GOSSIP_DEV_SET_MAX_SCIDS_ENCODE_SIZE, msg);
|
master_badmsg(WIRE_GOSSIP_DEV_SET_MAX_SCIDS_ENCODE_SIZE, msg);
|
||||||
|
|
||||||
status_trace("Set max_scids_encode_bytes to %u", max_scids_encode_bytes);
|
status_trace("Set max_scids_encode_bytes to %u", max_encoding_bytes);
|
||||||
return daemon_conn_read_next(conn, daemon->master);
|
return daemon_conn_read_next(conn, daemon->master);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user