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