mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-14 11:34:22 +01:00
gossipd: check consistency.
This is a hack to check that our gossip state is consistent on every insert and delete. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
da55d3c0ff
commit
5d6a9f3fb0
@@ -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 <common/pseudorand.h>
|
||||
#include <common/status.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <gossipd/broadcast.h>
|
||||
#include <wire/gen_peer_wire.h>
|
||||
|
||||
struct queued_message {
|
||||
/* 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);
|
||||
assert(q->payload == payload);
|
||||
broadcast_state_check(bstate, "broadcast_del");
|
||||
}
|
||||
|
||||
static void destroy_queued_message(struct queued_message *msg,
|
||||
@@ -55,6 +65,7 @@ u64 insert_broadcast(struct broadcast_state *bstate,
|
||||
/* Free payload, free index. */
|
||||
new_queued_message(payload, bstate, payload, timestamp,
|
||||
bstate->next_index);
|
||||
broadcast_state_check(bstate, "insert_broadcast");
|
||||
return bstate->next_index++;
|
||||
}
|
||||
|
||||
@@ -71,3 +82,88 @@ const u8 *next_broadcast(struct broadcast_state *bstate,
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -29,4 +29,9 @@ void broadcast_del(struct broadcast_state *bstate, u64 index, const u8 *payload)
|
||||
const u8 *next_broadcast(struct broadcast_state *bstate,
|
||||
u32 timestamp_min, u32 timestamp_max,
|
||||
u64 *last_index);
|
||||
|
||||
/* Returns b if all OK, otherwise aborts if abortstr non-NULL, otherwise returns
|
||||
* NULL. */
|
||||
struct broadcast_state *broadcast_state_check(struct broadcast_state *b,
|
||||
const char *abortstr);
|
||||
#endif /* LIGHTNING_GOSSIPD_BROADCAST_H */
|
||||
|
||||
Reference in New Issue
Block a user