mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
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:
parent
49bae2a873
commit
55f5a5caba
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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)",
|
||||
|
@ -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,
|
||||
|
147
gossipd/test/run-check_node_announcement.c
Normal file
147
gossipd/test/run-check_node_announcement.c
Normal 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;
|
||||
}
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user