Changeset View
Changeset View
Standalone View
Standalone View
src/addrdb.cpp
| Show First 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | try { | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| template <typename Data> | template <typename Data> | ||||
| bool SerializeFileDB(const CChainParams &chainParams, const std::string &prefix, | bool SerializeFileDB(const CChainParams &chainParams, const std::string &prefix, | ||||
| const fs::path &path, const Data &data, int version) { | const fs::path &path, const Data &data) { | ||||
| // Generate random temporary filename | // Generate random temporary filename | ||||
| const uint16_t randv{FastRandomContext().rand<uint16_t>()}; | const uint16_t randv{FastRandomContext().rand<uint16_t>()}; | ||||
| std::string tmpfn = strprintf("%s.%04x", prefix, randv); | std::string tmpfn = strprintf("%s.%04x", prefix, randv); | ||||
| // open temp output file, and associate with CAutoFile | // open temp output file | ||||
| fs::path pathTmp = gArgs.GetDataDirNet() / tmpfn; | fs::path pathTmp = gArgs.GetDataDirNet() / tmpfn; | ||||
| FILE *file = fsbridge::fopen(pathTmp, "wb"); | FILE *file = fsbridge::fopen(pathTmp, "wb"); | ||||
| CAutoFile fileout(file, SER_DISK, version); | AutoFile fileout{file}; | ||||
| if (fileout.IsNull()) { | if (fileout.IsNull()) { | ||||
| fileout.fclose(); | fileout.fclose(); | ||||
| remove(pathTmp); | remove(pathTmp); | ||||
| LogError("%s: Failed to open file %s\n", __func__, | LogError("%s: Failed to open file %s\n", __func__, | ||||
| fs::PathToString(pathTmp)); | fs::PathToString(pathTmp)); | ||||
| return false; | return false; | ||||
| } | } | ||||
| Show All 18 Lines | if (!RenameOver(pathTmp, path)) { | ||||
| LogError("%s: Rename-into-place failed\n", __func__); | LogError("%s: Rename-into-place failed\n", __func__); | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| template <typename Stream, typename Data> | template <typename Stream, typename Data> | ||||
| void DeserializeDB(const CChainParams &chainParams, Stream &stream, Data &data, | void DeserializeDB(const CChainParams &chainParams, Stream &stream, Data &&data, | ||||
| bool fCheckSum = true) { | bool fCheckSum = true) { | ||||
| CHashVerifier<Stream> verifier(&stream); | HashVerifier verifier{stream}; | ||||
| // de-serialize file header (network specific magic number) and .. | // de-serialize file header (network specific magic number) and .. | ||||
| uint8_t pchMsgTmp[4]; | uint8_t pchMsgTmp[4]; | ||||
| verifier >> pchMsgTmp; | verifier >> pchMsgTmp; | ||||
| // ... verify the network matches ours | // ... verify the network matches ours | ||||
| if (memcmp(pchMsgTmp, std::begin(chainParams.DiskMagic()), | if (memcmp(pchMsgTmp, std::begin(chainParams.DiskMagic()), | ||||
| sizeof(pchMsgTmp))) { | sizeof(pchMsgTmp))) { | ||||
| throw std::runtime_error{"Invalid network magic number"}; | throw std::runtime_error{"Invalid network magic number"}; | ||||
| } | } | ||||
| // de-serialize data | // de-serialize data | ||||
| verifier >> data; | verifier >> data; | ||||
| // verify checksum | // verify checksum | ||||
| if (fCheckSum) { | if (fCheckSum) { | ||||
| uint256 hashTmp; | uint256 hashTmp; | ||||
| stream >> hashTmp; | stream >> hashTmp; | ||||
| if (hashTmp != verifier.GetHash()) { | if (hashTmp != verifier.GetHash()) { | ||||
| throw std::runtime_error{"Checksum mismatch, data corrupted"}; | throw std::runtime_error{"Checksum mismatch, data corrupted"}; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| template <typename Data> | template <typename Data> | ||||
| void DeserializeFileDB(const CChainParams &chainParams, const fs::path &path, | void DeserializeFileDB(const CChainParams &chainParams, const fs::path &path, | ||||
| Data &data, int version) { | Data &&data) { | ||||
| // open input file, and associate with CAutoFile | |||||
| FILE *file = fsbridge::fopen(path, "rb"); | FILE *file = fsbridge::fopen(path, "rb"); | ||||
| CAutoFile filein(file, SER_DISK, version); | AutoFile filein{file}; | ||||
| if (filein.IsNull()) { | if (filein.IsNull()) { | ||||
| throw DbNotFoundError{}; | throw DbNotFoundError{}; | ||||
| } | } | ||||
| DeserializeDB(chainParams, filein, data); | DeserializeDB(chainParams, filein, data); | ||||
| } | } | ||||
| } // namespace | } // namespace | ||||
| Show All 20 Lines | bool CBanDB::Read(banmap_t &banSet, bool &dirty) { | ||||
| // banlist.dat. | // banlist.dat. | ||||
| // TODO: stop supporting banlist.dat after v0.34.0. See: | // TODO: stop supporting banlist.dat after v0.34.0. See: | ||||
| // https://github.com/bitcoin/bitcoin/pull/22570 | // https://github.com/bitcoin/bitcoin/pull/22570 | ||||
| if (!fs::exists(m_banlist_json)) { | if (!fs::exists(m_banlist_json)) { | ||||
| // If this succeeds then we need to flush to disk in order to create the | // If this succeeds then we need to flush to disk in order to create the | ||||
| // JSON banlist. | // JSON banlist. | ||||
| dirty = true; | dirty = true; | ||||
| try { | try { | ||||
| DeserializeFileDB(chainParams, m_banlist_dat, banSet, | DeserializeFileDB(chainParams, m_banlist_dat, | ||||
| CLIENT_VERSION); | WithParams(CAddress::V1_DISK, banSet)); | ||||
| } catch (const std::exception &) { | } catch (const std::exception &) { | ||||
| LogPrintf("Missing or invalid file %s\n", | LogPrintf("Missing or invalid file %s\n", | ||||
| fs::quoted(fs::PathToString(m_banlist_dat))); | fs::quoted(fs::PathToString(m_banlist_dat))); | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| Show All 19 Lines | bool CBanDB::Read(banmap_t &banSet, bool &dirty) { | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| bool DumpPeerAddresses(const CChainParams &chainParams, const ArgsManager &args, | bool DumpPeerAddresses(const CChainParams &chainParams, const ArgsManager &args, | ||||
| const AddrMan &addr) { | const AddrMan &addr) { | ||||
| const auto pathAddr = args.GetDataDirNet() / "peers.dat"; | const auto pathAddr = args.GetDataDirNet() / "peers.dat"; | ||||
| return SerializeFileDB(chainParams, "peers", pathAddr, addr, | return SerializeFileDB(chainParams, "peers", pathAddr, addr); | ||||
| CLIENT_VERSION); | |||||
| } | } | ||||
| void ReadFromStream(const CChainParams &chainParams, AddrMan &addr, | void ReadFromStream(const CChainParams &chainParams, AddrMan &addr, | ||||
| CDataStream &ssPeers) { | DataStream &ssPeers) { | ||||
| DeserializeDB(chainParams, ssPeers, addr, false); | DeserializeDB(chainParams, ssPeers, addr, false); | ||||
| } | } | ||||
| util::Result<std::unique_ptr<AddrMan>> | util::Result<std::unique_ptr<AddrMan>> | ||||
| LoadAddrman(const CChainParams &chainparams, const std::vector<bool> &asmap, | LoadAddrman(const CChainParams &chainparams, const std::vector<bool> &asmap, | ||||
| const ArgsManager &args) { | const ArgsManager &args) { | ||||
| auto check_addrman = std::clamp<int32_t>( | auto check_addrman = std::clamp<int32_t>( | ||||
| args.GetIntArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, | args.GetIntArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, | ||||
| 1000000); | 1000000); | ||||
| auto addrman{ | auto addrman{ | ||||
| std::make_unique<AddrMan>(asmap, /*deterministic=*/false, | std::make_unique<AddrMan>(asmap, /*deterministic=*/false, | ||||
| /*consistency_check_ratio=*/check_addrman)}; | /*consistency_check_ratio=*/check_addrman)}; | ||||
| int64_t nStart = GetTimeMillis(); | int64_t nStart = GetTimeMillis(); | ||||
| const auto path_addr{args.GetDataDirNet() / "peers.dat"}; | const auto path_addr{args.GetDataDirNet() / "peers.dat"}; | ||||
| try { | try { | ||||
| DeserializeFileDB(chainparams, path_addr, *addrman, CLIENT_VERSION); | DeserializeFileDB(chainparams, path_addr, *addrman); | ||||
| LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), | LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), | ||||
| GetTimeMillis() - nStart); | GetTimeMillis() - nStart); | ||||
| } catch (const DbNotFoundError &) { | } catch (const DbNotFoundError &) { | ||||
| // Addrman can be in an inconsistent state after failure, reset it | // Addrman can be in an inconsistent state after failure, reset it | ||||
| addrman = std::make_unique<AddrMan>( | addrman = std::make_unique<AddrMan>( | ||||
| asmap, /*deterministic=*/false, | asmap, /*deterministic=*/false, | ||||
| /*consistency_check_ratio=*/check_addrman); | /*consistency_check_ratio=*/check_addrman); | ||||
| LogPrintf("Creating peers.dat because the file was not found (%s)\n", | LogPrintf("Creating peers.dat because the file was not found (%s)\n", | ||||
| Show All 30 Lines | |||||
| } | } | ||||
| void DumpAnchors(const CChainParams &chainParams, | void DumpAnchors(const CChainParams &chainParams, | ||||
| const fs::path &anchors_db_path, | const fs::path &anchors_db_path, | ||||
| const std::vector<CAddress> &anchors) { | const std::vector<CAddress> &anchors) { | ||||
| LOG_TIME_SECONDS(strprintf( | LOG_TIME_SECONDS(strprintf( | ||||
| "Flush %d outbound block-relay-only peer addresses to anchors.dat", | "Flush %d outbound block-relay-only peer addresses to anchors.dat", | ||||
| anchors.size())); | anchors.size())); | ||||
| SerializeFileDB(chainParams, "anchors", anchors_db_path, anchors, | SerializeFileDB(chainParams, "anchors", anchors_db_path, | ||||
| CLIENT_VERSION | ADDRV2_FORMAT); | WithParams(CAddress::V2_DISK, anchors)); | ||||
| } | } | ||||
| std::vector<CAddress> ReadAnchors(const CChainParams &chainParams, | std::vector<CAddress> ReadAnchors(const CChainParams &chainParams, | ||||
| const fs::path &anchors_db_path) { | const fs::path &anchors_db_path) { | ||||
| std::vector<CAddress> anchors; | std::vector<CAddress> anchors; | ||||
| try { | try { | ||||
| DeserializeFileDB(chainParams, anchors_db_path, anchors, | DeserializeFileDB(chainParams, anchors_db_path, | ||||
| CLIENT_VERSION | ADDRV2_FORMAT); | WithParams(CAddress::V2_DISK, anchors)); | ||||
| LogPrintf("Loaded %i addresses from %s\n", anchors.size(), | LogPrintf("Loaded %i addresses from %s\n", anchors.size(), | ||||
| fs::quoted(fs::PathToString(anchors_db_path.filename()))); | fs::quoted(fs::PathToString(anchors_db_path.filename()))); | ||||
| } catch (const std::exception &) { | } catch (const std::exception &) { | ||||
| anchors.clear(); | anchors.clear(); | ||||
| } | } | ||||
| fs::remove(anchors_db_path); | fs::remove(anchors_db_path); | ||||
| return anchors; | return anchors; | ||||
| } | } | ||||