PIVX Core  5.6.99
P2P Digital Currency
addrdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 The Bitcoin Core developers
3 // Copyright (c) 2020-2021 The PIVX Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "addrdb.h"
8 
9 #include "addrman.h"
10 #include "chainparams.h"
11 #include "clientversion.h"
12 #include "hash.h"
13 #include "random.h"
14 #include "streams.h"
15 #include "tinyformat.h"
16 #include "util/system.h"
17 
18 #include <cstdint>
19 
20 namespace {
21 
22 template <typename Stream, typename Data>
23 bool SerializeDB(Stream& stream, const Data& data)
24 {
25  // Write and commit header, data
26  try {
27  CHashWriter hasher(SER_DISK, CLIENT_VERSION);
28  stream << Params().MessageStart() << data;
29  hasher << Params().MessageStart() << data;
30  stream << hasher.GetHash();
31  } catch (const std::exception& e) {
32  return error("%s: Serialize or I/O error - %s", __func__, e.what());
33  }
34 
35  return true;
36 }
37 
38 template <typename Data>
39 bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
40 {
41  // Generate random temporary filename
42  uint16_t randv = 0;
43  GetRandBytes((unsigned char*)&randv, sizeof(randv));
44  std::string tmpfn = strprintf("%s.%04x", prefix, randv);
45 
46  // open temp output file, and associate with CAutoFile
47  fs::path pathTmp = GetDataDir() / tmpfn;
48  FILE *file = fsbridge::fopen(pathTmp, "wb");
49  CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
50  if (fileout.IsNull()) {
51  fileout.fclose();
52  remove(pathTmp);
53  return error("%s: Failed to open file %s", __func__, pathTmp.string());
54  }
55 
56  // Serialize
57  if (!SerializeDB(fileout, data)) {
58  fileout.fclose();
59  remove(pathTmp);
60  return false;
61  }
62  if (!FileCommit(fileout.Get())) {
63  fileout.fclose();
64  remove(pathTmp);
65  return error("%s: Failed to flush file %s", __func__, pathTmp.string());
66  }
67  fileout.fclose();
68 
69  // replace existing file, if any, with new file
70  if (!RenameOver(pathTmp, path)) {
71  remove(pathTmp);
72  return error("%s: Rename-into-place failed", __func__);
73  }
74 
75  return true;
76 }
77 
78 template <typename Stream, typename Data>
79 bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
80 {
81  try {
82  CHashVerifier<Stream> verifier(&stream);
83  // de-serialize file header (network specific magic number) and ..
84  unsigned char pchMsgTmp[4];
85  verifier >> pchMsgTmp;
86  // ... verify the network matches ours
87  if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)) != 0)
88  return error("%s: Invalid network magic number", __func__);
89 
90  // de-serialize data
91  verifier >> data;
92 
93  // verify checksum
94  if (fCheckSum) {
95  uint256 hashTmp;
96  stream >> hashTmp;
97  if (hashTmp != verifier.GetHash()) {
98  return error("%s: Checksum mismatch, data corrupted", __func__);
99  }
100  }
101  }
102  catch (const std::exception& e) {
103  return error("%s: Deserialize or I/O error - %s", __func__, e.what());
104  }
105 
106  return true;
107 }
108 
109 template <typename Data>
110 bool DeserializeFileDB(const fs::path& path, Data& data)
111 {
112  // open input file, and associate with CAutoFile
113  FILE *file = fsbridge::fopen(path, "rb");
114  CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
115  if (filein.IsNull())
116  return error("%s: Failed to open file %s", __func__, path.string());
117 
118  return DeserializeDB(filein, data);
119 }
120 
121 }
122 
124 {
125  pathBanlist = GetDataDir() / "banlist.dat";
126 }
127 
128 bool CBanDB::Write(const banmap_t& banSet)
129 {
130  return SerializeFileDB("banlist", pathBanlist, banSet);
131 }
132 
133 bool CBanDB::Read(banmap_t& banSet)
134 {
135  return DeserializeFileDB(pathBanlist, banSet);
136 }
137 
139 {
140  pathAddr = GetDataDir() / "peers.dat";
141 }
142 
143 bool CAddrDB::Write(const CAddrMan& addr)
144 {
145  return SerializeFileDB("peers", pathAddr, addr);
146 }
147 
149 {
150  return DeserializeFileDB(pathAddr, addr);
151 }
152 
153 bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
154 {
155  bool ret = DeserializeDB(ssPeers, addr, false);
156  if (!ret) {
157  // Ensure addrman is left in a clean state
158  addr.Clear();
159  }
160  return ret;
161 }
std::map< CSubNet, CBanEntry > banmap_t
Definition: addrdb.h:71
const CChainParams & Params()
Return the currently selected parameters.
fs::path pathAddr
Definition: addrdb.h:77
bool Write(const CAddrMan &addr)
Definition: addrdb.cpp:143
bool Read(CAddrMan &addr)
Definition: addrdb.cpp:148
CAddrDB()
Definition: addrdb.cpp:138
Stochastical (IP) address manager.
Definition: addrman.h:178
void Clear()
Definition: addrman.h:568
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:452
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:128
fs::path pathBanlist
Definition: addrdb.h:90
bool Read(banmap_t &banSet)
Definition: addrdb.cpp:133
CBanDB()
Definition: addrdb.cpp:123
const CMessageHeader::MessageStartChars & MessageStart() const
Definition: chainparams.h:73
Reads data from an underlying stream, while hashing the read data.
Definition: hash.h:255
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:216
256-bit opaque blob.
Definition: uint256.h:138
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:23
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:579
const char * prefix
Definition: rest.cpp:564
@ SER_DISK
Definition: serialize.h:175
bool RenameOver(fs::path src, fs::path dest)
Definition: system.cpp:875
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:724
bool FileCommit(FILE *file)
Definition: system.cpp:904
bool error(const char *fmt, const Args &... args)
Definition: system.h:77
#define strprintf
Definition: tinyformat.h:1056