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