Skip to content

Commit 40a22e4

Browse files
committed
merge bitcoin#24201: Avoid InitError when downgrading peers.dat
1 parent cdcaf22 commit 40a22e4

File tree

4 files changed

+34
-20
lines changed

4 files changed

+34
-20
lines changed

src/addrdb.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,15 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
206206
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
207207
LogPrintf("Creating peers.dat because of invalid or corrupt file (%s)\n", e.what());
208208
DumpPeerAddresses(args, *addrman);
209+
} catch (const InvalidAddrManVersionError&) {
210+
if (!RenameOver(path_addr, (fs::path)path_addr + ".bak")) {
211+
addrman = nullptr;
212+
return strprintf(_("Failed to rename invalid peers.dat file. Please move or delete it and try again."));
213+
}
214+
// Addrman can be in an inconsistent state after failure, reset it
215+
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
216+
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)));
217+
DumpPeerAddresses(args, *addrman);
209218
} catch (const std::exception& e) {
210219
addrman = nullptr;
211220
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
@@ -250,7 +250,7 @@ void AddrManImpl::Unserialize(Stream& s_)
250250
s >> compat;
251251
const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE;
252252
if (lowest_compatible > FILE_FORMAT) {
253-
throw std::ios_base::failure(strprintf(
253+
throw InvalidAddrManVersionError(strprintf(
254254
"Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
255255
"but the maximum supported by this version of %s is %u.",
256256
uint8_t{format}, uint8_t{lowest_compatible}, PACKAGE_NAME, uint8_t{FILE_FORMAT}));

src/addrman.h

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

20+
class DbInconsistentError : public std::exception
21+
{
22+
using std::exception::exception;
23+
const std::string error;
24+
25+
public:
26+
explicit DbInconsistentError(const std::string _error) : error{_error} {}
27+
const char* what() const noexcept override { return error.c_str(); }
28+
};
29+
30+
class InvalidAddrManVersionError : public std::ios_base::failure
31+
{
32+
public:
33+
InvalidAddrManVersionError(std::string msg) : std::ios_base::failure(msg) { }
34+
};
35+
2036
class AddrInfo;
2137
class AddrManImpl;
2238

@@ -48,16 +64,6 @@ struct AddressPosition {
4864
: tried{tried_in}, multiplicity{multiplicity_in}, bucket{bucket_in}, position{position_in} {}
4965
};
5066

51-
class DbInconsistentError : public std::exception
52-
{
53-
using std::exception::exception;
54-
const std::string error;
55-
56-
public:
57-
explicit DbInconsistentError(const std::string _error) : error{_error} {}
58-
const char* what() const noexcept override { return error.c_str(); }
59-
};
60-
6167
/** Stochastic address manager
6268
*
6369
* Design goals:

test/functional/feature_addrman.py

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

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

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

0 commit comments

Comments
 (0)