core-lightning/common/per_peer_state.c
Rusty Russell 147eaced2e developer: consolidiate gossip timing options into one --dev-fast-gossip.
It's generally clearer to have simple hardcoded numbers with an
#if DEVELOPER around it, than apparent variables which aren't, really.

Interestingly, our pruning test was always kinda broken: we have to pass
two cycles, since l2 will refresh the channel once to avoid pruning.

Do the more obvious thing, and cut the network in half and check that
l1 and l3 time out.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-09-20 06:55:00 +00:00

140 lines
3.7 KiB
C

#include <assert.h>
#include <ccan/fdpass/fdpass.h>
#include <common/gossip_rcvd_filter.h>
#include <common/per_peer_state.h>
#include <gossipd/gossip_constants.h>
#include <unistd.h>
#include <wire/wire.h>
bool dev_fast_gossip = false;
static void destroy_per_peer_state(struct per_peer_state *pps)
{
if (pps->peer_fd != -1)
close(pps->peer_fd);
if (pps->gossip_fd != -1)
close(pps->gossip_fd);
if (pps->gossip_store_fd != -1)
close(pps->gossip_store_fd);
}
struct per_peer_state *new_per_peer_state(const tal_t *ctx,
const struct crypto_state *cs)
{
struct per_peer_state *pps = tal(ctx, struct per_peer_state);
pps->cs = *cs;
pps->gs = NULL;
pps->peer_fd = pps->gossip_fd = pps->gossip_store_fd = -1;
pps->grf = new_gossip_rcvd_filter(pps);
tal_add_destructor(pps, destroy_per_peer_state);
return pps;
}
void per_peer_state_set_fds(struct per_peer_state *pps,
int peer_fd, int gossip_fd, int gossip_store_fd)
{
assert(pps->peer_fd == -1);
assert(pps->gossip_fd == -1);
assert(pps->gossip_store_fd == -1);
pps->peer_fd = peer_fd;
pps->gossip_fd = gossip_fd;
pps->gossip_store_fd = gossip_store_fd;
}
void per_peer_state_set_fds_arr(struct per_peer_state *pps, const int *fds)
{
/* We expect 3 fds. */
assert(tal_count(fds) == 3);
per_peer_state_set_fds(pps, fds[0], fds[1], fds[2]);
}
void towire_gossip_state(u8 **pptr, const struct gossip_state *gs)
{
towire_u64(pptr, gs->next_gossip.ts.tv_sec);
towire_u64(pptr, gs->next_gossip.ts.tv_nsec);
towire_u32(pptr, gs->timestamp_min);
towire_u32(pptr, gs->timestamp_max);
}
void fromwire_gossip_state(const u8 **cursor, size_t *max,
struct gossip_state *gs)
{
gs->next_gossip.ts.tv_sec = fromwire_u64(cursor, max);
gs->next_gossip.ts.tv_nsec = fromwire_u64(cursor, max);
gs->timestamp_min = fromwire_u32(cursor, max);
gs->timestamp_max = fromwire_u32(cursor, max);
}
void towire_per_peer_state(u8 **pptr, const struct per_peer_state *pps)
{
towire_crypto_state(pptr, &pps->cs);
towire_bool(pptr, pps->gs != NULL);
if (pps->gs)
towire_gossip_state(pptr, pps->gs);
/* We don't pass the gossip_rcvd_filter: it's merely an optimization */
}
void per_peer_state_fdpass_send(int fd, const struct per_peer_state *pps)
{
assert(pps->peer_fd != -1);
assert(pps->gossip_fd != -1);
assert(pps->gossip_store_fd != -1);
fdpass_send(fd, pps->peer_fd);
fdpass_send(fd, pps->gossip_fd);
fdpass_send(fd, pps->gossip_store_fd);
}
struct per_peer_state *fromwire_per_peer_state(const tal_t *ctx,
const u8 **cursor, size_t *max)
{
struct crypto_state cs;
struct per_peer_state *pps;
fromwire_crypto_state(cursor, max, &cs);
pps = new_per_peer_state(ctx, &cs);
if (fromwire_bool(cursor, max)) {
pps->gs = tal(pps, struct gossip_state);
fromwire_gossip_state(cursor, max, pps->gs);
}
return pps;
}
/* FIXME: Put in ccan/time */
/* Is a after b? */
static inline bool timemono_after(struct timemono a, struct timemono b)
{
return time_greater_(a.ts, b.ts);
}
bool time_to_next_gossip(const struct per_peer_state *pps,
struct timerel *t)
{
if (!pps->gs)
return false;
struct timemono now = time_mono();
if (timemono_after(now, pps->gs->next_gossip))
*t = time_from_sec(0);
else
*t = timemono_between(pps->gs->next_gossip, now);
return true;
}
/* BOLT #7:
*
* A node:
*...
* - SHOULD flush outgoing gossip messages once every 60 seconds,
* independently of the arrival times of the messages.
* - Note: this results in staggered announcements that are unique
* (not duplicated).
*/
void per_peer_state_reset_gossip_timer(struct per_peer_state *pps)
{
struct timerel t = time_from_sec(GOSSIP_FLUSH_INTERVAL(dev_fast_gossip));
pps->gs->next_gossip = timemono_add(time_mono(), t);
gossip_rcvd_filter_age(pps->grf);
}