gossip/liquidity-ad: node_ann comparison, optional TLV check

Correctly mark whether or not the TLV's are the same/different, given two
node announcements
This commit is contained in:
niftynei 2021-05-28 15:12:41 -05:00 committed by neil saitug
parent 49bae2a873
commit 55f5a5caba
6 changed files with 202 additions and 15 deletions

View File

@ -96,13 +96,14 @@ bool cupdate_different(struct gossip_store *gs,
|| !memeq(oparts[1], osizes[1], nparts[1], nsizes[1]);
}
/* Get non-signature, non-timestamp parts of (valid!) node_announcement */
/* Get non-signature, non-timestamp parts of (valid!) node_announcement,
* with TLV broken out separately */
static void get_nannounce_parts(const u8 *node_announcement,
const u8 *parts[2],
size_t sizes[2])
const u8 *parts[3],
size_t sizes[3])
{
size_t len;
const u8 *flen;
size_t len, ad_len;
const u8 *flen, *ad_start;
/* BOLT #7:
*
@ -125,17 +126,43 @@ static void get_nannounce_parts(const u8 *node_announcement,
sizes[0] = 2 + fromwire_u16(&flen, &len);
assert(flen != NULL && len >= 4);
/* BOLT-0fe3485a5320efaa2be8cfa0e570ad4d0259cec3 #7:
*
* * [`u32`:`timestamp`]
* * [`point`:`node_id`]
* * [`3*byte`:`rgb_color`]
* * [`32*byte`:`alias`]
* * [`u16`:`addrlen`]
* * [`addrlen*byte`:`addresses`]
* * [`node_ann_tlvs`:`tlvs`]
*/
parts[1] = node_announcement + 2 + 64 + sizes[0] + 4;
sizes[1] = tal_count(node_announcement) - (2 + 64 + sizes[0] + 4);
/* Find the end of the addresses */
ad_start = parts[1] + 33 + 3 + 32;
len = tal_count(node_announcement)
- (2 + 64 + sizes[0] + 4 + 33 + 3 + 32);
ad_len = fromwire_u16(&ad_start, &len);
assert(ad_start != NULL && len >= ad_len);
sizes[1] = 33 + 3 + 32 + 2 + ad_len;
/* Is there a TLV ? */
sizes[2] = len - ad_len;
if (sizes[2] != 0)
parts[2] = parts[1] + sizes[1];
else
parts[2] = NULL;
}
/* Is this node_announcement different from prev (not sigs and timestamps)? */
bool nannounce_different(struct gossip_store *gs,
const struct node *node,
const u8 *nannounce)
const u8 *nannounce,
bool *only_missing_tlv)
{
const u8 *oparts[2], *nparts[2];
size_t osizes[2], nsizes[2];
const u8 *oparts[3], *nparts[3];
size_t osizes[3], nsizes[3];
const u8 *orig;
/* Get last one we have. */
@ -143,8 +170,14 @@ bool nannounce_different(struct gossip_store *gs,
get_nannounce_parts(orig, oparts, osizes);
get_nannounce_parts(nannounce, nparts, nsizes);
if (only_missing_tlv)
*only_missing_tlv = memeq(oparts[0], osizes[0], nparts[0], nsizes[0])
&& memeq(oparts[1], osizes[1], nparts[1], nsizes[1])
&& !memeq(oparts[2], osizes[2], nparts[2], nsizes[2]);
return !memeq(oparts[0], osizes[0], nparts[0], nsizes[0])
|| !memeq(oparts[1], osizes[1], nparts[1], nsizes[1]);
|| !memeq(oparts[1], osizes[1], nparts[1], nsizes[1])
|| !memeq(oparts[2], osizes[2], nparts[2], nsizes[2]);
}
/* This routine created a `node_announcement` for our node, and hands it to
@ -177,7 +210,8 @@ static void update_own_node_announcement(struct daemon *daemon)
if (self && self->bcast.index) {
u32 next;
if (!nannounce_different(daemon->rstate->gs, self, nannounce))
if (!nannounce_different(daemon->rstate->gs, self, nannounce,
NULL))
return;
/* BOLT #7:

View File

@ -29,7 +29,8 @@ bool cupdate_different(struct gossip_store *gs,
* node->bcast.index must be non-zero! */
bool nannounce_different(struct gossip_store *gs,
const struct node *node,
const u8 *nannounce);
const u8 *nannounce,
bool *only_missing_tlv);
/* Should we announce our own node? Called at strategic places. */
void maybe_send_own_node_announce(struct daemon *daemon);

View File

