From d41ed3215355582879c8eb6c99c2da33852f6cb1 Mon Sep 17 00:00:00 2001 From: junderw Date: Sat, 29 Jan 2022 21:58:59 +0900 Subject: p2p: Avoid InitError when downgrading peers.dat fixes #24188 When downgrading, a peers.dat with a future version that has a minimum required version larger than the downgraded version would cause an InitError. This commit changes this behavior to overwrite the existing peers.dat with a new empty one, while creating a backup in peers.dat.bak. --- src/addrdb.cpp | 9 +++++++++ src/addrman.cpp | 2 +- src/addrman.h | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 94518b88d8..9f3e2e7219 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -196,6 +196,15 @@ std::optional LoadAddrman(const std::vector& asmap, const A addrman = std::make_unique(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman); LogPrintf("Creating peers.dat because the file was not found (%s)\n", fs::quoted(fs::PathToString(path_addr))); DumpPeerAddresses(args, *addrman); + } catch (const InvalidAddrManVersionError&) { + if (!RenameOver(path_addr, (fs::path)path_addr + ".bak")) { + addrman = nullptr; + return strprintf(_("Failed to rename invalid peers.dat file. Please move or delete it and try again.")); + } + // Addrman can be in an inconsistent state after failure, reset it + addrman = std::make_unique(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman); + LogPrintf("Creating new peers.dat because the file version was not compatible (%s). Original backed up to peers.dat.bak\n", fs::quoted(fs::PathToString(path_addr))); + DumpPeerAddresses(args, *addrman); } catch (const std::exception& e) { addrman = nullptr; return strprintf(_("Invalid or corrupt peers.dat (%s). If you believe this is a bug, please report it to %s. As a workaround, you can move the file (%s) out of the way (rename, move, or delete) to have a new one created on the next start."), diff --git a/src/addrman.cpp b/src/addrman.cpp index 3a845b5b6e..f91a979934 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -248,7 +248,7 @@ void AddrManImpl::Unserialize(Stream& s_) s >> compat; const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE; if (lowest_compatible > FILE_FORMAT) { - throw std::ios_base::failure(strprintf( + throw InvalidAddrManVersionError(strprintf( "Unsupported format of addrman database: %u. It is compatible with formats >=%u, " "but the maximum supported by this version of %s is %u.", uint8_t{format}, uint8_t{lowest_compatible}, PACKAGE_NAME, uint8_t{FILE_FORMAT})); diff --git a/src/addrman.h b/src/addrman.h index 0646ef368d..472282833b 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -17,6 +17,12 @@ #include #include +class InvalidAddrManVersionError : public std::ios_base::failure +{ +public: + InvalidAddrManVersionError(std::string msg) : std::ios_base::failure(msg) { } +}; + class AddrManImpl; /** Default for -checkaddrman */ -- cgit v1.2.3