Line data Source code
1 : // Copyright (c) 2014-2015 The Dash developers
2 : // Copyright (c) 2015-2021 The PIVX Core developers
3 : // Distributed under the MIT/X11 software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "budget/budgetdb.h"
7 :
8 : #include "chainparams.h"
9 : #include "clientversion.h"
10 :
11 : static const int BUDGET_DB_VERSION = 1;
12 :
13 : //
14 : // CBudgetDB
15 : //
16 :
17 733 : CBudgetDB::CBudgetDB()
18 : {
19 733 : pathDB = GetDataDir() / "budget.dat";
20 733 : strMagicMessage = "MasternodeBudget";
21 733 : }
22 :
23 378 : bool CBudgetDB::Write(const CBudgetManager& objToSave)
24 : {
25 378 : int64_t nStart = GetTimeMillis();
26 :
27 : // serialize, checksum data up to that point, then append checksum
28 756 : CDataStream ssObj(SER_DISK, CLIENT_VERSION);
29 378 : ssObj << BUDGET_DB_VERSION;
30 378 : ssObj << strMagicMessage; // masternode cache file specific magic message
31 378 : ssObj << Params().MessageStart(); // network specific magic number
32 378 : ssObj << objToSave;
33 378 : uint256 hash = Hash(ssObj.begin(), ssObj.end());
34 378 : ssObj << hash;
35 :
36 : // open output file, and associate with CAutoFile
37 378 : FILE* file = fsbridge::fopen(pathDB, "wb");
38 756 : CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
39 378 : if (fileout.IsNull())
40 0 : return error("%s : Failed to open file %s", __func__, pathDB.string());
41 :
42 : // Write and commit header, data
43 378 : try {
44 378 : fileout << ssObj;
45 0 : } catch (const std::exception& e) {
46 0 : return error("%s : Serialize or I/O error - %s", __func__, e.what());
47 : }
48 378 : fileout.fclose();
49 :
50 378 : LogPrint(BCLog::MNBUDGET,"Written info to budget.dat %dms\n", GetTimeMillis() - nStart);
51 :
52 : return true;
53 : }
54 :
55 355 : CBudgetDB::ReadResult CBudgetDB::Read(CBudgetManager& objToLoad, bool fDryRun)
56 : {
57 355 : int64_t nStart = GetTimeMillis();
58 : // open input file, and associate with CAutoFile
59 355 : FILE* file = fsbridge::fopen(pathDB, "rb");
60 710 : CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
61 355 : if (filein.IsNull()) {
62 273 : error("%s : Failed to open file %s", __func__, pathDB.string());
63 : return FileError;
64 : }
65 :
66 : // use file size to size memory buffer
67 82 : int fileSize = fs::file_size(pathDB);
68 82 : int dataSize = fileSize - sizeof(uint256);
69 : // Don't try to resize to a negative number if file is small
70 82 : if (dataSize < 0)
71 0 : dataSize = 0;
72 437 : std::vector<unsigned char> vchData;
73 82 : vchData.resize(dataSize);
74 82 : uint256 hashIn;
75 :
76 : // read data and checksum from file
77 82 : try {
78 82 : filein.read((char*)vchData.data(), dataSize);
79 82 : filein >> hashIn;
80 0 : } catch (const std::exception& e) {
81 0 : error("%s : Deserialize or I/O error - %s", __func__, e.what());
82 0 : return HashReadError;
83 : }
84 82 : filein.fclose();
85 :
86 164 : CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
87 :
88 : // verify stored checksum matches input data
89 82 : uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
90 82 : if (hashIn != hashTmp) {
91 0 : error("%s : Checksum mismatch, data corrupted", __func__);
92 : return IncorrectHash;
93 : }
94 :
95 82 : int version;
96 164 : std::string strMagicMessageTmp;
97 82 : try {
98 : // de-serialize file header
99 82 : ssObj >> version;
100 82 : ssObj >> strMagicMessageTmp;
101 :
102 : // ... verify the message matches predefined one
103 82 : if (strMagicMessage != strMagicMessageTmp) {
104 0 : error("%s : Invalid masternode cache magic message", __func__);
105 0 : return IncorrectMagicMessage;
106 : }
107 :
108 : // de-serialize file header (network specific magic number) and ..
109 82 : std::vector<unsigned char> pchMsgTmp(4);
110 82 : ssObj >> MakeSpan(pchMsgTmp);
111 :
112 : // ... verify the network matches ours
113 82 : if (memcmp(pchMsgTmp.data(), Params().MessageStart(), pchMsgTmp.size()) != 0) {
114 0 : error("%s : Invalid network magic number", __func__);
115 0 : return IncorrectMagicNumber;
116 : }
117 :
118 : // de-serialize data into CBudgetManager object
119 82 : ssObj >> objToLoad;
120 0 : } catch (const std::exception& e) {
121 0 : objToLoad.Clear();
122 0 : error("%s : Deserialize or I/O error - %s", __func__, e.what());
123 0 : return IncorrectFormat;
124 : }
125 :
126 82 : LogPrint(BCLog::MNBUDGET,"Loaded info from budget.dat (dbversion=%d) %dms\n", version, GetTimeMillis() - nStart);
127 164 : LogPrint(BCLog::MNBUDGET,"%s\n", objToLoad.ToString());
128 82 : if (!fDryRun) {
129 54 : LogPrint(BCLog::MNBUDGET,"Budget manager - cleaning....\n");
130 54 : objToLoad.CheckAndRemove();
131 108 : LogPrint(BCLog::MNBUDGET,"Budget manager - result: %s\n", objToLoad.ToString());
132 : }
133 :
134 : return Ok;
135 : }
136 :
137 378 : void DumpBudgets(CBudgetManager& budgetman)
138 : {
139 378 : int64_t nStart = GetTimeMillis();
140 :
141 756 : CBudgetDB budgetdb;
142 378 : LogPrint(BCLog::MNBUDGET,"Writing info to budget.dat...\n");
143 378 : budgetdb.Write(budgetman);
144 :
145 378 : LogPrint(BCLog::MNBUDGET,"Budget dump finished %dms\n", GetTimeMillis() - nStart);
146 378 : }
|