Skip to content

Commit b00b60e

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#24201: p2p: Avoid InitError when downgrading peers.dat
d41ed32 p2p: Avoid InitError when downgrading peers.dat (junderw) Pull request description: fixes #24188 (also see bitcoin/bitcoin#22762 (comment)) When downgrading, a peers.dat with a future version that has a minimum required version larger than the downgraded Bitcoin Core version would cause an InitError. This commit changes this behavior to overwrite the existing peers.dat with a new empty one. ACKs for top commit: prayank23: reACK bitcoin/bitcoin@d41ed32 kallewoof: reACK d41ed32 Tree-SHA512: c8e625fe36ce0b1aab6c8ef7241c8954038bb856f2de27bdc4814dc9a60e51be28815c7d77d0f96eace49687a0cea02deb713978bbd3a5add742f50a675f2a40
2 parents f1ce67f + d41ed32 commit b00b60e

File tree

4 files changed

+24
-10
lines changed

4 files changed

+24
-10
lines changed

src/addrdb.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
197197
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
198198
LogPrintf("Creating peers.dat because the file was not found (%s)\n", fs::quoted(fs::PathToString(path_addr)));
199199
DumpPeerAddresses(args, *addrman);
200+
} catch (const InvalidAddrManVersionError&) {
201+
if (!RenameOver(path_addr, (fs::path)path_addr + ".bak")) {
202+
addrman = nullptr;
203+
return strprintf(_("Failed to rename invalid peers.dat file. Please move or delete it and try again."));
204+
}
205+
// Addrman can be in an inconsistent state after failure, reset it
206+
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
207+
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)));
208+
DumpPeerAddresses(args, *addrman);
200209
} catch (const std::exception& e) {
201210
addrman = nullptr;
202211
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."),

src/addrman.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ void AddrManImpl::Unserialize(Stream& s_)
248248
s >> compat;
249249
const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE;
250250
if (lowest_compatible > FILE_FORMAT) {
251-
throw std::ios_base::failure(strprintf(
251+
throw InvalidAddrManVersionError(strprintf(
252252
"Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
253253
"but the maximum supported by this version of %s is %u.",
254254
uint8_t{format}, uint8_t{lowest_compatible}, PACKAGE_NAME, uint8_t{FILE_FORMAT}));

src/addrman.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
#include <utility>
1818
#include <vector>
1919

20+
class InvalidAddrManVersionError : public std::ios_base::failure
21+
{
22+
public:
23+
InvalidAddrManVersionError(std::string msg) : std::ios_base::failure(msg) { }
24+
};
25+
2026
class AddrManImpl;
2127

2228
/** Default for -checkaddrman */

test/functional/feature_addrman.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,16 @@ def run_test(self):
6868
self.start_node(0, extra_args=["-checkaddrman=1"])
6969
assert_equal(self.nodes[0].getnodeaddresses(), [])
7070

71-
self.log.info("Check that addrman from future cannot be read")
71+
self.log.info("Check that addrman from future is overwritten with new addrman")
7272
self.stop_node(0)
7373
write_addrman(peers_dat, lowest_compatible=111)
74-
self.nodes[0].assert_start_raises_init_error(
75-
expected_msg=init_error(
76-
"Unsupported format of addrman database: 1. It is compatible with "
77-
"formats >=111, but the maximum supported by this version of "
78-
f"{self.config['environment']['PACKAGE_NAME']} is 4.: (.+)"
79-
),
80-
match=ErrorMatch.FULL_REGEX,
81-
)
74+
assert_equal(os.path.exists(peers_dat + ".bak"), False)
75+
with self.nodes[0].assert_debug_log([
76+
f'Creating new peers.dat because the file version was not compatible ("{peers_dat}"). Original backed up to peers.dat.bak',
77+
]):
78+
self.start_node(0)
79+
assert_equal(self.nodes[0].getnodeaddresses(), [])
80+
assert_equal(os.path.exists(peers_dat + ".bak"), True)
8281

8382
self.log.info("Check that corrupt addrman cannot be read (EOF)")
8483
self.stop_node(0)

0 commit comments

Comments
 (0)