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