gossipd: write uuid record on startup.
This is the first record, and ignored by everything else. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -832,6 +832,9 @@ static bool map_catchup(struct gossmap *map, bool must_be_clean, bool *changed)
|
||||
} else if (type == WIRE_GOSSIP_STORE_CHAN_DYING) {
|
||||
/* We don't really care until it's deleted */
|
||||
continue;
|
||||
} else if (type == WIRE_GOSSIP_STORE_UUID) {
|
||||
/* We handled this reopen, otherwise we don't care. */
|
||||
continue;
|
||||
} else {
|
||||
map->logcb(map->cbarg, LOG_BROKEN,
|
||||
"Unknown record %u@%u (size %zu) in gossmap: ignoring",
|
||||
|
||||
@@ -179,6 +179,18 @@ static bool upgrade_field(u8 oldversion,
|
||||
return true;
|
||||
}
|
||||
|
||||
static u8 *new_uuid_record(const tal_t *ctx, int fd, u64 *off)
|
||||
{
|
||||
u8 *uuid = tal_arr(ctx, u8, 32);
|
||||
|
||||
for (size_t i = 0; i < tal_bytelen(uuid); i++)
|
||||
uuid[i] = pseudorand(256);
|
||||
append_msg(fd, towire_gossip_store_uuid(tmpctx, uuid), 0, off, NULL);
|
||||
/* append_msg does not change file offset, so do that now. */
|
||||
lseek(fd, 0, SEEK_END);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/* Read gossip store entries, copy non-deleted ones. Check basic
|
||||
* validity, but this code is written as simply and robustly as
|
||||
* possible!
|
||||
@@ -198,6 +210,7 @@ static int gossip_store_compact(struct daemon *daemon,
|
||||
struct stat st;
|
||||
struct timemono start = time_mono();
|
||||
const char *bad;
|
||||
u8 *uuid = NULL;
|
||||
|
||||
*populated = false;
|
||||
old_len = 1;
|
||||
@@ -241,6 +254,10 @@ static int gossip_store_compact(struct daemon *daemon,
|
||||
|
||||
cur_off = old_len = sizeof(oldversion);
|
||||
|
||||
/* Make up uuid for old version */
|
||||
if (oldversion < 16)
|
||||
uuid = new_uuid_record(tmpctx, new_fd, total_len);
|
||||
|
||||
/* Read everything, write non-deleted ones to new_fd. If something goes wrong,
|
||||
* we end up with truncated store. */
|
||||
while (read_all(old_fd, &hdr, sizeof(hdr))) {
|
||||
@@ -327,6 +344,13 @@ static int gossip_store_compact(struct daemon *daemon,
|
||||
case WIRE_NODE_ANNOUNCEMENT:
|
||||
nannounces++;
|
||||
break;
|
||||
case WIRE_GOSSIP_STORE_UUID:
|
||||
uuid = tal_arr(tmpctx, u8, 32);
|
||||
if (!fromwire_gossip_store_uuid(msg, uuid)) {
|
||||
bad = "Corrupt uuid";
|
||||
goto badmsg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!write_all(new_fd, &hdr, sizeof(hdr))
|
||||
@@ -348,6 +372,16 @@ static int gossip_store_compact(struct daemon *daemon,
|
||||
}
|
||||
|
||||
rename_new:
|
||||
/* If we didn't copy a uuid, do so now. */
|
||||
if (!uuid) {
|
||||
if (lseek(new_fd, 0, SEEK_END) != 1) {
|
||||
bad = tal_fmt(tmpctx,
|
||||
"missing uuid in version %u", oldversion);
|
||||
goto badmsg;
|
||||
}
|
||||
uuid = new_uuid_record(tmpctx, new_fd, total_len);
|
||||
}
|
||||
|
||||
if (rename(GOSSIP_STORE_TEMP_FILENAME, GOSSIP_STORE_FILENAME) != 0) {
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"gossip_store_compact: rename failed: %s",
|
||||
@@ -357,7 +391,6 @@ rename_new:
|
||||
/* Create end marker now new file exists. */
|
||||
if (old_fd != -1) {
|
||||
/* FIXME: real uuid! */
|
||||
u8 uuid[32] = {0};
|
||||
append_msg(old_fd, towire_gossip_store_ended(tmpctx, *total_len, uuid),
|
||||
0, &old_len, NULL);
|
||||
close(old_fd);
|
||||
|
||||
@@ -1207,7 +1207,7 @@ def test_gossip_store_load(node_factory):
|
||||
|
||||
l1.start()
|
||||
# May preceed the Started msg waited for in 'start'.
|
||||
wait_for(lambda: l1.daemon.is_in_log('Read 1/1/1/0 cannounce/cupdate/nannounce/delete from store in 832 bytes, now 778 bytes'))
|
||||
wait_for(lambda: l1.daemon.is_in_log('Read 1/1/1/0 cannounce/cupdate/nannounce/delete from store in 832 bytes, now 824 bytes'))
|
||||
assert not l1.daemon.is_in_log('gossip_store.*truncating')
|
||||
|
||||
|
||||
@@ -1275,13 +1275,13 @@ def test_gossip_store_load_announce_before_update(node_factory):
|
||||
|
||||
l1.start()
|
||||
# May preceed the Started msg waited for in 'start'.
|
||||
wait_for(lambda: l1.daemon.is_in_log('Read 1/1/1/1 cannounce/cupdate/nannounce/delete from store in 950 bytes, now 778 bytes'))
|
||||
wait_for(lambda: l1.daemon.is_in_log('Read 1/1/1/1 cannounce/cupdate/nannounce/delete from store in 982 bytes, now 824 bytes'))
|
||||
assert not l1.daemon.is_in_log('gossip_store.*truncating')
|
||||
|
||||
|
||||
def test_gossip_store_load_amount_truncated(node_factory):
|
||||
"""Make sure we can read canned gossip store with truncated amount"""
|
||||
l1 = node_factory.get_node(start=False, broken_log=r'gossip_store only processed 1 bytes of 445 \(expected 445\)|Moving to gossip_store.corrupt|plugin-cln-renepay:.*unable to fetch channel capacity')
|
||||
l1 = node_factory.get_node(start=False, broken_log=r'gossip_store only processed 47 bytes of 491 \(expected 491\)|Moving to gossip_store.corrupt|plugin-cln-renepay:.*unable to fetch channel capacity')
|
||||
with open(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store'), 'wb') as f:
|
||||
f.write(bytearray.fromhex("0c" # GOSSIP_STORE_VERSION
|
||||
"000001b0" # len
|
||||
@@ -1292,9 +1292,9 @@ def test_gossip_store_load_amount_truncated(node_factory):
|
||||
|
||||
l1.start()
|
||||
# May preceed the Started msg waited for in 'start'.
|
||||
wait_for(lambda: l1.daemon.is_in_log(r'\*\*BROKEN\*\* gossipd: gossip_store only processed 1 bytes of 445 \(expected 445\)'))
|
||||
wait_for(lambda: l1.daemon.is_in_log(r'\*\*BROKEN\*\* gossipd: gossip_store only processed 47 bytes of 491 \(expected 491\)'))
|
||||
wait_for(lambda: l1.daemon.is_in_log(r'\*\*BROKEN\*\* gossipd: gossip_store: Moving to gossip_store.corrupt'))
|
||||
wait_for(lambda: l1.daemon.is_in_log(r'gossip_store: Read 0/0/0/0 cannounce/cupdate/nannounce/delete from store in 1 bytes, now 1 bytes \(populated=false\)'))
|
||||
wait_for(lambda: l1.daemon.is_in_log(r'gossip_store: Read 0/0/0/0 cannounce/cupdate/nannounce/delete from store in 1 bytes, now 47 bytes \(populated=false\)'))
|
||||
assert os.path.exists(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store.corrupt'))
|
||||
|
||||
|
||||
@@ -1658,7 +1658,7 @@ def test_gossip_store_load_no_channel_update(node_factory):
|
||||
l1.start()
|
||||
|
||||
# May preceed the Started msg waited for in 'start'.
|
||||
wait_for(lambda: l1.daemon.is_in_log('Read 1/0/1/0 cannounce/cupdate/nannounce/delete from store in 650 bytes, now 628 bytes'))
|
||||
wait_for(lambda: l1.daemon.is_in_log('Read 1/0/1/0 cannounce/cupdate/nannounce/delete from store in 682 bytes, now 674 bytes'))
|
||||
assert not os.path.exists(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store.corrupt'))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user