Raven Core  3.0.0
P2P Digital Currency
addrdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Copyright (c) 2017-2019 The Raven 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 "fs.h"
13 #include "hash.h"
14 #include "random.h"
15 #include "streams.h"
16 #include "tinyformat.h"
17 #include "util.h"
18 
19 namespace {
20 
21 template <typename Stream, typename Data>
22 bool SerializeDB(Stream& stream, const Data& data)
23 {
24  // Write and commit header, data
25  try {
26  CHashWriter hasher(SER_DISK, CLIENT_VERSION);
27  stream << FLATDATA(Params().MessageStart()) << data;
28  hasher << FLATDATA(Params().MessageStart()) << data;
29  stream << hasher.GetHash();
30  } catch (const std::exception& e) {
31  return error("%s: Serialize or I/O error - %s", __func__, e.what());
32  }
33 
34  return true;
35 }
36 
37 template <typename Data>
38 bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
39 {
40  // Generate random temporary filename
41  unsigned short randv = 0;
42  GetRandBytes((unsigned char*)&randv, sizeof(randv));
43  std::string tmpfn = strprintf("%s.%04x", prefix, randv);
44 
45  // open temp output file, and associate with CAutoFile
46  fs::path pathTmp = GetDataDir() / tmpfn;
47  FILE *file = fsbridge::fopen(pathTmp, "wb");
48  CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
49  if (fileout.IsNull())
50  return error("%s: Failed to open file %s", __func__, pathTmp.string());
51 
52  // Serialize
53  if (!SerializeDB(fileout, data)) return false;
54  FileCommit(fileout.Get());
55  fileout.fclose();
56 
57  // replace existing file, if any, with new file
58  if (!RenameOver(pathTmp, path))
59  return error("%s: Rename-into-place failed", __func__);
60 
61  return true;
62 }
63 
64 template <typename Stream, typename Data>
65 bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
66 {
67  try {
68  CHashVerifier<Stream> verifier(&stream);
69  // de-serialize file header (network specific magic number) and ..
70  unsigned char pchMsgTmp[4];
71  verifier >> FLATDATA(pchMsgTmp);
72  // ... verify the network matches ours
73  if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
74  return error("%s: Invalid network magic number", __func__);
75 
76  // de-serialize data
77  verifier >> data;
78 
79  // verify checksum
80  if (fCheckSum) {
81  uint256 hashTmp;
82  stream >> hashTmp;
83  if (hashTmp != verifier.GetHash()) {
84  return error("%s: Checksum mismatch, data corrupted", __func__);
85  }
86  }
87  }
88  catch (const std::exception& e) {
89  return error("%s: Deserialize or I/O error - %s", __func__, e.what());
90  }
91 
92  return true;
93 }
94 
95 template <typename Data>
96 bool DeserializeFileDB(const fs::path& path, Data& data)
97 {
98  // open input file, and associate with CAutoFile
99  FILE *file = fsbridge::fopen(path, "rb");
100  CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
101  if (filein.IsNull())
102  return error("%s: Failed to open file %s", __func__, path.string());
103 
104  return DeserializeDB(filein, data);
105 }
106 
107 }
108 
110 {
111  pathBanlist = GetDataDir() / "banlist.dat";
112 }
113 
114 bool CBanDB::Write(const banmap_t& banSet)
115 {
116  return SerializeFileDB("banlist", pathBanlist, banSet);
117 }
118 
119 bool CBanDB::Read(banmap_t& banSet)
120 {
121  return DeserializeFileDB(pathBanlist, banSet);
122 }
123 
125 {
126  pathAddr = GetDataDir() / "peers.dat";
127 }
128 
129 bool CAddrDB::Write(const CAddrMan& addr)
130 {
131  return SerializeFileDB("peers", pathAddr, addr);
132 }
133 
135 {
136  return DeserializeFileDB(pathAddr, addr);
137 }
138 
139 bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
140 {
141  bool ret = DeserializeDB(ssPeers, addr, false);
142  if (!ret) {
143  // Ensure addrman is left in a clean state
144  addr.Clear();
145  }
146  return ret;
147 }
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:5
void FileCommit(FILE *file)
Definition: util.cpp:699
CBanDB()
Definition: addrdb.cpp:109
#define strprintf
Definition: tinyformat.h:1054
CAddrDB()
Definition: addrdb.cpp:124
const char * prefix
Definition: rest.cpp:568
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:147
#define FLATDATA(obj)
Definition: serialize.h:366
Reads data from an underlying stream, while hashing the read data.
Definition: hash.h:266
Stochastical (IP) address manager.
Definition: addrman.h:183
std::map< CSubNet, CBanEntry > banmap_t
Definition: addrdb.h:78
bool Write(const CAddrMan &addr)
Definition: addrdb.cpp:129
bool RenameOver(fs::path src, fs::path dest)
Definition: util.cpp:668
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:114
fs::path pathBanlist
Definition: addrdb.h:96
bool Read(banmap_t &banSet)
Definition: addrdb.cpp:119
256-bit opaque blob.
Definition: uint256.h:123
void Clear()
Definition: addrman.h:457
const CChainParams & Params()
Return the currently selected parameters.
void GetRandBytes(unsigned char *buf, int num)
Functions to gather random data via the OpenSSL PRNG.
Definition: random.cpp:274
bool error(const char *fmt, const Args &... args)
Definition: util.h:168
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:231
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:572
bool Read(CAddrMan &addr)
Definition: addrdb.cpp:134
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:456