gossmap: check checksums.

We assume if it's incorrect, we simply need to wait.  If this proves incorrect,
we will see a stream of BROKEN log messages.

To measure the performance impact, I timed
tests/test_askrene.py::test_real_biases on my laptop.

	Before: 194.52s
	After: 202.81s

So it's marginal.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2025-02-10 12:18:49 +10:30
committed by Alex Myers
parent 307dbe3e62
commit 4b5e5b27ae

View File

@@ -1,5 +1,6 @@
#include "config.h"
#include <assert.h>
#include <ccan/crc32c/crc32c.h>
#include <ccan/crypto/siphash24/siphash24.h>
#include <ccan/err/err.h>
#include <ccan/htable/htable_type.h>
@@ -658,15 +659,17 @@ static bool map_catchup(struct gossmap *map)
{
size_t reclen;
bool changed = false;
u8 msgbuf[65535];
for (; map->map_end + sizeof(struct gossip_hdr) < map->map_size;
map->map_end += reclen) {
struct gossip_hdr ghdr;
u64 off;
u16 type, flags;
u16 msglen, type, flags;
map_copy(map, map->map_end, &ghdr, sizeof(ghdr));
reclen = be16_to_cpu(ghdr.len) + sizeof(ghdr);
msglen = be16_to_cpu(ghdr.len);
reclen = msglen + sizeof(ghdr);
flags = be16_to_cpu(ghdr.flags);
if (flags & GOSSIP_STORE_DELETED_BIT)
@@ -677,11 +680,31 @@ static bool map_catchup(struct gossmap *map)
break;
/* FIXME: In corruption, we can see zeroes here: don't crash. */
if (be16_to_cpu(ghdr.len) < sizeof(be16))
break;
if (msglen < sizeof(be16)) {
map->logcb(map->cbarg,
LOG_BROKEN,
"Truncated gossmap record @%"PRIu64
"/%"PRIu64" (len %zu): waiting",
map->map_end, map->map_size, msglen);
break;
}
off = map->map_end + sizeof(ghdr);
type = map_be16(map, off);
map_copy(map, off, msgbuf, msglen);
if (be32_to_cpu(ghdr.crc)
!= crc32c(be32_to_cpu(ghdr.timestamp), msgbuf, msglen)) {
map->logcb(map->cbarg,
LOG_BROKEN,
"Bad checksum on gossmap record @%"PRIu64
"/%"PRIu64" should be %u (%s): waiting",
map->map_end, map->map_size,
be32_to_cpu(ghdr.crc),
tal_hexstr(tmpctx, msgbuf, msglen));
break;
}
if (type == WIRE_CHANNEL_ANNOUNCEMENT) {
/* Don't read yet if amount field is not there! */
if (!add_channel(map, off, be16_to_cpu(ghdr.len)))