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