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"
15 #include "tinyformat.h"
20 template <typename Stream
, typename Data
>
21 bool SerializeDB(Stream
& stream
, const Data
& data
)
23 // Write and commit header, data
25 CHashWriter
hasher(SER_DISK
, CLIENT_VERSION
);
26 stream
<< FLATDATA(Params().MessageStart()) << data
;
27 hasher
<< FLATDATA(Params().MessageStart()) << data
;
28 stream
<< hasher
.GetHash();
29 } catch (const std::exception
& e
) {
30 return error("%s: Serialize or I/O error - %s", __func__
, e
.what());
36 template <typename Data
>
37 bool SerializeFileDB(const std::string
& prefix
, const fs::path
& path
, const Data
& data
)
39 // Generate random temporary filename
40 unsigned short randv
= 0;
41 GetRandBytes((unsigned char*)&randv
, sizeof(randv
));
42 std::string tmpfn
= strprintf("%s.%04x", prefix
, randv
);
44 // open temp output file, and associate with CAutoFile
45 fs::path pathTmp
= GetDataDir() / tmpfn
;
46 FILE *file
= fsbridge::fopen(pathTmp
, "wb");
47 CAutoFile
fileout(file
, SER_DISK
, CLIENT_VERSION
);
49 return error("%s: Failed to open file %s", __func__
, pathTmp
.string());
52 if (!SerializeDB(fileout
, data
)) return false;
53 FileCommit(fileout
.Get());
56 // replace existing file, if any, with new file
57 if (!RenameOver(pathTmp
, path
))
58 return error("%s: Rename-into-place failed", __func__
);
63 template <typename Stream
, typename Data
>
64 bool DeserializeDB(Stream
& stream
, Data
& data
, bool fCheckSum
= true)
67 CHashVerifier
<Stream
> verifier(&stream
);
68 // de-serialize file header (network specific magic number) and ..
69 unsigned char pchMsgTmp
[4];
70 verifier
>> FLATDATA(pchMsgTmp
);
71 // ... verify the network matches ours
72 if (memcmp(pchMsgTmp
, Params().MessageStart(), sizeof(pchMsgTmp
)))
73 return error("%s: Invalid network magic number", __func__
);
82 if (hashTmp
!= verifier
.GetHash()) {
83 return error("%s: Checksum mismatch, data corrupted", __func__
);
87 catch (const std::exception
& e
) {
88 return error("%s: Deserialize or I/O error - %s", __func__
, e
.what());
94 template <typename Data
>
95 bool DeserializeFileDB(const fs::path
& path
, Data
& data
)
97 // open input file, and associate with CAutoFile
98 FILE *file
= fsbridge::fopen(path
, "rb");
99 CAutoFile
filein(file
, SER_DISK
, CLIENT_VERSION
);
101 return error("%s: Failed to open file %s", __func__
, path
.string());
103 return DeserializeDB(filein
, data
);
110 pathBanlist
= GetDataDir() / "banlist.dat";
113 bool CBanDB::Write(const banmap_t
& banSet
)
115 return SerializeFileDB("banlist", pathBanlist
, banSet
);
118 bool CBanDB::Read(banmap_t
& banSet
)
120 return DeserializeFileDB(pathBanlist
, banSet
);
125 pathAddr
= GetDataDir() / "peers.dat";
128 bool CAddrDB::Write(const CAddrMan
& addr
)
130 return SerializeFileDB("peers", pathAddr
, addr
);
133 bool CAddrDB::Read(CAddrMan
& addr
)
135 return DeserializeFileDB(pathAddr
, addr
);
138 bool CAddrDB::Read(CAddrMan
& addr
, CDataStream
& ssPeers
)
140 bool ret
= DeserializeDB(ssPeers
, addr
, false);
142 // Ensure addrman is left in a clean state