From 855debcfe174e28ef0f05a525c21746eba974f00 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 4 May 2020 09:48:25 +0930 Subject: [PATCH] gossipd: upgrade v7 gossip_store to v8. Signed-off-by: Rusty Russell --- gossipd/gossip_store.c | 49 +++++++++++++++++++++++++++++++++++++++--- tests/test_gossip.py | 4 ++-- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 278c8436e..67531a958 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -116,6 +116,36 @@ static bool append_msg(int fd, const u8 *msg, u32 timestamp, return true; } +#ifdef COMPAT_V082 +/* The upgrade from version 7 is trivial */ +static bool can_upgrade(u8 oldversion) +{ + return oldversion == 7; +} + +static bool upgrade_field(u8 oldversion, u8 **msg) +{ + assert(can_upgrade(oldversion)); + + /* We only need to upgrade this */ + if (fromwire_peektype(*msg) == WIRE_GOSSIPD_LOCAL_ADD_CHANNEL) { + /* Append two 0 bytes, for (empty) feature bits */ + tal_resizez(msg, tal_bytelen(*msg) + 2); + } + return true; +} +#else +static bool can_upgrade(u8 oldversion) +{ + return false; +} + +static bool upgrade_field(u8 oldversion, u8 **msg) +{ + abort(); +} +#endif /* !COMPAT_V082 */ + /* Read gossip store entries, copy non-deleted ones. This code is written * as simply and robustly as possible! */ static u32 gossip_store_compact_offline(void) @@ -123,7 +153,7 @@ static u32 gossip_store_compact_offline(void) size_t count = 0, deleted = 0; int old_fd, new_fd; struct gossip_hdr hdr; - u8 version; + u8 oldversion, version = GOSSIP_STORE_VERSION; struct stat st; old_fd = open(GOSSIP_STORE_FILENAME, O_RDONLY); @@ -143,8 +173,8 @@ static u32 gossip_store_compact_offline(void) goto close_old; } - if (!read_all(old_fd, &version, sizeof(version)) - || version != GOSSIP_STORE_VERSION) { + if (!read_all(old_fd, &oldversion, sizeof(oldversion)) + || (oldversion != version && !can_upgrade(oldversion))) { status_broken("gossip_store_compact: bad version"); goto close_and_delete; } @@ -175,6 +205,19 @@ static u32 gossip_store_compact_offline(void) continue; } + if (oldversion != version) { + if (!upgrade_field(oldversion, &msg)) { + tal_free(msg); + goto close_and_delete; + } + + /* Recalc msglen and header */ + msglen = tal_bytelen(msg); + hdr.len = cpu_to_be32(msglen); + hdr.crc = cpu_to_be32(crc32c(be32_to_cpu(hdr.timestamp), + msg, msglen)); + } + if (!write_all(new_fd, &hdr, sizeof(hdr)) || !write_all(new_fd, msg, msglen)) { status_broken("gossip_store_compact_offline: writing msg len %zu to new store: %s", diff --git a/tests/test_gossip.py b/tests/test_gossip.py index 278852723..8e7187f9b 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -4,7 +4,7 @@ from fixtures import * # noqa: F401,F403 from fixtures import TEST_NETWORK from pyln.client import RpcError, Millisatoshi from utils import ( - wait_for, TIMEOUT, only_one, sync_blockheight, expected_node_features + wait_for, TIMEOUT, only_one, sync_blockheight, expected_node_features, COMPAT ) import json @@ -1659,7 +1659,7 @@ def test_torport_onions(node_factory): assert l2.daemon.is_in_log('x2y4zvh4fn5q3eouuh7nxnc7zeawrqoutljrup2xjtiyxgx3emgkemad.onion:45321,127.0.0.1:{}'.format(l2.port)) -@pytest.mark.xfail(strict=True) +@unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete gossip_store") def test_gossip_store_upgrade_v7_v8(node_factory): """Version 8 added feature bits to local channel announcements""" l1 = node_factory.get_node(start=False)