mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-15 20:09:18 +01:00
gossipd: new routines to support gossmap compatibility.
gossip_store_del - takes a gossmap-style offset-of-msg not offset-of-hdr. gossip_store_flag: set an arbitrary flag on a gossip_store hdr. gossip_store_get_timestamp/gossip_store_set_timestamp: access gossip_store hdr. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
37ccca5d69
commit
870c996628
3 changed files with 130 additions and 27 deletions
|
@ -667,7 +667,7 @@ void gossip_store_mark_dying(struct gossip_store *gs,
|
|||
}
|
||||
|
||||
/* Returns index of following entry. */
|
||||
static u32 delete_by_index(struct gossip_store *gs, u32 index, int type)
|
||||
static u32 flag_by_index(struct gossip_store *gs, u32 index, int flag, int type)
|
||||
{
|
||||
struct {
|
||||
beint16_t beflags;
|
||||
|
@ -682,28 +682,28 @@ static u32 delete_by_index(struct gossip_store *gs, u32 index, int type)
|
|||
|
||||
/* FIXME: debugging a gs->len overrun issue reported in #6270 */
|
||||
if (pread(gs->fd, &hdr, sizeof(hdr), index) != sizeof(hdr)) {
|
||||
status_broken("gossip_store overrun during delete @%u type: %i"
|
||||
" gs->len: %"PRIu64, index, type, gs->len);
|
||||
status_broken("gossip_store pread fail during flag %u @%u type: %i"
|
||||
" gs->len: %"PRIu64, flag, index, type, gs->len);
|
||||
return index;
|
||||
}
|
||||
if (index + sizeof(struct gossip_hdr) +
|
||||
be16_to_cpu(hdr.belen) > gs->len) {
|
||||
status_broken("gossip_store overrun during delete @%u type: %i"
|
||||
" gs->len: %"PRIu64, index, type, gs->len);
|
||||
status_broken("gossip_store overrun during flag-%u @%u type: %i"
|
||||
" gs->len: %"PRIu64, flag, index, type, gs->len);
|
||||
return index;
|
||||
}
|
||||
|
||||
const u8 *msg = gossip_store_get(tmpctx, gs, index);
|
||||
if(fromwire_peektype(msg) != type) {
|
||||
status_broken("asked to delete type %i @%u but store contains "
|
||||
status_broken("asked to flag-%u type %i @%u but store contains "
|
||||
"%i (gs->len=%"PRIu64"): %s",
|
||||
type, index, fromwire_peektype(msg),
|
||||
flag, type, index, fromwire_peektype(msg),
|
||||
gs->len, tal_hex(tmpctx, msg));
|
||||
return index;
|
||||
}
|
||||
|
||||
assert((be16_to_cpu(hdr.beflags) & GOSSIP_STORE_DELETED_BIT) == 0);
|
||||
hdr.beflags |= cpu_to_be16(GOSSIP_STORE_DELETED_BIT);
|
||||
assert((be16_to_cpu(hdr.beflags) & flag) == 0);
|
||||
hdr.beflags |= cpu_to_be16(flag);
|
||||
if (pwrite(gs->fd, &hdr.beflags, sizeof(hdr.beflags), index) != sizeof(hdr.beflags))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Failed writing flags to delete @%u: %s",
|
||||
|
@ -713,24 +713,45 @@ static u32 delete_by_index(struct gossip_store *gs, u32 index, int type)
|
|||
return index + sizeof(struct gossip_hdr) + be16_to_cpu(hdr.belen);
|
||||
}
|
||||
|
||||
void gossip_store_del(struct gossip_store *gs,
|
||||
u64 offset,
|
||||
int type)
|
||||
{
|
||||
u32 next_index;
|
||||
|
||||
assert(offset > sizeof(struct gossip_hdr));
|
||||
next_index = flag_by_index(gs, offset - sizeof(struct gossip_hdr),
|
||||
GOSSIP_STORE_DELETED_BIT,
|
||||
type);
|
||||
|
||||
/* For a channel_announcement, we need to delete amount too */
|
||||
if (type == WIRE_CHANNEL_ANNOUNCEMENT)
|
||||
flag_by_index(gs, next_index,
|
||||
GOSSIP_STORE_DELETED_BIT,
|
||||
WIRE_GOSSIP_STORE_CHANNEL_AMOUNT);
|
||||
}
|
||||
|
||||
void gossip_store_flag(struct gossip_store *gs,
|
||||
u64 offset,
|
||||
u16 flag,
|
||||
int type)
|
||||
{
|
||||
assert(offset > sizeof(struct gossip_hdr));
|
||||
|
||||
flag_by_index(gs, offset - sizeof(struct gossip_hdr), flag, type);
|
||||
}
|
||||
|
||||
void gossip_store_delete(struct gossip_store *gs,
|
||||
struct broadcastable *bcast,
|
||||
int type)
|
||||
{
|
||||
u32 next_index;
|
||||
|
||||
if (!bcast->index)
|
||||
return;
|
||||
|
||||
next_index = delete_by_index(gs, bcast->index, type);
|
||||
gossip_store_del(gs, bcast->index + sizeof(struct gossip_hdr), type);
|
||||
|
||||
/* Reset index. */
|
||||
bcast->index = 0;
|
||||
|
||||
/* For a channel_announcement, we need to delete amount too */
|
||||
if (type == WIRE_CHANNEL_ANNOUNCEMENT)
|
||||
delete_by_index(gs, next_index,
|
||||
WIRE_GOSSIP_STORE_CHANNEL_AMOUNT);
|
||||
}
|
||||
|
||||
void gossip_store_mark_channel_deleted(struct gossip_store *gs,
|
||||
|
@ -786,11 +807,26 @@ void gossip_store_mark_cupdate_zombie(struct gossip_store *gs,
|
|||
mark_zombie(gs, bcast, WIRE_CHANNEL_UPDATE);
|
||||
}
|
||||
|
||||
const u8 *gossip_store_get(const tal_t *ctx,
|
||||
struct gossip_store *gs,
|
||||
u64 offset)
|
||||
u32 gossip_store_get_timestamp(struct gossip_store *gs, u64 offset)
|
||||
{
|
||||
struct gossip_hdr hdr;
|
||||
|
||||
assert(offset > sizeof(struct gossip_hdr));
|
||||
|
||||
if (pread(gs->fd, &hdr, sizeof(hdr), offset - sizeof(hdr)) != sizeof(hdr)) {
|
||||
status_broken("gossip_store overrun during get_timestamp @%"PRIu64
|
||||
" gs->len: %"PRIu64, offset, gs->len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return be32_to_cpu(hdr.timestamp);
|
||||
}
|
||||
|
||||
static const u8 *gossip_store_get_with_hdr(const tal_t *ctx,
|
||||
struct gossip_store *gs,
|
||||
u64 offset,
|
||||
struct gossip_hdr *hdr)
|
||||
{
|
||||
u32 msglen, checksum;
|
||||
u8 *msg;
|
||||
|
||||
|
@ -798,28 +834,28 @@ const u8 *gossip_store_get(const tal_t *ctx,
|
|||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"gossip_store: can't access offset %"PRIu64,
|
||||
offset);
|
||||
if (pread(gs->fd, &hdr, sizeof(hdr), offset) != sizeof(hdr)) {
|
||||
if (pread(gs->fd, hdr, sizeof(*hdr), offset) != sizeof(*hdr)) {
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"gossip_store: can't read hdr offset %"PRIu64
|
||||
"/%"PRIu64": %s",
|
||||
offset, gs->len, strerror(errno));
|
||||
}
|
||||
|
||||
if (be16_to_cpu(hdr.flags) & GOSSIP_STORE_DELETED_BIT)
|
||||
if (be16_to_cpu(hdr->flags) & GOSSIP_STORE_DELETED_BIT)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"gossip_store: get delete entry offset %"PRIu64
|
||||
"/%"PRIu64"",
|
||||
offset, gs->len);
|
||||
|
||||
msglen = be16_to_cpu(hdr.len);
|
||||
checksum = be32_to_cpu(hdr.crc);
|
||||
msglen = be16_to_cpu(hdr->len);
|
||||
checksum = be32_to_cpu(hdr->crc);
|
||||
msg = tal_arr(ctx, u8, msglen);
|
||||
if (pread(gs->fd, msg, msglen, offset + sizeof(hdr)) != msglen)
|
||||
if (pread(gs->fd, msg, msglen, offset + sizeof(*hdr)) != msglen)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"gossip_store: can't read len %u offset %"PRIu64
|
||||
"/%"PRIu64, msglen, offset, gs->len);
|
||||
|
||||
if (checksum != crc32c(be32_to_cpu(hdr.timestamp), msg, msglen))
|
||||
if (checksum != crc32c(be32_to_cpu(hdr->timestamp), msg, msglen))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"gossip_store: bad checksum offset %"PRIu64": %s",
|
||||
offset, tal_hex(tmpctx, msg));
|
||||
|
@ -827,6 +863,38 @@ const u8 *gossip_store_get(const tal_t *ctx,
|
|||
return msg;
|
||||
}
|
||||
|
||||
void gossip_store_set_timestamp(struct gossip_store *gs, u64 offset, u32 timestamp)
|
||||
{
|
||||
struct gossip_hdr hdr;
|
||||
const u8 *msg;
|
||||
|
||||
assert(offset > sizeof(struct gossip_hdr));
|
||||
msg = gossip_store_get_with_hdr(tmpctx, gs, offset - sizeof(hdr), &hdr);
|
||||
if (pread(gs->fd, &hdr, sizeof(hdr), offset - sizeof(hdr)) != sizeof(hdr)) {
|
||||
status_broken("gossip_store overrun during set_timestamp @%"PRIu64
|
||||
" gs->len: %"PRIu64, offset, gs->len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Change timestamp and crc */
|
||||
hdr.timestamp = cpu_to_be32(timestamp);
|
||||
hdr.crc = cpu_to_be32(crc32c(timestamp, msg, tal_bytelen(msg)));
|
||||
|
||||
if (pwrite(gs->fd, &hdr, sizeof(hdr), offset - sizeof(hdr)) != sizeof(hdr))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Failed writing header to re-timestamp @%"PRIu64": %s",
|
||||
offset, strerror(errno));
|
||||
}
|
||||
|
||||
const u8 *gossip_store_get(const tal_t *ctx,
|
||||
struct gossip_store *gs,
|
||||
u64 offset)
|
||||
{
|
||||
struct gossip_hdr hdr;
|
||||
|
||||
return gossip_store_get_with_hdr(ctx, gs, offset, &hdr);
|
||||
}
|
||||
|
||||
int gossip_store_readonly_fd(struct gossip_store *gs)
|
||||
{
|
||||
int fd = open(GOSSIP_STORE_FILENAME, O_RDONLY);
|
||||
|
|
|
@ -53,6 +53,27 @@ void gossip_store_delete(struct gossip_store *gs,
|
|||
struct broadcastable *bcast,
|
||||
int type);
|
||||
|
||||
/**
|
||||
* Delete the record at this offset (offset is that of
|
||||
* record, not header, unlike bcast->index!).
|
||||
*
|
||||
* In developer mode, checks that type is correct.
|
||||
*/
|
||||
void gossip_store_del(struct gossip_store *gs,
|
||||
u64 offset,
|
||||
int type);
|
||||
|
||||
/**
|
||||
* Add a flag the record at this offset (offset is that of
|
||||
* record, not header, unlike bcast->index!).
|
||||
*
|
||||
* In developer mode, checks that type is correct.
|
||||
*/
|
||||
void gossip_store_flag(struct gossip_store *gs,
|
||||
u64 offset,
|
||||
u16 flag,
|
||||
int type);
|
||||
|
||||
/**
|
||||
* Mark that the channel is about to be deleted, for convenience of
|
||||
* others mapping the gossip_store.
|
||||
|
@ -91,6 +112,20 @@ const u8 *gossip_store_get(const tal_t *ctx,
|
|||
struct gossip_store *gs,
|
||||
u64 offset);
|
||||
|
||||
/**
|
||||
* Direct store accessor: get timestamp header for a record.
|
||||
*
|
||||
* Offset is *after* the header.
|
||||
*/
|
||||
u32 gossip_store_get_timestamp(struct gossip_store *gs, u64 offset);
|
||||
|
||||
/**
|
||||
* Direct store accessor: set timestamp header for a record.
|
||||
*
|
||||
* Offset is *after* the header.
|
||||
*/
|
||||
void gossip_store_set_timestamp(struct gossip_store *gs, u64 offset, u32 timestamp);
|
||||
|
||||
/* Exposed for dev-compact-gossip-store to force compaction. */
|
||||
bool gossip_store_compact(struct gossip_store *gs);
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ static void json_add_halfchan(struct json_stream *response,
|
|||
json_add_num(response, "direction", dir);
|
||||
json_add_bool(response, "public", !gossmap_chan_is_localmod(gossmap, c));
|
||||
|
||||
if (c->private) {
|
||||
if (gossmap_chan_is_localmod(gossmap, c)) {
|
||||
/* Local additions don't have a channel_update
|
||||
* in gossmap. This is deprecated anyway, but
|
||||
* fill in values from entry we added. */
|
||||
|
|
Loading…
Add table
Reference in a new issue