|
@ -1,5 +1,14 @@ |
|
|
|
|
|
#include <bitcoin/block.h> |
|
|
|
|
|
#include <bitcoin/pubkey.h> |
|
|
|
|
|
#include <bitcoin/short_channel_id.h> |
|
|
|
|
|
#include <ccan/crypto/siphash24/siphash24.h> |
|
|
|
|
|
#include <ccan/htable/htable_type.h> |
|
|
#include <ccan/mem/mem.h> |
|
|
#include <ccan/mem/mem.h> |
|
|
|
|
|
#include <common/pseudorand.h> |
|
|
|
|
|
#include <common/status.h> |
|
|
|
|
|
#include <common/type_to_string.h> |
|
|
#include <gossipd/broadcast.h> |
|
|
#include <gossipd/broadcast.h> |
|
|
|
|
|
#include <wire/gen_peer_wire.h> |
|
|
|
|
|
|
|
|
struct queued_message { |
|
|
struct queued_message { |
|
|
/* Broadcast index. */ |
|
|
/* Broadcast index. */ |
|
@ -25,6 +34,7 @@ void broadcast_del(struct broadcast_state *bstate, u64 index, const u8 *payload) |
|
|
{ |
|
|
{ |
|
|
const struct queued_message *q = uintmap_del(&bstate->broadcasts, index); |
|
|
const struct queued_message *q = uintmap_del(&bstate->broadcasts, index); |
|
|
assert(q->payload == payload); |
|
|
assert(q->payload == payload); |
|
|
|
|
|
broadcast_state_check(bstate, "broadcast_del"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void destroy_queued_message(struct queued_message *msg, |
|
|
static void destroy_queued_message(struct queued_message *msg, |
|
@ -55,6 +65,7 @@ u64 insert_broadcast(struct broadcast_state *bstate, |
|
|
/* Free payload, free index. */ |
|
|
/* Free payload, free index. */ |
|
|
new_queued_message(payload, bstate, payload, timestamp, |
|
|
new_queued_message(payload, bstate, payload, timestamp, |
|
|
bstate->next_index); |
|
|
bstate->next_index); |
|
|
|
|
|
broadcast_state_check(bstate, "insert_broadcast"); |
|
|
return bstate->next_index++; |
|
|
return bstate->next_index++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -71,3 +82,88 @@ const u8 *next_broadcast(struct broadcast_state *bstate, |
|
|
} |
|
|
} |
|
|
return NULL; |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const struct pubkey * |
|
|
|
|
|
pubkey_keyof(const struct pubkey *pk) |
|
|
|
|
|
{ |
|
|
|
|
|
return pk; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static size_t pubkey_hash(const struct pubkey *id) |
|
|
|
|
|
{ |
|
|
|
|
|
return siphash24(siphash_seed(), id, sizeof(*id)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HTABLE_DEFINE_TYPE(struct pubkey, |
|
|
|
|
|
pubkey_keyof, |
|
|
|
|
|
pubkey_hash, |
|
|
|
|
|
pubkey_eq, |
|
|
|
|
|
pubkey_set); |
|
|
|
|
|
|
|
|
|
|
|
static void *corrupt(const char *abortstr, const char *problem, |
|
|
|
|
|
const struct short_channel_id *scid, |
|
|
|
|
|
const struct pubkey *node_id) |
|
|
|
|
|
{ |
|
|
|
|
|
status_broken("Gossip corrupt %s %s: %s", |
|
|
|
|
|
problem, abortstr ? abortstr : "", |
|
|
|
|
|
scid ? type_to_string(tmpctx, |
|
|
|
|
|
struct short_channel_id, |
|
|
|
|
|
scid) |
|
|
|
|
|
: type_to_string(tmpctx, struct pubkey, node_id)); |
|
|
|
|
|
if (abortstr) |
|
|
|
|
|
abort(); |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct broadcast_state *broadcast_state_check(struct broadcast_state *b, |
|
|
|
|
|
const char *abortstr) |
|
|
|
|
|
{ |
|
|
|
|
|
secp256k1_ecdsa_signature sig; |
|
|
|
|
|
const u8 *msg; |
|
|
|
|
|
u8 *features, *addresses, color[3], alias[32]; |
|
|
|
|
|
struct bitcoin_blkid chain_hash; |
|
|
|
|
|
struct short_channel_id scid; |
|
|
|
|
|
struct pubkey node_id_1, node_id_2, bitcoin_key; |
|
|
|
|
|
u32 timestamp, fees; |
|
|
|
|
|
u16 flags, expiry; |
|
|
|
|
|
u64 index = 0, htlc_minimum_msat; |
|
|
|
|
|
struct pubkey_set pubkeys; |
|
|
|
|
|
/* We actually only need a set, not a map. */ |
|
|
|
|
|
UINTMAP(u64 *) channels; |
|
|
|
|
|
|
|
|
|
|
|
pubkey_set_init(&pubkeys); |
|
|
|
|
|
uintmap_init(&channels); |
|
|
|
|
|
|
|
|
|
|
|
while ((msg = next_broadcast(b, 0, UINT32_MAX, &index)) != NULL) { |
|
|
|
|
|
if (fromwire_channel_announcement(tmpctx, msg, &sig, &sig, &sig, |
|
|
|
|
|
&sig, &features, &chain_hash, |
|
|
|
|
|
&scid, &node_id_1, &node_id_2, |
|
|
|
|
|
&bitcoin_key, &bitcoin_key)) { |
|
|
|
|
|
if (!uintmap_add(&channels, scid.u64, &index)) |
|
|
|
|
|
return corrupt(abortstr, "announced twice", |
|
|
|
|
|
&scid, NULL); |
|
|
|
|
|
pubkey_set_add(&pubkeys, &node_id_1); |
|
|
|
|
|
pubkey_set_add(&pubkeys, &node_id_2); |
|
|
|
|
|
} else if (fromwire_channel_update(msg, &sig, &chain_hash, |
|
|
|
|
|
&scid, ×tamp, &flags, |
|
|
|
|
|
&expiry, &htlc_minimum_msat, |
|
|
|
|
|
&fees, &fees)) { |
|
|
|
|
|
if (!uintmap_get(&channels, scid.u64)) |
|
|
|
|
|
return corrupt(abortstr, |
|
|
|
|
|
"updated before announce", |
|
|
|
|
|
&scid, NULL); |
|
|
|
|
|
} else if (fromwire_node_announcement(tmpctx, msg, |
|
|
|
|
|
&sig, &features, |
|
|
|
|
|
×tamp, |
|
|
|
|
|
&node_id_1, color, alias, |
|
|
|
|
|
&addresses)) |
|
|
|
|
|
if (!uintmap_get(&channels, scid.u64)) |
|
|
|
|
|
return corrupt(abortstr, |
|
|
|
|
|
"node announced before channel", |
|
|
|
|
|
NULL, &node_id_1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pubkey_set_clear(&pubkeys); |
|
|
|
|
|
uintmap_clear(&channels); |
|
|
|
|
|
return b; |
|
|
|
|
|
} |
|
|