]> Git Repo - VerusCoin.git/blame - src/wallet-utility.cpp
Merge pull request #23 from Asherda/dev
[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;
48d800c2 19uint32_t ASSETCHAINS_EQUIHASH = 0;
e980a26d 20uint32_t ASSETCHAINS_VERUSHASH = 1;
48d800c2 21uint32_t ASSETCHAINS_ALGO = 0;
1f722359
MT
22int32_t ASSETCHAINS_LWMAPOS = 0;
23int32_t VERUS_BLOCK_POSUNITS = 1000;
48d800c2 24
5725f8ea 25unsigned int MAX_BLOCK_SIGOPS = 20000;
8b78a819
T
26
27void 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
47class 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 */
78std::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 */
92std::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
108bool 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
125bool 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
142bool 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 */
159std::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 */
183bool 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 */
206bool 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
326int 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;
e8972fab 354}
This page took 0.11174 seconds and 4 git commands to generate.