devtools: create conversion tool for old gossip stores.
What changed, and why it matters
This commit adds a new developer-only command-line tool called convert-gossmap. It upgrades old Lightning network gossip store files used in testing to a newer format. There is no change to the live node software, no network-facing code, and no indication this fixes or introduces a security issue.
No security action required. Treat as normal development tooling.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces devtools/convert-gossmap.c and wires it into devtools/Makefile. The tool reads an old gossip_store from stdin, rewrites its version header, and applies version-specific transformations: dropping legacy channel_update messages without htlc_maximum_msat, removing obsolete private-channel/private-update records, discarding zombie-flagged entries, and adding the COMPLETED bit. It is a standalone offline conversion utility for test fixtures, not part of the lightningd runtime.
Changed components
devtools/convert-gossmap.cdevtools/MakefileInspect captured patch +101 / −1
diff --git a/devtools/Makefile b/devtools/Makefile
index a80ebe4a..60627914 100644
--- a/devtools/Makefile
+++ b/devtools/Makefile
@@ -1,4 +1,4 @@
-DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route devtools/bolt12-cli devtools/encodeaddr devtools/features devtools/fp16 devtools/rune devtools/gossmap-compress devtools/bip137-verifysignature
+DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route devtools/bolt12-cli devtools/encodeaddr devtools/features devtools/fp16 devtools/rune devtools/gossmap-compress devtools/bip137-verifysignature devtools/convert-gossmap
ifeq ($(HAVE_SQLITE3),1)
DEVTOOLS += devtools/checkchannels
endif
@@ -72,6 +72,9 @@ devtools/dump-gossipstore: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(BITCOIN_OBJS)
devtools/dump-gossipstore.o: gossipd/gossip_store_wiregen.h
+devtools/convert-gossmap: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/convert-gossmap.o
+devtools/convert-gossmap.o: gossipd/gossip_store_wiregen.h
+
devtools/create-gossipstore: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/create-gossipstore.o gossipd/gossip_store_wiregen.o
devtools/create-gossipstore.o: gossipd/gossip_store_wiregen.h
diff --git a/devtools/convert-gossmap.c b/devtools/convert-gossmap.c
new file mode 100644
index 00000000..dee2b1f1
--- /dev/null
+++ b/devtools/convert-gossmap.c
@@ -0,0 +1,97 @@
+/* Tool we can use to convert our testing gossip_store files */
+#include "config.h"
+#include <ccan/crc32c/crc32c.h>
+#include <ccan/err/err.h>
+#include <ccan/opt/opt.h>
+#include <ccan/read_write_all/read_write_all.h>
+#include <common/gossip_store.h>
+#include <fcntl.h>
+#include <gossipd/gossip_store_wiregen.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <wire/peer_wire.h>
+
+/* Current versions we support */
+#define GSTORE_MAJOR 0
+#define GSTORE_MINOR 15
+
+/* Obsolete ZOMBIE bit */
+#define GOSSIP_STORE_ZOMBIE_BIT_V13 0x1000U
+
+static bool upgrade_field(u8 oldversion,
+ be16 *hdr_flags,
+ u8 **msg)
+{
+ int type = fromwire_peektype(*msg);
+
+ switch (oldversion) {
+ case 10:
+ /* Remove old channel_update with no htlc_maximum_msat */
+ if (type == WIRE_CHANNEL_UPDATE
+ && tal_bytelen(*msg) == 130) {
+ *msg = tal_free(*msg);
+ return true;
+ }
+ /* fall thru */
+ case 11:
+ case 12:
+ /* Remove private entries */
+ if (type == WIRE_GOSSIP_STORE_PRIVATE_CHANNEL_OBS) {
+ *msg = tal_free(*msg);
+ return true;
+ } else if (type == WIRE_GOSSIP_STORE_PRIVATE_UPDATE_OBS) {
+ *msg = tal_free(*msg);
+ return true;
+ }
+ /* fall thru */
+ case 13:
+ /* Discard any zombies */
+ if (be16_to_cpu(*hdr_flags) & GOSSIP_STORE_ZOMBIE_BIT_V13) {
+ *msg = tal_free(*msg);
+ return true;
+ }
+ case 14:
+ /* Add completed field */
+ *hdr_flags |= CPU_TO_BE16(GOSSIP_STORE_COMPLETED_BIT);
+ /* fall thru */
+ case 15:
+ /* Noop */
+ return true;
+ }
+
+ return false;
+}
+
+int main(int argc, char *argv[])
+{
+ u8 oldversion, version;
+ struct gossip_hdr hdr;
+
+ setup_locale();
+ if (!read_all(STDIN_FILENO, &oldversion, sizeof(oldversion)))
+ errx(1, "Empty file");
+
+ if (GOSSIP_STORE_MAJOR_VERSION(oldversion) != GSTORE_MAJOR)
+ errx(1, "Unsupported major gossip_version %u (expected %u)",
+ GOSSIP_STORE_MAJOR_VERSION(oldversion), GSTORE_MAJOR);
+
+ version = ((GSTORE_MAJOR << 5) | GSTORE_MINOR);
+ if (!write_all(STDOUT_FILENO, &version, sizeof(version)))
+ err(1, "Write error");
+
+ while (read_all(STDIN_FILENO, &hdr, sizeof(hdr))) {
+ u8 *msg;
+ msg = tal_arr(NULL, u8, be16_to_cpu(hdr.len));
+ if (!read_all(STDIN_FILENO, msg, tal_bytelen(msg)))
+ err(1, "truncated file");
+ if (!upgrade_field(oldversion, &hdr.flags, &msg))
+ errx(1, "Cannot upgrade from version %u", oldversion);
+ if (msg) {
+ if (!write_all(STDOUT_FILENO, &hdr, sizeof(hdr))
+ || !write_all(STDOUT_FILENO, msg, tal_bytelen(msg)))
+ err(1, "Write error");
+ tal_free(msg);
+ }
+ }
+ return 0;
+}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.