@ -1656,6 +1656,8 @@ bool routing_add_node_announcement(struct routing_state *rstate,
}
if (node->bcast.index) {
bool only_tlv_diff;
if (index != 0) {
status_broken("gossip_store node_announcement %u replaces %u!",
index, node->bcast.index);
@ -1670,7 +1672,8 @@ bool routing_add_node_announcement(struct routing_state *rstate,
/* Allow redundant updates once every 7 days */
if (timestamp < node->bcast.timestamp + GOSSIP_PRUNE_INTERVAL(rstate->dev_fast_gossip_prune) / 2
&& !nannounce_different(rstate->gs, node, msg)) {
&& !nannounce_different(rstate->gs, node, msg,
&only_tlv_diff)) {
SUPERVERBOSE(
"Ignoring redundant nannounce for %s"
" (last %u, now %u)",

View File

@ -103,7 +103,8 @@ void memleak_remove_intmap_(struct htable *memtable UNNEEDED, const struct intma
/* Generated stub for nannounce_different */
bool nannounce_different(struct gossip_store *gs UNNEEDED,
const struct node *node UNNEEDED,
const u8 *nannounce UNNEEDED)
const u8 *nannounce UNNEEDED,
bool *only_missing_tlv UNNEEDED)
{ fprintf(stderr, "nannounce_different called!\n"); abort(); }
/* Generated stub for new_reltimer_ */
struct oneshot *new_reltimer_(struct timers *timers UNNEEDED,

View File

@ -0,0 +1,147 @@
#include "../gossip_generation.c"
#include <common/json_stream.h>
#include <common/setup.h>
#include <stdio.h>
/* AUTOGENERATED MOCKS START */
/* Generated stub for find_peer */
struct peer *find_peer(struct daemon *daemon UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "find_peer called!\n"); abort(); }
/* Generated stub for fmt_wireaddr_without_port */
char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr *a UNNEEDED)
{ fprintf(stderr, "fmt_wireaddr_without_port called!\n"); abort(); }
/* Generated stub for fromwire_gossipd_local_channel_update */
bool fromwire_gossipd_local_channel_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, bool *disable UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, struct amount_msat *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, struct amount_msat *htlc_maximum_msat UNNEEDED)
{ fprintf(stderr, "fromwire_gossipd_local_channel_update called!\n"); abort(); }
/* Generated stub for fromwire_hsmd_cupdate_sig_reply */
bool fromwire_hsmd_cupdate_sig_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **cu UNNEEDED)
{ fprintf(stderr, "fromwire_hsmd_cupdate_sig_reply called!\n"); abort(); }
/* Generated stub for fromwire_hsmd_node_announcement_sig_reply */
bool fromwire_hsmd_node_announcement_sig_reply(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED)
{ fprintf(stderr, "fromwire_hsmd_node_announcement_sig_reply called!\n"); abort(); }
/* Generated stub for get_node */
struct node *get_node(struct routing_state *rstate UNNEEDED,
const struct node_id *id UNNEEDED)
{ fprintf(stderr, "get_node called!\n"); abort(); }
/* Generated stub for gossip_time_now */
struct timeabs gossip_time_now(const struct routing_state *rstate UNNEEDED)
{ fprintf(stderr, "gossip_time_now called!\n"); abort(); }
/* Generated stub for handle_channel_update */
u8 *handle_channel_update(struct routing_state *rstate UNNEEDED, const u8 *update TAKES UNNEEDED,
struct peer *peer UNNEEDED,
struct short_channel_id *unknown_scid UNNEEDED,
bool force UNNEEDED)
{ fprintf(stderr, "handle_channel_update called!\n"); abort(); }
/* Generated stub for handle_node_announcement */
u8 *handle_node_announcement(struct routing_state *rstate UNNEEDED, const u8 *node UNNEEDED,
struct peer *peer UNNEEDED, bool *was_unknown UNNEEDED)
{ fprintf(stderr, "handle_node_announcement called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for new_reltimer_ */
struct oneshot *new_reltimer_(struct timers *timers UNNEEDED,
const tal_t *ctx UNNEEDED,
struct timerel expire UNNEEDED,
void (*cb)(void *) UNNEEDED, void *arg UNNEEDED)
{ fprintf(stderr, "new_reltimer_ called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
/* Generated stub for queue_peer_msg */
void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED)
{ fprintf(stderr, "queue_peer_msg called!\n"); abort(); }
/* Generated stub for status_failed */
void status_failed(enum status_failreason code UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "status_failed called!\n"); abort(); }
/* Generated stub for status_fmt */
void status_fmt(enum log_level level UNNEEDED,
const struct node_id *peer UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "status_fmt called!\n"); abort(); }
/* Generated stub for towire_hsmd_cupdate_sig_req */
u8 *towire_hsmd_cupdate_sig_req(const tal_t *ctx UNNEEDED, const u8 *cu UNNEEDED)
{ fprintf(stderr, "towire_hsmd_cupdate_sig_req called!\n"); abort(); }
/* Generated stub for towire_hsmd_node_announcement_sig_req */
u8 *towire_hsmd_node_announcement_sig_req(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
{ fprintf(stderr, "towire_hsmd_node_announcement_sig_req called!\n"); abort(); }
/* Generated stub for towire_wireaddr */
void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED)
{ fprintf(stderr, "towire_wireaddr called!\n"); abort(); }
/* Generated stub for wire_sync_read */
u8 *wire_sync_read(const tal_t *ctx UNNEEDED, int fd UNNEEDED)
{ fprintf(stderr, "wire_sync_read called!\n"); abort(); }
/* Generated stub for wire_sync_write */
bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED)
{ fprintf(stderr, "wire_sync_write called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */
/* Overwriting this to return test data */
const u8 *gossip_store_get(const tal_t *ctx,
struct gossip_store *gs,
u64 offset)
{
/* No TLV, different */
if (offset == 0)
return tal_hexdata(ctx, "01010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000802aaa260b145790266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c035180266e453454e494f524245414d000000000000000000000000000000000000000000000000", strlen("01010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000802aaa260b145790266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c035180266e453454e494f524245414d000000000000000000000000000000000000000000000000"));
/* No TLV, same */
if (offset == 1)
return tal_hexdata(ctx, "01017d49b51b7d3772636c09901df78c81faa1a7f045e329366ad779ecbaf0cc07f764d8ffd3596ef6802fd0e4c5c180c74fb3dfb14aae493ed48d35a3df75c20eca00078000000802aaa260b14569022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59022d2253494c454e544152544953542d3236352d67373833393533312d6d6f646465640000", strlen("01017d49b51b7d3772636c09901df78c81faa1a7f045e329366ad779ecbaf0cc07f764d8ffd3596ef6802fd0e4c5c180c74fb3dfb14aae493ed48d35a3df75c20eca00078000000802aaa260b14569022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59022d2253494c454e544152544953542d3236352d67373833393533312d6d6f646465640000"));
/* Same, with TLV */
if (offset == 2)
return tal_hexdata(ctx, "0101069628d227649cc2823d94647ad08ea34ad24e7eea95b7a0249bc83e73efefa6072cab1841f0ef3e6d7f4c4140b7b1b13049eb0d85941d7d7bd30c921bfd550300078000000802aaa260b1496f0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c035180266e453454e494f524245414d000000000000000000000000000000000000000000000000010c0014000003e80096001607d0", strlen("0101069628d227649cc2823d94647ad08ea34ad24e7eea95b7a0249bc83e73efefa6072cab1841f0ef3e6d7f4c4140b7b1b13049eb0d85941d7d7bd30c921bfd550300078000000802aaa260b1496f0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c035180266e453454e494f524245414d000000000000000000000000000000000000000000000000010c0014000003e80096001607d0"));
return NULL;
}
int main(int argc, char *argv[])
{
struct node node;
bool only_missing_tlv;
u8 *ann;
common_setup(argv[0]);
/* No TLV checks */
node.bcast.index = 1;
ann = tal_hexdata(tmpctx, "01017d49b51b7d3772636c09901df78c81faa1a7f045e329366ad779ecbaf0cc07f764d8ffd3596ef6802fd0e4c5c180c74fb3dfb14aae493ed48d35a3df75c20eca00078000000802aaa260b14569022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59022d2253494c454e544152544953542d3236352d67373833393533312d6d6f646465640000", strlen("01017d49b51b7d3772636c09901df78c81faa1a7f045e329366ad779ecbaf0cc07f764d8ffd3596ef6802fd0e4c5c180c74fb3dfb14aae493ed48d35a3df75c20eca00078000000802aaa260b14569022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59022d2253494c454e544152544953542d3236352d67373833393533312d6d6f646465640000"));
assert(!nannounce_different(NULL, &node, ann, &only_missing_tlv));
assert(!only_missing_tlv);
node.bcast.index = 0;
assert(nannounce_different(NULL, &node, ann, &only_missing_tlv));
assert(!only_missing_tlv);
/* TLV checks */
ann = tal_hexdata(tmpctx, "0101069628d227649cc2823d94647ad08ea34ad24e7eea95b7a0249bc83e73efefa6072cab1841f0ef3e6d7f4c4140b7b1b13049eb0d85941d7d7bd30c921bfd550300078000000802aaa260b1496f0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c035180266e453454e494f524245414d000000000000000000000000000000000000000000000000010c0014000003e80096001607d0", strlen("0101069628d227649cc2823d94647ad08ea34ad24e7eea95b7a0249bc83e73efefa6072cab1841f0ef3e6d7f4c4140b7b1b13049eb0d85941d7d7bd30c921bfd550300078000000802aaa260b1496f0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c035180266e453454e494f524245414d000000000000000000000000000000000000000000000000010c0014000003e80096001607d0"));
node.bcast.index = 2;
assert(!nannounce_different(NULL, &node, ann, &only_missing_tlv));
assert(!only_missing_tlv);
/* Tweak the last, check that it fails */
node.bcast.index = 2;
ann[tal_count(ann) - 1]++;
assert(nannounce_different(NULL, &node, ann, &only_missing_tlv));
assert(only_missing_tlv);
common_shutdown();
return 0;
}

View File

@ -70,7 +70,8 @@ void memleak_remove_intmap_(struct htable *memtable UNNEEDED, const struct intma
/* Generated stub for nannounce_different */
bool nannounce_different(struct gossip_store *gs UNNEEDED,
const struct node *node UNNEEDED,
const u8 *nannounce UNNEEDED)
const u8 *nannounce UNNEEDED,
bool *only_missing_tlv UNNEEDED)
{ fprintf(stderr, "nannounce_different called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)