mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-10 14:08:40 +01:00
Raise InitError when peers.dat is invalid or corrupted
This commit is contained in:
@@ -21,6 +21,12 @@
|
||||
#include <util/translation.h>
|
||||
|
||||
namespace {
|
||||
|
||||
class DbNotFoundError : public std::exception
|
||||
{
|
||||
using std::exception::exception;
|
||||
};
|
||||
|
||||
template <typename Stream, typename Data>
|
||||
bool SerializeDB(Stream& stream, const Data& data)
|
||||
{
|
||||
@@ -78,47 +84,40 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data
|
||||
}
|
||||
|
||||
template <typename Stream, typename Data>
|
||||
bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
|
||||
void DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
|
||||
{
|
||||
try {
|
||||
CHashVerifier<Stream> verifier(&stream);
|
||||
// de-serialize file header (network specific magic number) and ..
|
||||
unsigned char pchMsgTmp[4];
|
||||
verifier >> pchMsgTmp;
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
|
||||
return error("%s: Invalid network magic number", __func__);
|
||||
CHashVerifier<Stream> verifier(&stream);
|
||||
// de-serialize file header (network specific magic number) and ..
|
||||
unsigned char pchMsgTmp[4];
|
||||
verifier >> pchMsgTmp;
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
|
||||
throw std::runtime_error{"Invalid network magic number"};
|
||||
}
|
||||
|
||||
// de-serialize data
|
||||
verifier >> data;
|
||||
// de-serialize data
|
||||
verifier >> data;
|
||||
|
||||
// verify checksum
|
||||
if (fCheckSum) {
|
||||
uint256 hashTmp;
|
||||
stream >> hashTmp;
|
||||
if (hashTmp != verifier.GetHash()) {
|
||||
return error("%s: Checksum mismatch, data corrupted", __func__);
|
||||
}
|
||||
// verify checksum
|
||||
if (fCheckSum) {
|
||||
uint256 hashTmp;
|
||||
stream >> hashTmp;
|
||||
if (hashTmp != verifier.GetHash()) {
|
||||
throw std::runtime_error{"Checksum mismatch, data corrupted"};
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
bool DeserializeFileDB(const fs::path& path, Data& data, int version)
|
||||
void DeserializeFileDB(const fs::path& path, Data& data, int version)
|
||||
{
|
||||
// open input file, and associate with CAutoFile
|
||||
FILE* file = fsbridge::fopen(path, "rb");
|
||||
CAutoFile filein(file, SER_DISK, version);
|
||||
if (filein.IsNull()) {
|
||||
LogPrintf("Missing or invalid file %s\n", path.string());
|
||||
return false;
|
||||
throw DbNotFoundError{};
|
||||
}
|
||||
return DeserializeDB(filein, data);
|
||||
DeserializeDB(filein, data);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -177,9 +176,9 @@ bool DumpPeerAddresses(const ArgsManager& args, const CAddrMan& addr)
|
||||
return SerializeFileDB("peers", pathAddr, addr, CLIENT_VERSION);
|
||||
}
|
||||
|
||||
bool ReadFromStream(CAddrMan& addr, CDataStream& ssPeers)
|
||||
void ReadFromStream(CAddrMan& addr, CDataStream& ssPeers)
|
||||
{
|
||||
return DeserializeDB(ssPeers, addr, false);
|
||||
DeserializeDB(ssPeers, addr, false);
|
||||
}
|
||||
|
||||
std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const ArgsManager& args, std::unique_ptr<CAddrMan>& addrman)
|
||||
@@ -189,13 +188,18 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
|
||||
|
||||
int64_t nStart = GetTimeMillis();
|
||||
const auto path_addr{args.GetDataDirNet() / "peers.dat"};
|
||||
if (DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION)) {
|
||||
try {
|
||||
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
|
||||
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), GetTimeMillis() - nStart);
|
||||
} else {
|
||||
} catch (const DbNotFoundError&) {
|
||||
// Addrman can be in an inconsistent state after failure, reset it
|
||||
addrman = std::make_unique<CAddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
|
||||
LogPrintf("Recreating peers.dat\n");
|
||||
LogPrintf("Creating peers.dat because the file was not found (%s)\n", 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."),
|
||||
e.what(), PACKAGE_BUGREPORT, path_addr);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -209,9 +213,10 @@ void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& a
|
||||
std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path)
|
||||
{
|
||||
std::vector<CAddress> anchors;
|
||||
if (DeserializeFileDB(anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT)) {
|
||||
try {
|
||||
DeserializeFileDB(anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT);
|
||||
LogPrintf("Loaded %i addresses from %s\n", anchors.size(), anchors_db_path.filename());
|
||||
} else {
|
||||
} catch (const std::exception&) {
|
||||
anchors.clear();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user