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 608 : CBudgetDB::CBudgetDB()
18 : {
19 608 : pathDB = GetDataDir() / "budget.dat";
20 608 : strMagicMessage = "MasternodeBudget";
21 608 : }
22 :
23 315 : bool CBudgetDB::Write(const CBudgetManager& objToSave)
24 : {
25 315 : int64_t nStart = GetTimeMillis();
26 :
27 : // serialize, checksum data up to that point, then append checksum
28 630 : CDataStream ssObj(SER_DISK, CLIENT_VERSION);
29 315 : ssObj << BUDGET_DB_VERSION;
30 315 : ssObj << strMagicMessage; // masternode cache file specific magic message
31 315 : ssObj << Params().MessageStart(); // network specific magic number
32 315 : ssObj << objToSave;
33 315 : uint256 hash = Hash(ssObj.begin(), ssObj.end());
34 315 : ssObj << hash;
35 :
36 : // open output file, and associate with CAutoFile
37 315 : FILE* file = fsbridge::fopen(pathDB, "wb");
38 630 : CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
39 315 : if (fileout.IsNull())
40 0 : return error("%s : Failed to open file %s", __func__, pathDB.string());
41 :
42 : // Write and commit header, data
43 315 : try {
44 315 : 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 315 : fileout.fclose();
49 :
50 315 : LogPrint(BCLog::MNBUDGET,"Written info to budget.dat %dms\n", GetTimeMillis() - nStart);
51 :
52 : return true;
53 : }
54 :
55 293 : CBudgetDB::ReadResult CBudgetDB::Read(CBudgetManager& objToLoad, bool fDryRun)
56 : {
57 293 : int64_t nStart = GetTimeMillis();
58 : // open input file, and associate with CAutoFile
59 293 : FILE* file = fsbridge::fopen(pathDB, "rb");
60 586 : CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
61 293 : if (filein.IsNull()) {
62 217 : error("%s : Failed to open file %s", __func__, pathDB.string());
63 : return FileError;
64 : }
65 :
66 : // use file size to size memory buffer
67 76 : int fileSize = fs::file_size(pathDB);
68 76 : int dataSize = fileSize - sizeof(uint256);
69 : // Don't try to resize to a negative number if file is small
70 76 : if (dataSize < 0)
71 0 : dataSize = 0;
72 369 : std::vector<unsigned char> vchData;
73 76 : vchData.resize(dataSize);
74 76 : uint256 hashIn;
75 :
76 : // read data and checksum from file
77 76 : try {
78 76 : filein.read((char*)vchData.data(), dataSize);
79 76 : 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 76 : filein.fclose();
85 :
86 152 : CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
87 :
88 : // verify stored checksum matches input data
89 76 : uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
90 76 : if (hashIn != hashTmp) {
91 0 : error("%s : Checksum mismatch, data corrupted", __func__);
92 : return IncorrectHash;
93 : }
94 :
95 76 : int version;
96 152 : std::string strMagicMessageTmp;
97 76 : try {
98 : // de-serialize file header
99 76 : ssObj >> version;
100 76 : ssObj >> strMagicMessageTmp;
101 :
102 : // ... verify the message matches predefined one
103 76 : 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 76 : std::vector<unsigned char> pchMsgTmp(4);
110 76 : ssObj >> MakeSpan(pchMsgTmp);
111 :
112 : // ... verify the network matches ours
113 76 : 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 76 : 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 76 : LogPrint(BCLog::MNBUDGET,"Loaded info from budget.dat (dbversion=%d) %dms\n", version, GetTimeMillis() - nStart);
127 152 : LogPrint(BCLog::MNBUDGET,"%s\n", objToLoad.ToString());
128 76 : if (!fDryRun) {
129 53 : LogPrint(BCLog::MNBUDGET,"Budget manager - cleaning....\n");
130 53 : objToLoad.CheckAndRemove();
131 106 : LogPrint(BCLog::MNBUDGET,"Budget manager - result: %s\n", objToLoad.ToString());
132 : }
133 :
134 : return Ok;
135 : }
136 :
137 315 : void DumpBudgets(CBudgetManager& budgetman)
138 : {
139 315 : int64_t nStart = GetTimeMillis();
140 :
141 630 : CBudgetDB budgetdb;
142 315 : LogPrint(BCLog::MNBUDGET,"Writing info to budget.dat...\n");
143 315 : budgetdb.Write(budgetman);
144 :
145 315 : LogPrint(BCLog::MNBUDGET,"Budget dump finished %dms\n", GetTimeMillis() - nStart);
146 315 : }
|