Browse Source
This clarifies things a fair bit: we simply add and remove from the gossip_store directly. Before this series: (--disable-developer, -Og) store_load_msec:20669-20902(20822.2+/-82) vsz_kb:439704-439712(439706+/-3.2) listnodes_sec:0.890000-1.000000(0.92+/-0.04) listchannels_sec:11.960000-13.380000(12.576+/-0.49) routing_sec:3.070000-5.970000(4.814+/-1.2) peer_write_all_sec:28.490000-30.580000(29.532+/-0.78) After: (--disable-developer, -Og) store_load_msec:19722-20124(19921.6+/-1.4e+02) vsz_kb:288320 listnodes_sec:0.860000-0.980000(0.912+/-0.056) listchannels_sec:10.790000-12.260000(11.65+/-0.5) routing_sec:2.540000-4.950000(4.262+/-0.88) peer_write_all_sec:17.570000-19.500000(18.048+/-0.73) Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>htlc_accepted_hook
Rusty Russell
6 years ago
12 changed files with 86 additions and 408 deletions
@ -1,227 +0,0 @@ |
|||||
#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/memleak.h> |
|
||||
#include <common/pseudorand.h> |
|
||||
#include <common/status.h> |
|
||||
#include <common/type_to_string.h> |
|
||||
#include <errno.h> |
|
||||
#include <gossipd/broadcast.h> |
|
||||
#include <gossipd/gossip_store.h> |
|
||||
#include <wire/gen_peer_wire.h> |
|
||||
|
|
||||
static void destroy_broadcast_state(struct broadcast_state *bstate) |
|
||||
{ |
|
||||
uintmap_clear(&bstate->broadcasts); |
|
||||
} |
|
||||
|
|
||||
struct broadcast_state *new_broadcast_state(struct routing_state *rstate, |
|
||||
struct gossip_store *gs, |
|
||||
struct list_head *peers) |
|
||||
{ |
|
||||
struct broadcast_state *bstate = tal(rstate, struct broadcast_state); |
|
||||
uintmap_init(&bstate->broadcasts); |
|
||||
bstate->count = 0; |
|
||||
bstate->gs = gs; |
|
||||
bstate->peers = peers; |
|
||||
tal_add_destructor(bstate, destroy_broadcast_state); |
|
||||
return bstate; |
|
||||
} |
|
||||
|
|
||||
void broadcast_del(struct broadcast_state *bstate, |
|
||||
struct broadcastable *bcast) |
|
||||
{ |
|
||||
const struct broadcastable *b |
|
||||
= uintmap_del(&bstate->broadcasts, bcast->index); |
|
||||
if (b != NULL) { |
|
||||
assert(b == bcast); |
|
||||
bstate->count--; |
|
||||
broadcast_state_check(bstate, "broadcast_del"); |
|
||||
} |
|
||||
bcast->index = 0; |
|
||||
} |
|
||||
|
|
||||
static void add_broadcast(struct broadcast_state *bstate, |
|
||||
struct broadcastable *bcast) |
|
||||
{ |
|
||||
assert(bcast); |
|
||||
assert(bcast->index); |
|
||||
if (!uintmap_add(&bstate->broadcasts, bcast->index, bcast)) |
|
||||
abort(); |
|
||||
bstate->count++; |
|
||||
} |
|
||||
|
|
||||
void insert_broadcast_nostore(struct broadcast_state *bstate, |
|
||||
struct broadcastable *bcast) |
|
||||
{ |
|
||||
add_broadcast(bstate, bcast); |
|
||||
broadcast_state_check(bstate, "insert_broadcast"); |
|
||||
} |
|
||||
|
|
||||
void insert_broadcast(struct broadcast_state **bstate, |
|
||||
const u8 *msg, |
|
||||
const u8 *addendum, |
|
||||
struct broadcastable *bcast) |
|
||||
{ |
|
||||
u32 offset; |
|
||||
|
|
||||
assert(bcast->timestamp); |
|
||||
/* If we're loading from the store, we already have index */ |
|
||||
if (!bcast->index) { |
|
||||
u64 idx; |
|
||||
|
|
||||
bcast->index = idx = gossip_store_add((*bstate)->gs, msg, |
|
||||
bcast->timestamp, |
|
||||
addendum); |
|
||||
if (!idx) |
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR, |
|
||||
"Could not add to gossip store: %s", |
|
||||
strerror(errno)); |
|
||||
/* We assume we can fit in 32 bits for now! */ |
|
||||
assert(idx == bcast->index); |
|
||||
} |
|
||||
|
|
||||
insert_broadcast_nostore(*bstate, bcast); |
|
||||
|
|
||||
/* If it compacts, it replaces *bstate */ |
|
||||
if (gossip_store_maybe_compact((*bstate)->gs, bstate, &offset)) |
|
||||
update_peers_broadcast_index((*bstate)->peers, offset); |
|
||||
} |
|
||||
|
|
||||
struct broadcastable *next_broadcast_raw(struct broadcast_state *bstate, |
|
||||
u32 *last_index) |
|
||||
{ |
|
||||
struct broadcastable *b; |
|
||||
u64 idx = *last_index; |
|
||||
|
|
||||
b = uintmap_after(&bstate->broadcasts, &idx); |
|
||||
if (!b) |
|
||||
return NULL; |
|
||||
/* Assert no overflow */ |
|
||||
*last_index = idx; |
|
||||
assert(*last_index == idx); |
|
||||
return b; |
|
||||
} |
|
||||
|
|
||||
struct broadcastable *next_broadcast(struct broadcast_state *bstate, |
|
||||
u32 timestamp_min, u32 timestamp_max, |
|
||||
u32 *last_index) |
|
||||
{ |
|
||||
struct broadcastable *b; |
|
||||
|
|
||||
while ((b = next_broadcast_raw(bstate, last_index)) != NULL) { |
|
||||
if (b->timestamp >= timestamp_min |
|
||||
&& b->timestamp <= timestamp_max) { |
|
||||
return b; |
|
||||
} |
|
||||
} |
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
u64 broadcast_final_index(const struct broadcast_state *bstate) |
|
||||
{ |
|
||||
u64 idx; |
|
||||
|
|
||||
if (!uintmap_last(&bstate->broadcasts, &idx)) |
|
||||
return 0; |
|
||||
return idx; |
|
||||
} |
|
||||
|
|
||||
#ifdef PEDANTIC |
|
||||
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; |
|
||||
u32 index = 0; |
|
||||
u64 htlc_minimum_msat; |
|
||||
struct pubkey_set pubkeys; |
|
||||
struct broadcastable *bcast; |
|
||||
/* We actually only need a set, not a map. */ |
|
||||
UINTMAP(u64 *) channels; |
|
||||
|
|
||||
pubkey_set_init(&pubkeys); |
|
||||
uintmap_init(&channels); |
|
||||
|
|
||||
while ((bcast = next_broadcast_raw(b, &index)) != NULL) { |
|
||||
msg = gossip_store_get(b, b->gs, b->index); |
|
||||
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 (!pubkey_set_get(&pubkeys, &node_id_1)) |
|
||||
return corrupt(abortstr, |
|
||||
"node announced before channel", |
|
||||
NULL, &node_id_1); |
|
||||
} |
|
||||
|
|
||||
pubkey_set_clear(&pubkeys); |
|
||||
uintmap_clear(&channels); |
|
||||
return b; |
|
||||
} |
|
||||
#else |
|
||||
struct broadcast_state *broadcast_state_check(struct broadcast_state *b, |
|
||||
const char *abortstr UNUSED) |
|
||||
{ |
|
||||
return b; |
|
||||
} |
|
||||
#endif |
|
Loading…
Reference in new issue