Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ BITCOIN_CORE_H = \
addressindex.h \
spentindex.h \
addrman.h \
addrman_impl.h \
attributes.h \
banman.h \
base58.h \
Expand Down
1 change: 0 additions & 1 deletion src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
test/fuzz/crypto_poly1305.cpp \
test/fuzz/cuckoocache.cpp \
test/fuzz/data_stream.cpp \
test/fuzz/decode_tx.cpp \
test/fuzz/descriptor_parse.cpp \
test/fuzz/deserialize.cpp \
Expand Down
92 changes: 55 additions & 37 deletions src/addrdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@
#include <univalue.h>
#include <util/settings.h>
#include <util/system.h>
#include <util/translation.h>

#include <cstdint>

namespace {

class DbNotFoundError : public std::exception
{
using std::exception::exception;
};

template <typename Stream, typename Data>
bool SerializeDB(Stream& stream, const Data& data)
{
Expand Down Expand Up @@ -78,47 +85,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__);

// 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__);
}
}
}
catch (const std::exception& e) {
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
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"};
}

return true;
// de-serialize data
verifier >> data;

// verify checksum
if (fCheckSum) {
uint256 hashTmp;
stream >> hashTmp;
if (hashTmp != verifier.GetHash()) {
throw std::runtime_error{"Checksum mismatch, data corrupted"};
}
}
}

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

Expand Down Expand Up @@ -171,21 +171,38 @@ bool CBanDB::Read(banmap_t& banSet)
return true;
}

bool DumpPeerAddresses(const ArgsManager& args, const CAddrMan& addr)
bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr)
{
const auto pathAddr = GetDataDir() / "peers.dat";
return SerializeFileDB("peers", pathAddr, addr, CLIENT_VERSION);
}

bool ReadPeerAddresses(const ArgsManager& args, CAddrMan& addr)
void ReadFromStream(AddrMan& addr, CDataStream& ssPeers)
{
const auto pathAddr = GetDataDir() / "peers.dat";
return DeserializeFileDB(pathAddr, addr, CLIENT_VERSION);
DeserializeDB(ssPeers, addr, false);
}

bool ReadFromStream(CAddrMan& addr, CDataStream& ssPeers)
std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const ArgsManager& args, std::unique_ptr<AddrMan>& addrman)
{
return DeserializeDB(ssPeers, addr, false);
auto check_addrman = std::clamp<int32_t>(args.GetArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000);
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);

int64_t nStart = GetTimeMillis();
const auto path_addr{GetDataDir() / "peers.dat"};
try {
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), GetTimeMillis() - nStart);
} catch (const DbNotFoundError&) {
// Addrman can be in an inconsistent state after failure, reset it
addrman = std::make_unique<AddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
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;
}

void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors)
Expand All @@ -197,9 +214,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();
}

Expand Down
12 changes: 8 additions & 4 deletions src/addrdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@
#include <net_types.h> // For banmap_t
#include <univalue.h>

#include <optional>
#include <vector>

class ArgsManager;
class CAddrMan;
class AddrMan;
class CAddress;
class CDataStream;
struct bilingual_str;

bool DumpPeerAddresses(const ArgsManager& args, const CAddrMan& addr);
bool ReadPeerAddresses(const ArgsManager& args, CAddrMan& addr);
bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr);
/** Only used by tests. */
bool ReadFromStream(CAddrMan& addr, CDataStream& ssPeers);
void ReadFromStream(AddrMan& addr, CDataStream& ssPeers);

/** Access to the banlist database (banlist.json) */
class CBanDB
Expand All @@ -46,6 +47,9 @@ class CBanDB
bool Read(banmap_t& banSet);
};

/** Returns an error string on failure */
std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const ArgsManager& args, std::unique_ptr<AddrMan>& addrman);

/**
* Dump the anchor IP address database (anchors.dat)
*
Expand Down
Loading