From b80342b9284839ca88730643005199cc7852ae1f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 20 Oct 2020 14:28:06 +1030 Subject: [PATCH] gossmap: implement feature tests Faster than pulling the announce msg and parsing. We need this to test if the node supports TLV. Signed-off-by: Rusty Russell --- common/gossmap.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ common/gossmap.h | 10 ++++++ 2 files changed, 90 insertions(+) diff --git a/common/gossmap.c b/common/gossmap.c index f77c8ec09..29256c9b2 100644 --- a/common/gossmap.c +++ b/common/gossmap.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,18 @@ static void map_nodeid(const struct gossmap *map, size_t offset, map_copy(map, offset, id, sizeof(*id)); } +static bool map_feature_set(const struct gossmap *map, int bit, + size_t offset, size_t len) +{ + size_t bytenum = bit / 8; + + if (bytenum >= len) + return false; + + /* Note reversed! */ + return map_u8(map, offset + len - 1 - bytenum) & (1 << (bit % 8)); +} + /* These values can change across calls to gossmap_check. */ u32 gossmap_max_node_idx(const struct gossmap *map) { @@ -835,3 +848,70 @@ u8 *gossmap_node_get_announce(const tal_t *ctx, map_copy(map, n->nann_off, msg, len); return msg; } + +/* BOLT #7: + * 1. type: 256 (`channel_announcement`) + * 2. data: + * * [`signature`:`node_signature_1`] + * * [`signature`:`node_signature_2`] + * * [`signature`:`bitcoin_signature_1`] + * * [`signature`:`bitcoin_signature_2`] + * * [`u16`:`len`] + * * [`len*byte`:`features`] + * * [`chain_hash`:`chain_hash`] + * * [`short_channel_id`:`short_channel_id`] + * * [`point`:`node_id_1`] + * * [`point`:`node_id_2`] + */ +int gossmap_chan_has_feature(const struct gossmap *map, + const struct gossmap_chan *c, + int fbit) +{ + /* Note that first two bytes are message type */ + const size_t feature_len_off = 2 + (64 + 64 + 64 + 64); + size_t feature_len; + + feature_len = map_be16(map, c->cann_off + feature_len_off); + + if (map_feature_set(map, OPTIONAL_FEATURE(fbit), + c->cann_off + feature_len_off + 2, feature_len)) + return OPTIONAL_FEATURE(fbit); + if (map_feature_set(map, COMPULSORY_FEATURE(fbit), + c->cann_off + feature_len_off + 2, feature_len)) + return COMPULSORY_FEATURE(fbit); + return -1; +} + +/* BOLT #7: + * 1. type: 257 (`node_announcement`) + * 2. data: + * * [`signature`:`signature`] + * * [`u16`:`flen`] + * * [`flen*byte`:`features`] + * * [`u32`:`timestamp`] + * * [`point`:`node_id`] + * * [`3*byte`:`rgb_color`] + * * [`32*byte`:`alias`] + * * [`u16`:`addrlen`] + * * [`addrlen*byte`:`addresses`] + */ +int gossmap_node_has_feature(const struct gossmap *map, + const struct gossmap_node *n, + int fbit) +{ + const size_t feature_len_off = 2 + 64; + size_t feature_len; + + if (n->nann_off == 0) + return -1; + + feature_len = map_be16(map, n->nann_off + feature_len_off); + + if (map_feature_set(map, OPTIONAL_FEATURE(fbit), + n->nann_off + feature_len_off + 2, feature_len)) + return OPTIONAL_FEATURE(fbit); + if (map_feature_set(map, COMPULSORY_FEATURE(fbit), + n->nann_off + feature_len_off + 2, feature_len)) + return COMPULSORY_FEATURE(fbit); + return -1; +} diff --git a/common/gossmap.h b/common/gossmap.h index 64e577272..0eca35d4a 100644 --- a/common/gossmap.h +++ b/common/gossmap.h @@ -89,6 +89,16 @@ u8 *gossmap_node_get_announce(const tal_t *ctx, const struct gossmap *map, const struct gossmap_node *n); +/* Return the feature bit (odd or even), or -1 if neither. */ +int gossmap_chan_has_feature(const struct gossmap *map, + const struct gossmap_chan *c, + int fbit); + +/* Return the feature bit (odd or even), or -1 if neither (or no announcement) */ +int gossmap_node_has_feature(const struct gossmap *map, + const struct gossmap_node *n, + int fbit); + /* Given a struct node, get the nth channel, and tell us if we're half[0/1]. * n must be less than node->num_chans */ struct gossmap_chan *gossmap_nth_chan(const struct gossmap *map,