]> Git Repo - VerusCoin.git/blame - src/wallet-utility.cpp
improve check
[VerusCoin.git] / src / wallet-utility.cpp
CommitLineData
8b78a819
T
1#include <iostream>
2#include <string>
3
4// Include local headers
5#include "wallet/walletdb.h"
6#include "util.h"
7#include "base58.h"
8#include "wallet/crypter.h"
9#include <boost/foreach.hpp>
10
60eafafa 11#include "komodo_defs.h"
12char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
b2a98c42
MT
13bool PBAAS_TESTMODE;
14uint160 ASSETCHAINS_CHAINID;
15uint160 VERUS_CHAINID;
60eafafa 16int64_t MAX_MONEY = 200000000 * 100000000LL;
6e0857ce 17uint64_t ASSETCHAINS_SUPPLY;
05c2ba63 18uint16_t BITCOIND_RPCPORT = 7771;
19uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
6e0857ce 20uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC;
21uint32_t ASSETCHAINS_MAGIC = 2387029918;
48d800c2 22uint32_t ASSETCHAINS_EQUIHASH = 0;
e980a26d 23uint32_t ASSETCHAINS_VERUSHASH = 1;
48d800c2 24uint32_t ASSETCHAINS_ALGO = 0;
1f722359
MT
25int32_t ASSETCHAINS_LWMAPOS = 0;
26int32_t VERUS_BLOCK_POSUNITS = 1000;
ceaccb0c 27int32_t ASSETCHAINS_OVERWINTER = 227520;
4b729ec5 28int32_t ASSETCHAINS_SAPLING = 227520;
8fc4030c 29boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
10214558 30std::string VERUS_CHEATCATCHER = "";
48d800c2 31
5725f8ea 32unsigned int MAX_BLOCK_SIGOPS = 20000;
8b78a819
T
33
34void show_help()
35{
36 std::cout <<
37 "This program outputs Bitcoin addresses and private keys from a wallet.dat file" << std::endl
38 << std::endl
39 << "Usage and options: "
40 << std::endl
41 << " -datadir=<directory> to tell the program where your wallet is"
42 << std::endl
43 << " -wallet=<name> (Optional) if your wallet is not named wallet.dat"
44 << std::endl
45 << " -regtest or -testnet (Optional) dumps addresses from regtest/testnet"
46 << std::endl
47 << " -dumppass (Optional)if you want to extract private keys associated with addresses"
48 << std::endl
49 << " -pass=<walletpassphrase> if you have encrypted private keys stored in your wallet"
50 << std::endl;
51}
52
53
54class WalletUtilityDB : public CDB
55{
56 private:
57 typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
58 MasterKeyMap mapMasterKeys;
59 unsigned int nMasterKeyMaxID;
60 SecureString mPass;
61 std::vector<CKeyingMaterial> vMKeys;
62
63 public:
64 WalletUtilityDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnClose = true) : CDB(strFilename, pszMode, fFlushOnClose)
65 {
66 nMasterKeyMaxID = 0;
67 mPass.reserve(100);
68 }
69
70 std::string getAddress(CDataStream ssKey);
71 std::string getKey(CDataStream ssKey, CDataStream ssValue);
72 std::string getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass);
73 bool updateMasterKeys(CDataStream ssKey, CDataStream ssValue);
74 bool parseKeys(bool dumppriv, std::string masterPass);
75
76 bool DecryptSecret(const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
77 bool Unlock();
78 bool DecryptKey(const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key);
79};
80
81
82/*
83 * Address from a public key in base58
84 */
85std::string WalletUtilityDB::getAddress(CDataStream ssKey)
86{
87 CPubKey vchPubKey;
88 ssKey >> vchPubKey;
89 CKeyID id = vchPubKey.GetID();
90 std::string strAddr = CBitcoinAddress(id).ToString();
91
92 return strAddr;
93}
94
95
96/*
97 * Non encrypted private key in WIF
98 */
99std::string WalletUtilityDB::getKey(CDataStream ssKey, CDataStream ssValue)
100{
101 std::string strKey;
102 CPubKey vchPubKey;
103 ssKey >> vchPubKey;
104 CPrivKey pkey;
105 CKey key;
106
107 ssValue >> pkey;
108 if (key.Load(pkey, vchPubKey, true))
109 strKey = CBitcoinSecret(key).ToString();
110
111 return strKey;
112}
113
114
115bool WalletUtilityDB::DecryptSecret(const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
116{
117 CCrypter cKeyCrypter;
118 std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
119 memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
120
121 BOOST_FOREACH(const CKeyingMaterial vMKey, vMKeys)
122 {
123 if(!cKeyCrypter.SetKey(vMKey, chIV))
124 continue;
125 if (cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)))
126 return true;
127 }
128 return false;
129}
130
131
132bool WalletUtilityDB::Unlock()
133{
134 CCrypter crypter;
135 CKeyingMaterial vMasterKey;
136
137 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
138 {
139 if(!crypter.SetKeyFromPassphrase(mPass, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
140 return false;
141 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
142 continue; // try another master key
143 vMKeys.push_back(vMasterKey);
144 }
145 return true;
146}
147
148
149bool WalletUtilityDB::DecryptKey(const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key)
150{
151 CKeyingMaterial vchSecret;
152 if(!DecryptSecret(vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
153 return false;
154
155 if (vchSecret.size() != 32)
156 return false;
157
158 key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
159 return true;
160}
161
162
163/*
164 * Encrypted private key in WIF format
165 */
166std::string WalletUtilityDB::getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass)
167{
168 mPass = masterPass.c_str();
169 CPubKey vchPubKey;
170 ssKey >> vchPubKey;
171 CKey key;
172
173 std::vector<unsigned char> vKey;
174 ssValue >> vKey;
175
176 if (!Unlock())
177 return "";
178
179 if(!DecryptKey(vKey, vchPubKey, key))
180 return "";
181
182 std::string strKey = CBitcoinSecret(key).ToString();
183 return strKey;
184}
185
186
187/*
188 * Master key derivation
189 */
190bool WalletUtilityDB::updateMasterKeys(CDataStream ssKey, CDataStream ssValue)
191{
192 unsigned int nID;
193 ssKey >> nID;
194 CMasterKey kMasterKey;
195 ssValue >> kMasterKey;
196 if (mapMasterKeys.count(nID) != 0)
197 {
198 std::cout << "Error reading wallet database: duplicate CMasterKey id " << nID << std::endl;
199 return false;
200 }
201 mapMasterKeys[nID] = kMasterKey;
202
203 if (nMasterKeyMaxID < nID)
204 nMasterKeyMaxID = nID;
205
206 return true;
207}
208
209
210/*
211 * Look at all the records and parse keys for addresses and private keys
212 */
213bool WalletUtilityDB::parseKeys(bool dumppriv, std::string masterPass)
214{
215 DBErrors result = DB_LOAD_OK;
216 std::string strType;
217 bool first = true;
218
219 try {
220 Dbc* pcursor = GetCursor();
221 if (!pcursor)
222 {
223 LogPrintf("Error getting wallet database cursor\n");
224 result = DB_CORRUPT;
225 }
226
227 if (dumppriv)
228 {
229 while (result == DB_LOAD_OK && true)
230 {
231 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
232 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
233 int result = ReadAtCursor(pcursor, ssKey, ssValue);
234
235 if (result == DB_NOTFOUND) {
236 break;
237 }
238 else if (result != 0)
239 {
240 LogPrintf("Error reading next record from wallet database\n");
241 result = DB_CORRUPT;
242 break;
243 }
244
245 ssKey >> strType;
246 if (strType == "mkey")
247 {
248 updateMasterKeys(ssKey, ssValue);
249 }
250 }
251 pcursor->close();
252 pcursor = GetCursor();
253 }
254
255 while (result == DB_LOAD_OK && true)
256 {
257 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
258 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
259 int ret = ReadAtCursor(pcursor, ssKey, ssValue);
260
261 if (ret == DB_NOTFOUND)
262 {
263 std::cout << " ]" << std::endl;
264 first = true;
265 break;
266 }
267 else if (ret != DB_LOAD_OK)
268 {
269 LogPrintf("Error reading next record from wallet database\n");
270 result = DB_CORRUPT;
271 break;
272 }
273
274 ssKey >> strType;
275
276 if (strType == "key" || strType == "ckey")
277 {
278 std::string strAddr = getAddress(ssKey);
279 std::string strKey = "";
280
281
282 if (dumppriv && strType == "key")
283 strKey = getKey(ssKey, ssValue);
284 if (dumppriv && strType == "ckey")
285 {
286 if (masterPass == "")
287 {
288 std::cout << "Encrypted wallet, please provide a password. See help below" << std::endl;
289 show_help();
290 result = DB_LOAD_FAIL;
291 break;
292 }
293 strKey = getCryptedKey(ssKey, ssValue, masterPass);
294 }
295
296 if (strAddr != "")
297 {
298 if (first)
299 std::cout << "[ ";
300 else
301 std::cout << ", ";
302 }
303
304 if (dumppriv)
305 {
306 std::cout << "{\"addr\" : \"" + strAddr + "\", "
307 << "\"pkey\" : \"" + strKey + "\"}"
308 << std::flush;
309 }
310 else
311 {
312 std::cout << "\"" + strAddr + "\"";
313 }
314
315 first = false;
316 }
317 }
318
319 pcursor->close();
320 } catch (DbException &e) {
321 std::cout << "DBException caught " << e.get_errno() << std::endl;
322 } catch (std::exception &e) {
323 std::cout << "Exception caught " << std::endl;
324 }
325
326 if (result == DB_LOAD_OK)
327 return true;
328 else
329 return false;
330}
331
332
333int main(int argc, char* argv[])
334{
335 ParseParameters(argc, argv);
336 std::string walletFile = GetArg("-wallet", "wallet.dat");
337 std::string masterPass = GetArg("-pass", "");
338 bool fDumpPass = GetBoolArg("-dumppass", false);
339 bool help = GetBoolArg("-h", false);
340 bool result = false;
341
b2a98c42
MT
342 PBAAS_TESTMODE = false;
343
344
8b78a819
T
345 if (help)
346 {
347 show_help();
348 return 0;
349 }
350
351 try {
352 SelectParamsFromCommandLine();
353 result = WalletUtilityDB(walletFile, "r").parseKeys(fDumpPass, masterPass);
354 }
355 catch (const std::exception& e) {
356 std::cout << "Error opening wallet file " << walletFile << std::endl;
357 std::cout << e.what() << std::endl;
358 }
359
360 if (result)
361 return 0;
362 else
363 return -1;
e8972fab 364}
This page took 0.113556 seconds and 4 git commands to generate.