1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
9 #include <chainparams.h>
10 #include <clientversion.h>
14 #include <tinyformat.h>
19 template <typename Stream
, typename Data
>
20 bool SerializeDB(Stream
& stream
, const Data
& data
)
22 // Write and commit header, data
24 CHashWriter
hasher(SER_DISK
, CLIENT_VERSION
);
25 stream
<< FLATDATA(Params().MessageStart()) << data
;
26 hasher
<< FLATDATA(Params().MessageStart()) << data
;
27 stream
<< hasher
.GetHash();
28 } catch (const std::exception
& e
) {
29 return error("%s: Serialize or I/O error - %s", __func__
, e
.what());
35 template <typename Data
>
36 bool SerializeFileDB(const std::string
& prefix
, const fs::path
& path
, const Data
& data
)
38 // Generate random temporary filename
39 unsigned short randv
= 0;
40 GetRandBytes((unsigned char*)&randv
, sizeof(randv
));
41 std::string tmpfn
= strprintf("%s.%04x", prefix
, randv
);
43 // open temp output file, and associate with CAutoFile
44 fs::path pathTmp
= GetDataDir() / tmpfn
;
45 FILE *file
= fsbridge::fopen(pathTmp
, "wb");
46 CAutoFile
fileout(file
, SER_DISK
, CLIENT_VERSION
);
48 return error("%s: Failed to open file %s", __func__
, pathTmp
.string());
51 if (!SerializeDB(fileout
, data
)) return false;
52 FileCommit(fileout
.Get());
55 // replace existing file, if any, with new file
56 if (!RenameOver(pathTmp
, path
))
57 return error("%s: Rename-into-place failed", __func__
);
62 template <typename Stream
, typename Data
>
63 bool DeserializeDB(Stream
& stream
, Data
& data
, bool fCheckSum
= true)
66 CHashVerifier
<Stream
> verifier(&stream
);
67 // de-serialize file header (network specific magic number) and ..
68 unsigned char pchMsgTmp
[4];
69 verifier
>> FLATDATA(pchMsgTmp
);
70 // ... verify the network matches ours
71 if (memcmp(pchMsgTmp
, Params().MessageStart(), sizeof(pchMsgTmp
)))
72 return error("%s: Invalid network magic number", __func__
);
81 if (hashTmp
!= verifier
.GetHash()) {
82 return error("%s: Checksum mismatch, data corrupted", __func__
);
86 catch (const std::exception
& e
) {
87 return error("%s: Deserialize or I/O error - %s", __func__
, e
.what());
93 template <typename Data
>
94 bool DeserializeFileDB(const fs::path
& path
, Data
& data
)
96 // open input file, and associate with CAutoFile
97 FILE *file
= fsbridge::fopen(path
, "rb");
98 CAutoFile
filein(file
, SER_DISK
, CLIENT_VERSION
);
100 return error("%s: Failed to open file %s", __func__
, path
.string());
102 return DeserializeDB(filein
, data
);
109 pathBanlist
= GetDataDir() / "banlist.dat";
112 bool CBanDB::Write(const banmap_t
& banSet
)
114 return SerializeFileDB("banlist", pathBanlist
, banSet
);
117 bool CBanDB::Read(banmap_t
& banSet
)
119 return DeserializeFileDB(pathBanlist
, banSet
);
124 pathAddr
= GetDataDir() / "peers.dat";
127 bool CAddrDB::Write(const CAddrMan
& addr
)
129 return SerializeFileDB("peers", pathAddr
, addr
);
132 bool CAddrDB::Read(CAddrMan
& addr
)
134 return DeserializeFileDB(pathAddr
, addr
);
137 bool CAddrDB::Read(CAddrMan
& addr
, CDataStream
& ssPeers
)
139 bool ret
= DeserializeDB(ssPeers
, addr
, false);
141 // Ensure addrman is left in a clean state