]> Git Repo - VerusCoin.git/blame - src/wallet.cpp
Merge pull request #3021 from Diapolo/fix_extract_strings_qt
[VerusCoin.git] / src / wallet.cpp
CommitLineData
b2120e22 1// Copyright (c) 2009-2010 Satoshi Nakamoto
88216419 2// Copyright (c) 2009-2012 The Bitcoin developers
e8ef3da7 3// Distributed under the MIT/X11 software license, see the accompanying
3a25a2b9 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
e8ef3da7 5
9eace6b1
JG
6#include "wallet.h"
7#include "walletdb.h"
4e87d341 8#include "crypter.h"
6b6aaa16 9#include "ui_interface.h"
10254401 10#include "base58.h"
cae686d3 11#include <boost/algorithm/string/replace.hpp>
e8ef3da7
WL
12
13using namespace std;
14
15
e8ef3da7
WL
16//////////////////////////////////////////////////////////////////////////////
17//
18// mapWallet
19//
20
d650f96d
CM
21struct CompareValueOnly
22{
23 bool operator()(const pair<int64, pair<const CWalletTx*, unsigned int> >& t1,
24 const pair<int64, pair<const CWalletTx*, unsigned int> >& t2) const
25 {
26 return t1.first < t2.first;
27 }
28};
29
fd61d6f5 30CPubKey CWallet::GenerateNewKey()
9976cf07 31{
439e1497 32 bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
38067c18 33
9976cf07 34 RandAddSeedPerfmon();
dfa23b94
PW
35 CKey secret;
36 secret.MakeNewKey(fCompressed);
38067c18
PW
37
38 // Compressed public keys were introduced in version 0.6.0
39 if (fCompressed)
439e1497 40 SetMinVersion(FEATURE_COMPRPUBKEY);
38067c18 41
dfa23b94 42 CPubKey pubkey = secret.GetPubKey();
4addb2c0
PW
43
44 // Create new metadata
45 int64 nCreationTime = GetTime();
46 mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
47 if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
48 nTimeFirstKey = nCreationTime;
49
dfa23b94 50 if (!AddKeyPubKey(secret, pubkey))
9976cf07 51 throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
dfa23b94 52 return pubkey;
9976cf07 53}
e8ef3da7 54
4addb2c0 55bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
e8ef3da7 56{
dfa23b94 57 if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
acd65016 58 return false;
e8ef3da7
WL
59 if (!fFileBacked)
60 return true;
dfa23b94 61 if (!IsCrypted()) {
3869fb89
JG
62 return CWalletDB(strWalletFile).WriteKey(pubkey,
63 secret.GetPrivKey(),
4addb2c0 64 mapKeyMetadata[pubkey.GetID()]);
dfa23b94 65 }
84c3c2eb 66 return true;
4e87d341
MC
67}
68
3869fb89 69bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
4addb2c0 70 const vector<unsigned char> &vchCryptedSecret)
4e87d341
MC
71{
72 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
73 return false;
74 if (!fFileBacked)
75 return true;
96f34cd5 76 {
f8dcd5ca 77 LOCK(cs_wallet);
96f34cd5 78 if (pwalletdbEncryption)
3869fb89
JG
79 return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
80 vchCryptedSecret,
4addb2c0 81 mapKeyMetadata[vchPubKey.GetID()]);
96f34cd5 82 else
3869fb89
JG
83 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
84 vchCryptedSecret,
4addb2c0 85 mapKeyMetadata[vchPubKey.GetID()]);
96f34cd5 86 }
0767e691 87 return false;
4e87d341
MC
88}
89
4addb2c0
PW
90bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
91{
92 if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
93 nTimeFirstKey = meta.nCreateTime;
94
95 mapKeyMetadata[pubkey.GetID()] = meta;
96 return true;
97}
98
2f15e86a
GA
99bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
100{
101 return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
102}
103
922e8e29 104bool CWallet::AddCScript(const CScript& redeemScript)
e679ec96 105{
922e8e29 106 if (!CCryptoKeyStore::AddCScript(redeemScript))
e679ec96
GA
107 return false;
108 if (!fFileBacked)
109 return true;
922e8e29 110 return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
e679ec96
GA
111}
112
94f778bd 113bool CWallet::Unlock(const SecureString& strWalletPassphrase)
4e87d341 114{
6cc4a62c
GA
115 CCrypter crypter;
116 CKeyingMaterial vMasterKey;
4e87d341 117
f8dcd5ca
PW
118 {
119 LOCK(cs_wallet);
4e87d341
MC
120 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
121 {
122 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
123 return false;
124 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
92f2c1fe 125 continue; // try another master key
4e87d341
MC
126 if (CCryptoKeyStore::Unlock(vMasterKey))
127 return true;
128 }
f8dcd5ca 129 }
4e87d341
MC
130 return false;
131}
132
94f778bd 133bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
4e87d341 134{
6cc4a62c 135 bool fWasLocked = IsLocked();
4e87d341 136
6cc4a62c 137 {
f8dcd5ca 138 LOCK(cs_wallet);
4e87d341
MC
139 Lock();
140
141 CCrypter crypter;
142 CKeyingMaterial vMasterKey;
143 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
144 {
145 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
146 return false;
6cc4a62c 147 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
4e87d341
MC
148 return false;
149 if (CCryptoKeyStore::Unlock(vMasterKey))
150 {
bde280b9 151 int64 nStartTime = GetTimeMillis();
ddebdd9a
MC
152 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
153 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
154
155 nStartTime = GetTimeMillis();
156 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
157 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
158
159 if (pMasterKey.second.nDeriveIterations < 25000)
160 pMasterKey.second.nDeriveIterations = 25000;
161
881a85a2 162 LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
ddebdd9a 163
4e87d341
MC
164 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
165 return false;
166 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
167 return false;
168 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
169 if (fWasLocked)
170 Lock();
171 return true;
172 }
173 }
174 }
6cc4a62c 175
4e87d341
MC
176 return false;
177}
178
ed6d0b5f
PW
179void CWallet::SetBestChain(const CBlockLocator& loc)
180{
181 CWalletDB walletdb(strWalletFile);
182 walletdb.WriteBestBlock(loc);
183}
7414733b
MC
184
185// This class implements an addrIncoming entry that causes pre-0.4
186// clients to crash on startup if reading a private-key-encrypted wallet.
187class CCorruptAddress
188{
189public:
190 IMPLEMENT_SERIALIZE
191 (
192 if (nType & SER_DISK)
193 READWRITE(nVersion);
194 )
195};
196
439e1497 197bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
0b807a41
PW
198{
199 if (nWalletVersion >= nVersion)
200 return true;
201
439e1497
PW
202 // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
203 if (fExplicit && nVersion > nWalletMaxVersion)
204 nVersion = FEATURE_LATEST;
205
0b807a41
PW
206 nWalletVersion = nVersion;
207
439e1497
PW
208 if (nVersion > nWalletMaxVersion)
209 nWalletMaxVersion = nVersion;
210
0b807a41
PW
211 if (fFileBacked)
212 {
213 CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
214 if (nWalletVersion >= 40000)
215 {
216 // Versions prior to 0.4.0 did not support the "minversion" record.
217 // Use a CCorruptAddress to make them crash instead.
218 CCorruptAddress corruptAddress;
219 pwalletdb->WriteSetting("addrIncoming", corruptAddress);
220 }
221 if (nWalletVersion > 40000)
222 pwalletdb->WriteMinVersion(nWalletVersion);
223 if (!pwalletdbIn)
224 delete pwalletdb;
225 }
226
227 return true;
228}
229
439e1497
PW
230bool CWallet::SetMaxVersion(int nVersion)
231{
232 // cannot downgrade below current version
233 if (nWalletVersion > nVersion)
234 return false;
235
236 nWalletMaxVersion = nVersion;
237
238 return true;
239}
240
94f778bd 241bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
4e87d341 242{
6cc4a62c
GA
243 if (IsCrypted())
244 return false;
4e87d341 245
6cc4a62c
GA
246 CKeyingMaterial vMasterKey;
247 RandAddSeedPerfmon();
4e87d341 248
6cc4a62c
GA
249 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
250 RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
4e87d341 251
6cc4a62c 252 CMasterKey kMasterKey;
4e87d341 253
6cc4a62c
GA
254 RandAddSeedPerfmon();
255 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
256 RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
4e87d341 257
6cc4a62c 258 CCrypter crypter;
bde280b9 259 int64 nStartTime = GetTimeMillis();
6cc4a62c
GA
260 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
261 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
ddebdd9a 262
6cc4a62c
GA
263 nStartTime = GetTimeMillis();
264 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
265 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
ddebdd9a 266
6cc4a62c
GA
267 if (kMasterKey.nDeriveIterations < 25000)
268 kMasterKey.nDeriveIterations = 25000;
ddebdd9a 269
881a85a2 270 LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
ddebdd9a 271
6cc4a62c
GA
272 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
273 return false;
274 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
275 return false;
4e87d341 276
6cc4a62c 277 {
f8dcd5ca 278 LOCK(cs_wallet);
4e87d341
MC
279 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
280 if (fFileBacked)
281 {
96f34cd5 282 pwalletdbEncryption = new CWalletDB(strWalletFile);
0fb78eae
JG
283 if (!pwalletdbEncryption->TxnBegin())
284 return false;
96f34cd5 285 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
4e87d341
MC
286 }
287
288 if (!EncryptKeys(vMasterKey))
96f34cd5
MC
289 {
290 if (fFileBacked)
291 pwalletdbEncryption->TxnAbort();
292 exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
293 }
294
0b807a41 295 // Encryption was introduced in version 0.4.0
439e1497 296 SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
0b807a41 297
96f34cd5
MC
298 if (fFileBacked)
299 {
300 if (!pwalletdbEncryption->TxnCommit())
301 exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
302
fcfd7ff8 303 delete pwalletdbEncryption;
96f34cd5
MC
304 pwalletdbEncryption = NULL;
305 }
4e87d341 306
37971fcc
GA
307 Lock();
308 Unlock(strWalletPassphrase);
309 NewKeyPool();
4e87d341 310 Lock();
6cc4a62c 311
d764d916
GA
312 // Need to completely rewrite the wallet file; if we don't, bdb might keep
313 // bits of the unencrypted private key in slack space in the database file.
b2d3b2d6 314 CDB::Rewrite(strWalletFile);
fe4a6550 315
d764d916 316 }
ab1b288f 317 NotifyStatusChanged(this);
9e9869d0 318
4e87d341 319 return true;
e8ef3da7
WL
320}
321
4291e8fe 322int64 CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
da7b8c12 323{
4291e8fe
PW
324 int64 nRet = nOrderPosNext++;
325 if (pwalletdb) {
326 pwalletdb->WriteOrderPosNext(nOrderPosNext);
327 } else {
328 CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
329 }
da7b8c12
LD
330 return nRet;
331}
332
ddb709e9 333CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
c3f95ef1
LD
334{
335 CWalletDB walletdb(strWalletFile);
336
337 // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
338 TxItems txOrdered;
339
340 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
341 // would make this much faster for applications that do this a lot.
342 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
343 {
344 CWalletTx* wtx = &((*it).second);
345 txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
346 }
ddb709e9 347 acentries.clear();
c3f95ef1
LD
348 walletdb.ListAccountCreditDebit(strAccount, acentries);
349 BOOST_FOREACH(CAccountingEntry& entry, acentries)
350 {
351 txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
352 }
353
354 return txOrdered;
355}
356
e8ef3da7
WL
357void CWallet::WalletUpdateSpent(const CTransaction &tx)
358{
359 // Anytime a signature is successfully verified, it's proof the outpoint is spent.
360 // Update the wallet spent flag if it doesn't know due to wallet.dat being
361 // restored from backup or the user making copies of wallet.dat.
e8ef3da7 362 {
f8dcd5ca 363 LOCK(cs_wallet);
e8ef3da7
WL
364 BOOST_FOREACH(const CTxIn& txin, tx.vin)
365 {
366 map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
367 if (mi != mapWallet.end())
368 {
369 CWalletTx& wtx = (*mi).second;
eed1785f 370 if (txin.prevout.n >= wtx.vout.size())
881a85a2 371 LogPrintf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
eed1785f 372 else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
e8ef3da7 373 {
881a85a2 374 LogPrintf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
e8ef3da7
WL
375 wtx.MarkSpent(txin.prevout.n);
376 wtx.WriteToDisk();
fe4a6550 377 NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
e8ef3da7
WL
378 }
379 }
380 }
381 }
382}
383
95d888a6
PW
384void CWallet::MarkDirty()
385{
95d888a6 386 {
f8dcd5ca 387 LOCK(cs_wallet);
95d888a6
PW
388 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
389 item.second.MarkDirty();
390 }
391}
392
e8ef3da7
WL
393bool CWallet::AddToWallet(const CWalletTx& wtxIn)
394{
395 uint256 hash = wtxIn.GetHash();
e8ef3da7 396 {
f8dcd5ca 397 LOCK(cs_wallet);
e8ef3da7
WL
398 // Inserts only if not already there, returns tx inserted or tx found
399 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
400 CWalletTx& wtx = (*ret.first).second;
4c6e2295 401 wtx.BindWallet(this);
e8ef3da7
WL
402 bool fInsertedNew = ret.second;
403 if (fInsertedNew)
9c7722b7 404 {
e8ef3da7 405 wtx.nTimeReceived = GetAdjustedTime();
da7b8c12 406 wtx.nOrderPos = IncOrderPosNext();
c3f95ef1
LD
407
408 wtx.nTimeSmart = wtx.nTimeReceived;
409 if (wtxIn.hashBlock != 0)
410 {
411 if (mapBlockIndex.count(wtxIn.hashBlock))
412 {
413 unsigned int latestNow = wtx.nTimeReceived;
414 unsigned int latestEntry = 0;
415 {
416 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
417 int64 latestTolerated = latestNow + 300;
ddb709e9
LD
418 std::list<CAccountingEntry> acentries;
419 TxItems txOrdered = OrderedTxItems(acentries);
c3f95ef1
LD
420 for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
421 {
422 CWalletTx *const pwtx = (*it).second.first;
423 if (pwtx == &wtx)
424 continue;
425 CAccountingEntry *const pacentry = (*it).second.second;
426 int64 nSmartTime;
427 if (pwtx)
428 {
429 nSmartTime = pwtx->nTimeSmart;
430 if (!nSmartTime)
431 nSmartTime = pwtx->nTimeReceived;
432 }
433 else
434 nSmartTime = pacentry->nTime;
435 if (nSmartTime <= latestTolerated)
436 {
437 latestEntry = nSmartTime;
438 if (nSmartTime > latestNow)
439 latestNow = nSmartTime;
440 break;
441 }
442 }
443 }
444
445 unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime;
446 wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
447 }
448 else
881a85a2
GA
449 LogPrintf("AddToWallet() : found %s in block %s not in index\n",
450 wtxIn.GetHash().ToString().c_str(),
451 wtxIn.hashBlock.ToString().c_str());
c3f95ef1 452 }
9c7722b7 453 }
e8ef3da7
WL
454
455 bool fUpdated = false;
456 if (!fInsertedNew)
457 {
458 // Merge
459 if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
460 {
461 wtx.hashBlock = wtxIn.hashBlock;
462 fUpdated = true;
463 }
464 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
465 {
466 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
467 wtx.nIndex = wtxIn.nIndex;
468 fUpdated = true;
469 }
470 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
471 {
472 wtx.fFromMe = wtxIn.fFromMe;
473 fUpdated = true;
474 }
475 fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
476 }
477
478 //// debug print
881a85a2 479 LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
e8ef3da7
WL
480
481 // Write to disk
482 if (fInsertedNew || fUpdated)
483 if (!wtx.WriteToDisk())
484 return false;
ee4b170c
CF
485
486 if (!fHaveGUI) {
34994ebc
CF
487 // If default receiving address gets used, replace it with a new one
488 if (vchDefaultKey.IsValid()) {
489 CScript scriptDefaultKey;
490 scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
491 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
7db3b75b 492 {
34994ebc 493 if (txout.scriptPubKey == scriptDefaultKey)
360cfe14 494 {
34994ebc 495 CPubKey newDefaultKey;
71ac5052 496 if (GetKeyFromPool(newDefaultKey))
34994ebc
CF
497 {
498 SetDefaultKey(newDefaultKey);
a41d5fe0 499 SetAddressBook(vchDefaultKey.GetID(), "", "receive");
34994ebc 500 }
360cfe14 501 }
7db3b75b 502 }
d5115a71 503 }
e8ef3da7 504 }
e8ef3da7
WL
505 // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
506 WalletUpdateSpent(wtx);
e8ef3da7 507
fe4a6550
WL
508 // Notify UI of new or updated transaction
509 NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
cae686d3 510
511 // notify an external script when a wallet transaction comes in or is updated
512 std::string strCmd = GetArg("-walletnotify", "");
513
514 if ( !strCmd.empty())
515 {
516 boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
517 boost::thread t(runCommand, strCmd); // thread runs free
518 }
519
fe4a6550 520 }
e8ef3da7
WL
521 return true;
522}
523
d825e6a3
PW
524// Add a transaction to the wallet, or update it.
525// pblock is optional, but should be provided if the transaction is known to be in a block.
526// If fUpdate is true, existing transactions will be updated.
64dd46fd 527bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
e8ef3da7 528{
e8ef3da7 529 {
f8dcd5ca 530 LOCK(cs_wallet);
6cc4a62c
GA
531 bool fExisted = mapWallet.count(hash);
532 if (fExisted && !fUpdate) return false;
533 if (fExisted || IsMine(tx) || IsFromMe(tx))
534 {
535 CWalletTx wtx(this,tx);
536 // Get merkle branch if transaction was found in a block
537 if (pblock)
538 wtx.SetMerkleBranch(pblock);
539 return AddToWallet(wtx);
540 }
541 else
542 WalletUpdateSpent(tx);
e8ef3da7 543 }
e8ef3da7
WL
544 return false;
545}
546
547bool CWallet::EraseFromWallet(uint256 hash)
548{
549 if (!fFileBacked)
550 return false;
e8ef3da7 551 {
f8dcd5ca 552 LOCK(cs_wallet);
e8ef3da7
WL
553 if (mapWallet.erase(hash))
554 CWalletDB(strWalletFile).EraseTx(hash);
555 }
556 return true;
557}
558
559
560bool CWallet::IsMine(const CTxIn &txin) const
561{
e8ef3da7 562 {
f8dcd5ca 563 LOCK(cs_wallet);
e8ef3da7
WL
564 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
565 if (mi != mapWallet.end())
566 {
567 const CWalletTx& prev = (*mi).second;
568 if (txin.prevout.n < prev.vout.size())
569 if (IsMine(prev.vout[txin.prevout.n]))
570 return true;
571 }
572 }
573 return false;
574}
575
bde280b9 576int64 CWallet::GetDebit(const CTxIn &txin) const
e8ef3da7 577{
e8ef3da7 578 {
f8dcd5ca 579 LOCK(cs_wallet);
e8ef3da7
WL
580 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
581 if (mi != mapWallet.end())
582 {
583 const CWalletTx& prev = (*mi).second;
584 if (txin.prevout.n < prev.vout.size())
585 if (IsMine(prev.vout[txin.prevout.n]))
586 return prev.vout[txin.prevout.n].nValue;
587 }
588 }
589 return 0;
590}
591
e679ec96
GA
592bool CWallet::IsChange(const CTxOut& txout) const
593{
10254401 594 CTxDestination address;
2a45a494
GA
595
596 // TODO: fix handling of 'change' outputs. The assumption is that any
597 // payment to a TX_PUBKEYHASH that is mine but isn't in the address book
598 // is change. That assumption is likely to break when we implement multisignature
599 // wallets that return change back into a multi-signature-protected address;
600 // a better way of identifying which outputs are 'the send' and which are
601 // 'the change' will need to be implemented (maybe extend CWalletTx to remember
602 // which output, if any, was change).
10254401 603 if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
f8dcd5ca
PW
604 {
605 LOCK(cs_wallet);
606 if (!mapAddressBook.count(address))
607 return true;
608 }
e679ec96
GA
609 return false;
610}
611
bde280b9 612int64 CWalletTx::GetTxTime() const
e8ef3da7 613{
c3f95ef1
LD
614 int64 n = nTimeSmart;
615 return n ? n : nTimeReceived;
e8ef3da7
WL
616}
617
618int CWalletTx::GetRequestCount() const
619{
620 // Returns -1 if it wasn't being tracked
621 int nRequests = -1;
e8ef3da7 622 {
f8dcd5ca 623 LOCK(pwallet->cs_wallet);
e8ef3da7
WL
624 if (IsCoinBase())
625 {
626 // Generated block
627 if (hashBlock != 0)
628 {
629 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
630 if (mi != pwallet->mapRequestCount.end())
631 nRequests = (*mi).second;
632 }
633 }
634 else
635 {
636 // Did anyone request this transaction?
637 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
638 if (mi != pwallet->mapRequestCount.end())
639 {
640 nRequests = (*mi).second;
641
642 // How about the block it's in?
643 if (nRequests == 0 && hashBlock != 0)
644 {
645 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
646 if (mi != pwallet->mapRequestCount.end())
647 nRequests = (*mi).second;
648 else
649 nRequests = 1; // If it's in someone else's block it must have got out
650 }
651 }
652 }
653 }
654 return nRequests;
655}
656
e07c8e91 657void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
10254401 658 list<pair<CTxDestination, int64> >& listSent, int64& nFee, string& strSentAccount) const
e8ef3da7 659{
e07c8e91 660 nFee = 0;
e8ef3da7
WL
661 listReceived.clear();
662 listSent.clear();
663 strSentAccount = strFromAccount;
664
e8ef3da7 665 // Compute fee:
bde280b9 666 int64 nDebit = GetDebit();
e8ef3da7
WL
667 if (nDebit > 0) // debit>0 means we signed/sent this transaction
668 {
05df3fc6 669 int64 nValueOut = GetValueOut(*this);
e8ef3da7
WL
670 nFee = nDebit - nValueOut;
671 }
672
e679ec96 673 // Sent/received.
e8ef3da7
WL
674 BOOST_FOREACH(const CTxOut& txout, vout)
675 {
10254401 676 CTxDestination address;
e8ef3da7 677 vector<unsigned char> vchPubKey;
10254401 678 if (!ExtractDestination(txout.scriptPubKey, address))
e8ef3da7 679 {
881a85a2
GA
680 LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
681 this->GetHash().ToString().c_str());
e8ef3da7
WL
682 }
683
684 // Don't report 'change' txouts
685 if (nDebit > 0 && pwallet->IsChange(txout))
686 continue;
687
688 if (nDebit > 0)
689 listSent.push_back(make_pair(address, txout.nValue));
690
691 if (pwallet->IsMine(txout))
692 listReceived.push_back(make_pair(address, txout.nValue));
693 }
694
695}
696
e07c8e91 697void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nReceived,
bde280b9 698 int64& nSent, int64& nFee) const
e8ef3da7 699{
e07c8e91 700 nReceived = nSent = nFee = 0;
e8ef3da7 701
e07c8e91 702 int64 allFee;
e8ef3da7 703 string strSentAccount;
10254401
PW
704 list<pair<CTxDestination, int64> > listReceived;
705 list<pair<CTxDestination, int64> > listSent;
e07c8e91 706 GetAmounts(listReceived, listSent, allFee, strSentAccount);
e8ef3da7 707
e8ef3da7
WL
708 if (strAccount == strSentAccount)
709 {
10254401 710 BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& s, listSent)
e8ef3da7
WL
711 nSent += s.second;
712 nFee = allFee;
713 }
e8ef3da7 714 {
f8dcd5ca 715 LOCK(pwallet->cs_wallet);
10254401 716 BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listReceived)
e8ef3da7
WL
717 {
718 if (pwallet->mapAddressBook.count(r.first))
719 {
61885513
GA
720 map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
721 if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
e8ef3da7
WL
722 nReceived += r.second;
723 }
724 else if (strAccount.empty())
725 {
726 nReceived += r.second;
727 }
728 }
729 }
730}
731
450cbb09 732void CWalletTx::AddSupportingTransactions()
e8ef3da7
WL
733{
734 vtxPrev.clear();
735
736 const int COPY_DEPTH = 3;
737 if (SetMerkleBranch() < COPY_DEPTH)
738 {
739 vector<uint256> vWorkQueue;
740 BOOST_FOREACH(const CTxIn& txin, vin)
741 vWorkQueue.push_back(txin.prevout.hash);
742
e8ef3da7 743 {
f8dcd5ca 744 LOCK(pwallet->cs_wallet);
e8ef3da7
WL
745 map<uint256, const CMerkleTx*> mapWalletPrev;
746 set<uint256> setAlreadyDone;
c376ac35 747 for (unsigned int i = 0; i < vWorkQueue.size(); i++)
e8ef3da7
WL
748 {
749 uint256 hash = vWorkQueue[i];
750 if (setAlreadyDone.count(hash))
751 continue;
752 setAlreadyDone.insert(hash);
753
754 CMerkleTx tx;
755 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
756 if (mi != pwallet->mapWallet.end())
757 {
758 tx = (*mi).second;
759 BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
760 mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
761 }
762 else if (mapWalletPrev.count(hash))
763 {
764 tx = *mapWalletPrev[hash];
765 }
e8ef3da7
WL
766
767 int nDepth = tx.SetMerkleBranch();
768 vtxPrev.push_back(tx);
769
770 if (nDepth < COPY_DEPTH)
da7bbd9d 771 {
e8ef3da7
WL
772 BOOST_FOREACH(const CTxIn& txin, tx.vin)
773 vWorkQueue.push_back(txin.prevout.hash);
da7bbd9d 774 }
e8ef3da7
WL
775 }
776 }
777 }
778
779 reverse(vtxPrev.begin(), vtxPrev.end());
780}
781
782bool CWalletTx::WriteToDisk()
783{
784 return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
785}
786
d825e6a3
PW
787// Scan the block chain (starting in pindexStart) for transactions
788// from or to us. If fUpdate is true, found transactions that already
789// exist in the wallet will be updated.
e8ef3da7
WL
790int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
791{
792 int ret = 0;
793
794 CBlockIndex* pindex = pindexStart;
e8ef3da7 795 {
f8dcd5ca 796 LOCK(cs_wallet);
e8ef3da7
WL
797 while (pindex)
798 {
8da9dd07
JG
799 // no need to read and scan block, if block was created before
800 // our wallet birthday (as adjusted for block time variability)
801 if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
802 pindex = pindex->GetNextInMainChain();
803 continue;
804 }
805
e8ef3da7 806 CBlock block;
7db120d5 807 ReadBlockFromDisk(block, pindex);
e8ef3da7
WL
808 BOOST_FOREACH(CTransaction& tx, block.vtx)
809 {
64dd46fd 810 if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
e8ef3da7
WL
811 ret++;
812 }
0fe8010a 813 pindex = pindex->GetNextInMainChain();
e8ef3da7
WL
814 }
815 }
816 return ret;
817}
818
819void CWallet::ReacceptWalletTransactions()
820{
e8ef3da7 821 bool fRepeat = true;
f8dcd5ca 822 while (fRepeat)
e8ef3da7 823 {
f8dcd5ca 824 LOCK(cs_wallet);
e8ef3da7 825 fRepeat = false;
450cbb09 826 bool fMissing = false;
e8ef3da7
WL
827 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
828 {
829 CWalletTx& wtx = item.second;
830 if (wtx.IsCoinBase() && wtx.IsSpent(0))
831 continue;
832
450cbb09 833 CCoins coins;
e8ef3da7 834 bool fUpdated = false;
ddba5823
PW
835 bool fFound = pcoinsTip->GetCoins(wtx.GetHash(), coins);
836 if (fFound || wtx.GetDepthInMainChain() > 0)
e8ef3da7
WL
837 {
838 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
450cbb09 839 for (unsigned int i = 0; i < wtx.vout.size(); i++)
e8ef3da7
WL
840 {
841 if (wtx.IsSpent(i))
842 continue;
450cbb09 843 if ((i >= coins.vout.size() || coins.vout[i].IsNull()) && IsMine(wtx.vout[i]))
e8ef3da7
WL
844 {
845 wtx.MarkSpent(i);
846 fUpdated = true;
450cbb09 847 fMissing = true;
e8ef3da7
WL
848 }
849 }
850 if (fUpdated)
851 {
881a85a2 852 LogPrintf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
e8ef3da7
WL
853 wtx.MarkDirty();
854 wtx.WriteToDisk();
855 }
856 }
857 else
858 {
814efd6f 859 // Re-accept any txes of ours that aren't already in a block
e8ef3da7 860 if (!wtx.IsCoinBase())
b1f15b21 861 wtx.AcceptWalletTransaction();
e8ef3da7
WL
862 }
863 }
450cbb09 864 if (fMissing)
e8ef3da7
WL
865 {
866 // TODO: optimize this to scan just part of the block chain?
867 if (ScanForWalletTransactions(pindexGenesisBlock))
814efd6f 868 fRepeat = true; // Found missing transactions: re-do re-accept.
e8ef3da7
WL
869 }
870 }
871}
872
ae8bfd12 873void CWalletTx::RelayWalletTransaction()
e8ef3da7
WL
874{
875 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
876 {
269d9c64 877 if (!tx.IsCoinBase())
5eaf91a4 878 if (tx.GetDepthInMainChain() == 0)
269d9c64 879 RelayTransaction((CTransaction)tx, tx.GetHash());
e8ef3da7
WL
880 }
881 if (!IsCoinBase())
882 {
5eaf91a4
PW
883 if (GetDepthInMainChain() == 0) {
884 uint256 hash = GetHash();
881a85a2 885 LogPrintf("Relaying wtx %s\n", hash.ToString().c_str());
269d9c64 886 RelayTransaction((CTransaction)*this, hash);
e8ef3da7
WL
887 }
888 }
889}
890
e8ef3da7
WL
891void CWallet::ResendWalletTransactions()
892{
893 // Do this infrequently and randomly to avoid giving away
894 // that these are our transactions.
203d1ae6 895 if (GetTime() < nNextResend)
e8ef3da7 896 return;
203d1ae6
LD
897 bool fFirst = (nNextResend == 0);
898 nNextResend = GetTime() + GetRand(30 * 60);
e8ef3da7
WL
899 if (fFirst)
900 return;
901
902 // Only do it if there's been a new block since last time
203d1ae6 903 if (nTimeBestReceived < nLastResend)
e8ef3da7 904 return;
203d1ae6 905 nLastResend = GetTime();
e8ef3da7
WL
906
907 // Rebroadcast any of our txes that aren't in a block yet
881a85a2 908 LogPrintf("ResendWalletTransactions()\n");
e8ef3da7 909 {
f8dcd5ca 910 LOCK(cs_wallet);
e8ef3da7
WL
911 // Sort them in chronological order
912 multimap<unsigned int, CWalletTx*> mapSorted;
913 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
914 {
915 CWalletTx& wtx = item.second;
916 // Don't rebroadcast until it's had plenty of time that
917 // it should have gotten in already by now.
bde280b9 918 if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
e8ef3da7
WL
919 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
920 }
921 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
922 {
923 CWalletTx& wtx = *item.second;
ae8bfd12 924 wtx.RelayWalletTransaction();
e8ef3da7
WL
925 }
926 }
927}
928
929
930
931
932
933
934//////////////////////////////////////////////////////////////////////////////
935//
936// Actions
937//
938
939
bde280b9 940int64 CWallet::GetBalance() const
e8ef3da7 941{
bde280b9 942 int64 nTotal = 0;
e8ef3da7 943 {
f8dcd5ca 944 LOCK(cs_wallet);
e8ef3da7
WL
945 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
946 {
947 const CWalletTx* pcoin = &(*it).second;
d28bd8b7 948 if (pcoin->IsConfirmed())
8fdb7e10 949 nTotal += pcoin->GetAvailableCredit();
e8ef3da7
WL
950 }
951 }
952
e8ef3da7
WL
953 return nTotal;
954}
955
bde280b9 956int64 CWallet::GetUnconfirmedBalance() const
df5ccbd2 957{
bde280b9 958 int64 nTotal = 0;
df5ccbd2 959 {
f8dcd5ca 960 LOCK(cs_wallet);
df5ccbd2
WL
961 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
962 {
963 const CWalletTx* pcoin = &(*it).second;
05df3fc6 964 if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
8fdb7e10 965 nTotal += pcoin->GetAvailableCredit();
966 }
967 }
968 return nTotal;
969}
970
971int64 CWallet::GetImmatureBalance() const
972{
973 int64 nTotal = 0;
974 {
975 LOCK(cs_wallet);
976 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
977 {
966a0e8c
PK
978 const CWalletTx* pcoin = &(*it).second;
979 nTotal += pcoin->GetImmatureCredit();
df5ccbd2
WL
980 }
981 }
982 return nTotal;
983}
e8ef3da7 984
831f59ce 985// populate vCoins with vector of spendable COutputs
a2709fad 986void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
9b0369c7
CM
987{
988 vCoins.clear();
989
990 {
991 LOCK(cs_wallet);
992 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
993 {
994 const CWalletTx* pcoin = &(*it).second;
995
05df3fc6 996 if (!IsFinalTx(*pcoin))
a2709fad
GA
997 continue;
998
999 if (fOnlyConfirmed && !pcoin->IsConfirmed())
9b0369c7
CM
1000 continue;
1001
1002 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1003 continue;
1004
fdbb537d
JG
1005 for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
1006 if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) &&
1007 !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0)
9b0369c7 1008 vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
fdbb537d 1009 }
9b0369c7
CM
1010 }
1011 }
1012}
1013
831f59ce
CM
1014static void ApproximateBestSubset(vector<pair<int64, pair<const CWalletTx*,unsigned int> > >vValue, int64 nTotalLower, int64 nTargetValue,
1015 vector<char>& vfBest, int64& nBest, int iterations = 1000)
1016{
1017 vector<char> vfIncluded;
1018
1019 vfBest.assign(vValue.size(), true);
1020 nBest = nTotalLower;
1021
907a2aa4
GM
1022 seed_insecure_rand();
1023
831f59ce
CM
1024 for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
1025 {
1026 vfIncluded.assign(vValue.size(), false);
1027 int64 nTotal = 0;
1028 bool fReachedTarget = false;
1029 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
1030 {
1031 for (unsigned int i = 0; i < vValue.size(); i++)
1032 {
907a2aa4
GM
1033 //The solver here uses a randomized algorithm,
1034 //the randomness serves no real security purpose but is just
1035 //needed to prevent degenerate behavior and it is important
1036 //that the rng fast. We do not use a constant random sequence,
1037 //because there may be some privacy improvement by making
1038 //the selection random.
1039 if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
831f59ce
CM
1040 {
1041 nTotal += vValue[i].first;
1042 vfIncluded[i] = true;
1043 if (nTotal >= nTargetValue)
1044 {
1045 fReachedTarget = true;
1046 if (nTotal < nBest)
1047 {
1048 nBest = nTotal;
1049 vfBest = vfIncluded;
1050 }
1051 nTotal -= vValue[i].first;
1052 vfIncluded[i] = false;
1053 }
1054 }
1055 }
1056 }
1057 }
1058}
1059
9b0369c7
CM
1060bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
1061 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
e8ef3da7
WL
1062{
1063 setCoinsRet.clear();
1064 nValueRet = 0;
1065
1066 // List of values less than target
bde280b9
WL
1067 pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
1068 coinLowestLarger.first = std::numeric_limits<int64>::max();
e8ef3da7 1069 coinLowestLarger.second.first = NULL;
bde280b9
WL
1070 vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
1071 int64 nTotalLower = 0;
e8ef3da7 1072
e333ab56
CM
1073 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
1074
9b0369c7 1075 BOOST_FOREACH(COutput output, vCoins)
e8ef3da7 1076 {
9b0369c7 1077 const CWalletTx *pcoin = output.tx;
e8ef3da7 1078
9b0369c7
CM
1079 if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
1080 continue;
e8ef3da7 1081
9b0369c7
CM
1082 int i = output.i;
1083 int64 n = pcoin->vout[i].nValue;
e8ef3da7 1084
9b0369c7 1085 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
e8ef3da7 1086
9b0369c7
CM
1087 if (n == nTargetValue)
1088 {
1089 setCoinsRet.insert(coin.second);
1090 nValueRet += coin.first;
1091 return true;
1092 }
1093 else if (n < nTargetValue + CENT)
1094 {
1095 vValue.push_back(coin);
1096 nTotalLower += n;
1097 }
1098 else if (n < coinLowestLarger.first)
1099 {
1100 coinLowestLarger = coin;
e8ef3da7
WL
1101 }
1102 }
1103
831f59ce 1104 if (nTotalLower == nTargetValue)
e8ef3da7 1105 {
c376ac35 1106 for (unsigned int i = 0; i < vValue.size(); ++i)
e8ef3da7
WL
1107 {
1108 setCoinsRet.insert(vValue[i].second);
1109 nValueRet += vValue[i].first;
1110 }
1111 return true;
1112 }
1113
831f59ce 1114 if (nTotalLower < nTargetValue)
e8ef3da7
WL
1115 {
1116 if (coinLowestLarger.second.first == NULL)
1117 return false;
1118 setCoinsRet.insert(coinLowestLarger.second);
1119 nValueRet += coinLowestLarger.first;
1120 return true;
1121 }
1122
e8ef3da7 1123 // Solve subset sum by stochastic approximation
d650f96d 1124 sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
831f59ce
CM
1125 vector<char> vfBest;
1126 int64 nBest;
e8ef3da7 1127
831f59ce
CM
1128 ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
1129 if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
1130 ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
e8ef3da7 1131
831f59ce
CM
1132 // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
1133 // or the next bigger coin is closer), return the bigger coin
1134 if (coinLowestLarger.second.first &&
1135 ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
e8ef3da7
WL
1136 {
1137 setCoinsRet.insert(coinLowestLarger.second);
1138 nValueRet += coinLowestLarger.first;
1139 }
1140 else {
c376ac35 1141 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7
WL
1142 if (vfBest[i])
1143 {
1144 setCoinsRet.insert(vValue[i].second);
1145 nValueRet += vValue[i].first;
1146 }
1147
881a85a2 1148 LogPrintf("selectcoins", "SelectCoins() best subset: ");
c376ac35 1149 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7 1150 if (vfBest[i])
881a85a2
GA
1151 LogPrintf("selectcoins", "%s ", FormatMoney(vValue[i].first).c_str());
1152 LogPrintf("selectcoins", "total %s\n", FormatMoney(nBest).c_str());
e8ef3da7
WL
1153 }
1154
1155 return true;
1156}
1157
bde280b9 1158bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
e8ef3da7 1159{
9b0369c7
CM
1160 vector<COutput> vCoins;
1161 AvailableCoins(vCoins);
1162
1163 return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
1164 SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
1165 SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet));
e8ef3da7
WL
1166}
1167
1168
1169
1170
1f00f4e9
GA
1171bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
1172 CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
e8ef3da7 1173{
bde280b9
WL
1174 int64 nValue = 0;
1175 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
e8ef3da7
WL
1176 {
1177 if (nValue < 0)
1f00f4e9
GA
1178 {
1179 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 1180 return false;
1f00f4e9 1181 }
e8ef3da7
WL
1182 nValue += s.second;
1183 }
1184 if (vecSend.empty() || nValue < 0)
1f00f4e9
GA
1185 {
1186 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 1187 return false;
1f00f4e9 1188 }
e8ef3da7 1189
4c6e2295 1190 wtxNew.BindWallet(this);
e8ef3da7 1191
e8ef3da7 1192 {
f8dcd5ca 1193 LOCK2(cs_main, cs_wallet);
e8ef3da7
WL
1194 {
1195 nFeeRet = nTransactionFee;
050d2e95 1196 while (true)
e8ef3da7
WL
1197 {
1198 wtxNew.vin.clear();
1199 wtxNew.vout.clear();
1200 wtxNew.fFromMe = true;
1201
bde280b9 1202 int64 nTotalValue = nValue + nFeeRet;
e8ef3da7
WL
1203 double dPriority = 0;
1204 // vouts to the payees
bde280b9 1205 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
8de9bb53
GA
1206 {
1207 CTxOut txout(s.second, s.first);
05df3fc6 1208 if (txout.IsDust(CTransaction::nMinRelayTxFee))
1f00f4e9
GA
1209 {
1210 strFailReason = _("Transaction amount too small");
8de9bb53 1211 return false;
1f00f4e9 1212 }
8de9bb53
GA
1213 wtxNew.vout.push_back(txout);
1214 }
e8ef3da7
WL
1215
1216 // Choose coins to use
1217 set<pair<const CWalletTx*,unsigned int> > setCoins;
bde280b9 1218 int64 nValueIn = 0;
e8ef3da7 1219 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
1f00f4e9
GA
1220 {
1221 strFailReason = _("Insufficient funds");
e8ef3da7 1222 return false;
1f00f4e9 1223 }
e8ef3da7
WL
1224 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1225 {
bde280b9 1226 int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
d7836552
GM
1227 //The priority after the next block (depth+1) is used instead of the current,
1228 //reflecting an assumption the user would accept a bit more delay for
1229 //a chance at a free transaction.
1230 dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1);
e8ef3da7
WL
1231 }
1232
bde280b9 1233 int64 nChange = nValueIn - nValue - nFeeRet;
000dc551 1234 // if sub-cent change is required, the fee must be raised to at least nMinTxFee
a7dd11c6 1235 // or until nChange becomes zero
dbbf1d4a 1236 // NOTE: this depends on the exact behaviour of GetMinFee
000dc551 1237 if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
a7dd11c6 1238 {
000dc551 1239 int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
a7dd11c6
PW
1240 nChange -= nMoveToFee;
1241 nFeeRet += nMoveToFee;
1242 }
1243
1244 if (nChange > 0)
e8ef3da7
WL
1245 {
1246 // Note: We use a new key here to keep it from being obvious which side is the change.
1247 // The drawback is that by not reusing a previous key, the change may be lost if a
1248 // backup is restored, if the backup doesn't have the new private key for the change.
1249 // If we reused the old key, it would be possible to add code to look for and
1250 // rediscover unknown transactions that were written with keys of ours to recover
1251 // post-backup change.
1252
1253 // Reserve a new key pair from key pool
360cfe14
PW
1254 CPubKey vchPubKey;
1255 assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
e8ef3da7 1256
bf798734
GA
1257 // Fill a vout to ourself
1258 // TODO: pass in scriptChange instead of reservekey so
1259 // change transaction isn't always pay-to-bitcoin-address
e8ef3da7 1260 CScript scriptChange;
10254401 1261 scriptChange.SetDestination(vchPubKey.GetID());
e8ef3da7 1262
8de9bb53
GA
1263 CTxOut newTxOut(nChange, scriptChange);
1264
1265 // Never create dust outputs; if we would, just
1266 // add the dust to the fee.
05df3fc6 1267 if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
8de9bb53
GA
1268 {
1269 nFeeRet += nChange;
1270 reservekey.ReturnKey();
1271 }
1272 else
1273 {
1274 // Insert change txn at random position:
1275 vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
1276 wtxNew.vout.insert(position, newTxOut);
1277 }
e8ef3da7
WL
1278 }
1279 else
1280 reservekey.ReturnKey();
1281
1282 // Fill vin
1283 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1284 wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1285
1286 // Sign
1287 int nIn = 0;
1288 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1289 if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1f00f4e9
GA
1290 {
1291 strFailReason = _("Signing transaction failed");
e8ef3da7 1292 return false;
1f00f4e9 1293 }
e8ef3da7
WL
1294
1295 // Limit size
6b6aaa16 1296 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
41e1a0d7 1297 if (nBytes >= MAX_STANDARD_TX_SIZE)
1f00f4e9
GA
1298 {
1299 strFailReason = _("Transaction too large");
e8ef3da7 1300 return false;
1f00f4e9 1301 }
e8ef3da7
WL
1302 dPriority /= nBytes;
1303
1304 // Check that enough fee is included
bde280b9 1305 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
05df3fc6 1306 bool fAllowFree = AllowFree(dPriority);
87cce04c 1307 int64 nMinFee = GetMinFee(wtxNew, fAllowFree, GMF_SEND);
e8ef3da7
WL
1308 if (nFeeRet < max(nPayFee, nMinFee))
1309 {
1310 nFeeRet = max(nPayFee, nMinFee);
1311 continue;
1312 }
1313
1314 // Fill vtxPrev by copying from previous transactions vtxPrev
450cbb09 1315 wtxNew.AddSupportingTransactions();
e8ef3da7
WL
1316 wtxNew.fTimeReceivedIsTxTime = true;
1317
1318 break;
1319 }
1320 }
1321 }
1322 return true;
1323}
1324
1f00f4e9
GA
1325bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue,
1326 CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
e8ef3da7 1327{
bde280b9 1328 vector< pair<CScript, int64> > vecSend;
e8ef3da7 1329 vecSend.push_back(make_pair(scriptPubKey, nValue));
1f00f4e9 1330 return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason);
e8ef3da7
WL
1331}
1332
1333// Call after CreateTransaction unless you want to abort
1334bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1335{
e8ef3da7 1336 {
f8dcd5ca 1337 LOCK2(cs_main, cs_wallet);
881a85a2 1338 LogPrintf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
e8ef3da7
WL
1339 {
1340 // This is only to keep the database open to defeat the auto-flush for the
1341 // duration of this scope. This is the only place where this optimization
1342 // maybe makes sense; please don't do it anywhere else.
1343 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1344
1345 // Take key pair from key pool so it won't be used again
1346 reservekey.KeepKey();
1347
1348 // Add tx to wallet, because if it has change it's also ours,
1349 // otherwise just for transaction history.
1350 AddToWallet(wtxNew);
1351
1352 // Mark old coins as spent
1353 set<CWalletTx*> setCoins;
1354 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1355 {
1356 CWalletTx &coin = mapWallet[txin.prevout.hash];
4c6e2295 1357 coin.BindWallet(this);
e8ef3da7
WL
1358 coin.MarkSpent(txin.prevout.n);
1359 coin.WriteToDisk();
fe4a6550 1360 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
e8ef3da7
WL
1361 }
1362
1363 if (fFileBacked)
1364 delete pwalletdb;
1365 }
1366
1367 // Track how many getdata requests our transaction gets
6cc4a62c 1368 mapRequestCount[wtxNew.GetHash()] = 0;
e8ef3da7
WL
1369
1370 // Broadcast
b1f15b21 1371 if (!wtxNew.AcceptToMemoryPool(false))
e8ef3da7
WL
1372 {
1373 // This must not fail. The transaction has already been signed and recorded.
881a85a2 1374 LogPrintf("CommitTransaction() : Error: Transaction not valid");
e8ef3da7
WL
1375 return false;
1376 }
1377 wtxNew.RelayWalletTransaction();
1378 }
e8ef3da7
WL
1379 return true;
1380}
1381
1382
1383
1384
bde280b9 1385string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
e8ef3da7
WL
1386{
1387 CReserveKey reservekey(this);
bde280b9 1388 int64 nFeeRequired;
6cc4a62c
GA
1389
1390 if (IsLocked())
e8ef3da7 1391 {
6b3783a9 1392 string strError = _("Error: Wallet locked, unable to create transaction!");
881a85a2 1393 LogPrintf("SendMoney() : %s", strError.c_str());
6cc4a62c
GA
1394 return strError;
1395 }
1f00f4e9
GA
1396 string strError;
1397 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
6cc4a62c 1398 {
6cc4a62c 1399 if (nValue + nFeeRequired > GetBalance())
6b3783a9 1400 strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired).c_str());
881a85a2 1401 LogPrintf("SendMoney() : %s\n", strError.c_str());
6cc4a62c 1402 return strError;
e8ef3da7
WL
1403 }
1404
15d8ff20 1405 if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired))
e8ef3da7
WL
1406 return "ABORTED";
1407
1408 if (!CommitTransaction(wtxNew, reservekey))
6b3783a9 1409 return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
e8ef3da7 1410
e8ef3da7
WL
1411 return "";
1412}
1413
1414
1415
10254401 1416string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
e8ef3da7
WL
1417{
1418 // Check amount
1419 if (nValue <= 0)
1420 return _("Invalid amount");
1421 if (nValue + nTransactionFee > GetBalance())
1422 return _("Insufficient funds");
1423
ff0ee876 1424 // Parse Bitcoin address
e8ef3da7 1425 CScript scriptPubKey;
10254401 1426 scriptPubKey.SetDestination(address);
e8ef3da7
WL
1427
1428 return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1429}
1430
1431
1432
1433
eed1785f 1434DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
e8ef3da7
WL
1435{
1436 if (!fFileBacked)
4f76be1d 1437 return DB_LOAD_OK;
e8ef3da7 1438 fFirstRunRet = false;
eed1785f 1439 DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
d764d916 1440 if (nLoadWalletRet == DB_NEED_REWRITE)
9e9869d0 1441 {
d764d916
GA
1442 if (CDB::Rewrite(strWalletFile, "\x04pool"))
1443 {
1444 setKeyPool.clear();
1445 // Note: can't top-up keypool here, because wallet is locked.
1446 // User will be prompted to unlock wallet the next operation
1447 // the requires a new key.
1448 }
9e9869d0
PW
1449 }
1450
7ec55267
MC
1451 if (nLoadWalletRet != DB_LOAD_OK)
1452 return nLoadWalletRet;
fd61d6f5 1453 fFirstRunRet = !vchDefaultKey.IsValid();
e8ef3da7 1454
116df55e 1455 return DB_LOAD_OK;
e8ef3da7
WL
1456}
1457
ae3d0aba 1458
a41d5fe0 1459bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
ae3d0aba 1460{
61885513
GA
1461 std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
1462 mapAddressBook[address].name = strName;
dcd0b077
WL
1463 if (!strPurpose.empty()) /* update purpose only if requested */
1464 mapAddressBook[address].purpose = strPurpose;
1465 NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address),
1466 mapAddressBook[address].purpose,
1467 (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
ae3d0aba
WL
1468 if (!fFileBacked)
1469 return false;
a41d5fe0
GA
1470 if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
1471 return false;
10254401 1472 return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
ae3d0aba
WL
1473}
1474
a41d5fe0 1475bool CWallet::DelAddressBook(const CTxDestination& address)
ae3d0aba 1476{
2ffba736 1477 mapAddressBook.erase(address);
dcd0b077 1478 NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
ae3d0aba
WL
1479 if (!fFileBacked)
1480 return false;
a41d5fe0 1481 CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
10254401 1482 return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
ae3d0aba
WL
1483}
1484
e8ef3da7
WL
1485void CWallet::PrintWallet(const CBlock& block)
1486{
e8ef3da7 1487 {
f8dcd5ca 1488 LOCK(cs_wallet);
e8ef3da7
WL
1489 if (mapWallet.count(block.vtx[0].GetHash()))
1490 {
1491 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
881a85a2 1492 LogPrintf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
e8ef3da7
WL
1493 }
1494 }
881a85a2 1495 LogPrintf("\n");
e8ef3da7
WL
1496}
1497
1498bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1499{
e8ef3da7 1500 {
f8dcd5ca 1501 LOCK(cs_wallet);
e8ef3da7
WL
1502 map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1503 if (mi != mapWallet.end())
1504 {
1505 wtx = (*mi).second;
1506 return true;
1507 }
1508 }
1509 return false;
1510}
1511
fd61d6f5 1512bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
ae3d0aba
WL
1513{
1514 if (fFileBacked)
1515 {
1516 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1517 return false;
1518 }
1519 vchDefaultKey = vchPubKey;
1520 return true;
1521}
1522
e8ef3da7
WL
1523bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1524{
1525 if (!pwallet->fFileBacked)
1526 return false;
1527 strWalletFileOut = pwallet->strWalletFile;
1528 return true;
1529}
1530
37971fcc
GA
1531//
1532// Mark old keypool keys as used,
1533// and generate all new keys
1534//
1535bool CWallet::NewKeyPool()
1536{
37971fcc 1537 {
f8dcd5ca 1538 LOCK(cs_wallet);
37971fcc 1539 CWalletDB walletdb(strWalletFile);
bde280b9 1540 BOOST_FOREACH(int64 nIndex, setKeyPool)
37971fcc
GA
1541 walletdb.ErasePool(nIndex);
1542 setKeyPool.clear();
1543
1544 if (IsLocked())
1545 return false;
1546
bde280b9 1547 int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
37971fcc
GA
1548 for (int i = 0; i < nKeys; i++)
1549 {
bde280b9 1550 int64 nIndex = i+1;
37971fcc
GA
1551 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1552 setKeyPool.insert(nIndex);
1553 }
881a85a2 1554 LogPrintf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
37971fcc
GA
1555 }
1556 return true;
1557}
1558
13dd2d09 1559bool CWallet::TopUpKeyPool(unsigned int kpSize)
e8ef3da7 1560{
e8ef3da7 1561 {
f8dcd5ca
PW
1562 LOCK(cs_wallet);
1563
4e87d341
MC
1564 if (IsLocked())
1565 return false;
1566
e8ef3da7
WL
1567 CWalletDB walletdb(strWalletFile);
1568
1569 // Top up key pool
13dd2d09
JG
1570 unsigned int nTargetSize;
1571 if (kpSize > 0)
1572 nTargetSize = kpSize;
1573 else
1574 nTargetSize = max(GetArg("-keypool", 100), 0LL);
1575
faf705a4 1576 while (setKeyPool.size() < (nTargetSize + 1))
e8ef3da7 1577 {
bde280b9 1578 int64 nEnd = 1;
e8ef3da7
WL
1579 if (!setKeyPool.empty())
1580 nEnd = *(--setKeyPool.end()) + 1;
1581 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
4e87d341 1582 throw runtime_error("TopUpKeyPool() : writing generated key failed");
e8ef3da7 1583 setKeyPool.insert(nEnd);
881a85a2 1584 LogPrintf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
e8ef3da7 1585 }
4e87d341
MC
1586 }
1587 return true;
1588}
1589
bde280b9 1590void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
4e87d341
MC
1591{
1592 nIndex = -1;
fd61d6f5 1593 keypool.vchPubKey = CPubKey();
4e87d341 1594 {
f8dcd5ca
PW
1595 LOCK(cs_wallet);
1596
4e87d341
MC
1597 if (!IsLocked())
1598 TopUpKeyPool();
e8ef3da7
WL
1599
1600 // Get the oldest key
4e87d341
MC
1601 if(setKeyPool.empty())
1602 return;
1603
1604 CWalletDB walletdb(strWalletFile);
1605
e8ef3da7
WL
1606 nIndex = *(setKeyPool.begin());
1607 setKeyPool.erase(setKeyPool.begin());
1608 if (!walletdb.ReadPool(nIndex, keypool))
1609 throw runtime_error("ReserveKeyFromKeyPool() : read failed");
fd61d6f5 1610 if (!HaveKey(keypool.vchPubKey.GetID()))
e8ef3da7 1611 throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
fd61d6f5 1612 assert(keypool.vchPubKey.IsValid());
881a85a2 1613 LogPrintf("keypool reserve %"PRI64d"\n", nIndex);
e8ef3da7
WL
1614 }
1615}
1616
bde280b9 1617int64 CWallet::AddReserveKey(const CKeyPool& keypool)
30ab2c9c 1618{
30ab2c9c 1619 {
f8dcd5ca 1620 LOCK2(cs_main, cs_wallet);
30ab2c9c
PW
1621 CWalletDB walletdb(strWalletFile);
1622
bde280b9 1623 int64 nIndex = 1 + *(--setKeyPool.end());
30ab2c9c
PW
1624 if (!walletdb.WritePool(nIndex, keypool))
1625 throw runtime_error("AddReserveKey() : writing added key failed");
1626 setKeyPool.insert(nIndex);
1627 return nIndex;
1628 }
1629 return -1;
1630}
1631
bde280b9 1632void CWallet::KeepKey(int64 nIndex)
e8ef3da7
WL
1633{
1634 // Remove from key pool
1635 if (fFileBacked)
1636 {
1637 CWalletDB walletdb(strWalletFile);
6cc4a62c 1638 walletdb.ErasePool(nIndex);
e8ef3da7 1639 }
881a85a2 1640 LogPrintf("keypool keep %"PRI64d"\n", nIndex);
e8ef3da7
WL
1641}
1642
bde280b9 1643void CWallet::ReturnKey(int64 nIndex)
e8ef3da7
WL
1644{
1645 // Return to key pool
f8dcd5ca
PW
1646 {
1647 LOCK(cs_wallet);
e8ef3da7 1648 setKeyPool.insert(nIndex);
f8dcd5ca 1649 }
881a85a2 1650 LogPrintf("keypool return %"PRI64d"\n", nIndex);
e8ef3da7
WL
1651}
1652
71ac5052 1653bool CWallet::GetKeyFromPool(CPubKey& result)
e8ef3da7 1654{
bde280b9 1655 int64 nIndex = 0;
e8ef3da7 1656 CKeyPool keypool;
7db3b75b 1657 {
f8dcd5ca 1658 LOCK(cs_wallet);
ed02c95d
GA
1659 ReserveKeyFromKeyPool(nIndex, keypool);
1660 if (nIndex == -1)
7db3b75b 1661 {
ed02c95d
GA
1662 if (IsLocked()) return false;
1663 result = GenerateNewKey();
7db3b75b
GA
1664 return true;
1665 }
ed02c95d
GA
1666 KeepKey(nIndex);
1667 result = keypool.vchPubKey;
7db3b75b 1668 }
7db3b75b 1669 return true;
e8ef3da7
WL
1670}
1671
bde280b9 1672int64 CWallet::GetOldestKeyPoolTime()
e8ef3da7 1673{
bde280b9 1674 int64 nIndex = 0;
e8ef3da7
WL
1675 CKeyPool keypool;
1676 ReserveKeyFromKeyPool(nIndex, keypool);
4e87d341
MC
1677 if (nIndex == -1)
1678 return GetTime();
e8ef3da7
WL
1679 ReturnKey(nIndex);
1680 return keypool.nTime;
1681}
1682
b1093efa 1683std::map<CTxDestination, int64> CWallet::GetAddressBalances()
22dfd735 1684{
b1093efa 1685 map<CTxDestination, int64> balances;
22dfd735 1686
1687 {
1688 LOCK(cs_wallet);
1689 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1690 {
1691 CWalletTx *pcoin = &walletEntry.second;
1692
05df3fc6 1693 if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
22dfd735 1694 continue;
1695
1696 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1697 continue;
1698
1699 int nDepth = pcoin->GetDepthInMainChain();
1700 if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
1701 continue;
1702
b1093efa 1703 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 1704 {
b1093efa 1705 CTxDestination addr;
22dfd735 1706 if (!IsMine(pcoin->vout[i]))
1707 continue;
b1093efa
GM
1708 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
1709 continue;
22dfd735 1710
1711 int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
1712
22dfd735 1713 if (!balances.count(addr))
1714 balances[addr] = 0;
1715 balances[addr] += n;
1716 }
1717 }
1718 }
1719
1720 return balances;
1721}
1722
b1093efa 1723set< set<CTxDestination> > CWallet::GetAddressGroupings()
22dfd735 1724{
b1093efa
GM
1725 set< set<CTxDestination> > groupings;
1726 set<CTxDestination> grouping;
22dfd735 1727
1728 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1729 {
1730 CWalletTx *pcoin = &walletEntry.second;
1731
a3fad211 1732 if (pcoin->vin.size() > 0)
22dfd735 1733 {
a3fad211 1734 bool any_mine = false;
22dfd735 1735 // group all input addresses with each other
1736 BOOST_FOREACH(CTxIn txin, pcoin->vin)
b1093efa
GM
1737 {
1738 CTxDestination address;
a3fad211
GM
1739 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
1740 continue;
b1093efa
GM
1741 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
1742 continue;
1743 grouping.insert(address);
a3fad211 1744 any_mine = true;
b1093efa 1745 }
22dfd735 1746
1747 // group change with input addresses
a3fad211
GM
1748 if (any_mine)
1749 {
1750 BOOST_FOREACH(CTxOut txout, pcoin->vout)
1751 if (IsChange(txout))
1752 {
1753 CTxDestination txoutAddr;
1754 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
1755 continue;
1756 grouping.insert(txoutAddr);
1757 }
1758 }
1759 if (grouping.size() > 0)
1760 {
1761 groupings.insert(grouping);
1762 grouping.clear();
1763 }
22dfd735 1764 }
1765
1766 // group lone addrs by themselves
b1093efa 1767 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 1768 if (IsMine(pcoin->vout[i]))
1769 {
b1093efa
GM
1770 CTxDestination address;
1771 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
1772 continue;
1773 grouping.insert(address);
22dfd735 1774 groupings.insert(grouping);
1775 grouping.clear();
1776 }
1777 }
1778
b1093efa
GM
1779 set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
1780 map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
1781 BOOST_FOREACH(set<CTxDestination> grouping, groupings)
22dfd735 1782 {
1783 // make a set of all the groups hit by this new group
b1093efa
GM
1784 set< set<CTxDestination>* > hits;
1785 map< CTxDestination, set<CTxDestination>* >::iterator it;
1786 BOOST_FOREACH(CTxDestination address, grouping)
22dfd735 1787 if ((it = setmap.find(address)) != setmap.end())
1788 hits.insert((*it).second);
1789
1790 // merge all hit groups into a new single group and delete old groups
b1093efa
GM
1791 set<CTxDestination>* merged = new set<CTxDestination>(grouping);
1792 BOOST_FOREACH(set<CTxDestination>* hit, hits)
22dfd735 1793 {
1794 merged->insert(hit->begin(), hit->end());
1795 uniqueGroupings.erase(hit);
1796 delete hit;
1797 }
1798 uniqueGroupings.insert(merged);
1799
1800 // update setmap
b1093efa 1801 BOOST_FOREACH(CTxDestination element, *merged)
22dfd735 1802 setmap[element] = merged;
1803 }
1804
b1093efa
GM
1805 set< set<CTxDestination> > ret;
1806 BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
22dfd735 1807 {
1808 ret.insert(*uniqueGrouping);
1809 delete uniqueGrouping;
1810 }
1811
1812 return ret;
1813}
1814
3624356e
GA
1815set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
1816{
1817 set<CTxDestination> result;
1818 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
1819 {
1820 const CTxDestination& address = item.first;
1821 const string& strName = item.second.name;
1822 if (strName == strAccount)
1823 result.insert(address);
1824 }
1825 return result;
1826}
1827
360cfe14 1828bool CReserveKey::GetReservedKey(CPubKey& pubkey)
e8ef3da7
WL
1829{
1830 if (nIndex == -1)
1831 {
1832 CKeyPool keypool;
1833 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
0d7b28e5
MC
1834 if (nIndex != -1)
1835 vchPubKey = keypool.vchPubKey;
360cfe14
PW
1836 else {
1837 if (pwallet->vchDefaultKey.IsValid()) {
881a85a2 1838 LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
360cfe14
PW
1839 vchPubKey = pwallet->vchDefaultKey;
1840 } else
1841 return false;
cee69980 1842 }
e8ef3da7 1843 }
fd61d6f5 1844 assert(vchPubKey.IsValid());
360cfe14
PW
1845 pubkey = vchPubKey;
1846 return true;
e8ef3da7
WL
1847}
1848
1849void CReserveKey::KeepKey()
1850{
1851 if (nIndex != -1)
1852 pwallet->KeepKey(nIndex);
1853 nIndex = -1;
fd61d6f5 1854 vchPubKey = CPubKey();
e8ef3da7
WL
1855}
1856
1857void CReserveKey::ReturnKey()
1858{
1859 if (nIndex != -1)
1860 pwallet->ReturnKey(nIndex);
1861 nIndex = -1;
fd61d6f5 1862 vchPubKey = CPubKey();
e8ef3da7 1863}
ae3d0aba 1864
434e4273 1865void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
30ab2c9c
PW
1866{
1867 setAddress.clear();
1868
1869 CWalletDB walletdb(strWalletFile);
1870
f8dcd5ca 1871 LOCK2(cs_main, cs_wallet);
bde280b9 1872 BOOST_FOREACH(const int64& id, setKeyPool)
30ab2c9c
PW
1873 {
1874 CKeyPool keypool;
1875 if (!walletdb.ReadPool(id, keypool))
1876 throw runtime_error("GetAllReserveKeyHashes() : read failed");
fd61d6f5 1877 assert(keypool.vchPubKey.IsValid());
10254401
PW
1878 CKeyID keyID = keypool.vchPubKey.GetID();
1879 if (!HaveKey(keyID))
30ab2c9c 1880 throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
10254401 1881 setAddress.insert(keyID);
30ab2c9c
PW
1882 }
1883}
fe4a6550
WL
1884
1885void CWallet::UpdatedTransaction(const uint256 &hashTx)
1886{
1887 {
1888 LOCK(cs_wallet);
1889 // Only notify UI if this transaction is in this wallet
1890 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
1891 if (mi != mapWallet.end())
1892 NotifyTransactionChanged(this, hashTx, CT_UPDATED);
1893 }
1894}
fdbb537d
JG
1895
1896void CWallet::LockCoin(COutPoint& output)
1897{
1898 setLockedCoins.insert(output);
1899}
1900
1901void CWallet::UnlockCoin(COutPoint& output)
1902{
1903 setLockedCoins.erase(output);
1904}
1905
1906void CWallet::UnlockAllCoins()
1907{
1908 setLockedCoins.clear();
1909}
1910
1911bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
1912{
1913 COutPoint outpt(hash, n);
1914
1915 return (setLockedCoins.count(outpt) > 0);
1916}
1917
1918void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
1919{
1920 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
1921 it != setLockedCoins.end(); it++) {
1922 COutPoint outpt = (*it);
1923 vOutpts.push_back(outpt);
1924 }
1925}
1926
434e4273
PW
1927void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
1928 mapKeyBirth.clear();
1929
1930 // get birth times for keys with metadata
1931 for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
1932 if (it->second.nCreateTime)
1933 mapKeyBirth[it->first] = it->second.nCreateTime;
1934
1935 // map in which we'll infer heights of other keys
1936 CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
1937 std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
1938 std::set<CKeyID> setKeys;
1939 GetKeys(setKeys);
1940 BOOST_FOREACH(const CKeyID &keyid, setKeys) {
1941 if (mapKeyBirth.count(keyid) == 0)
1942 mapKeyFirstBlock[keyid] = pindexMax;
1943 }
1944 setKeys.clear();
1945
1946 // if there are no such keys, we're done
1947 if (mapKeyFirstBlock.empty())
1948 return;
1949
1950 // find first block that affects those keys, if there are any left
1951 std::vector<CKeyID> vAffected;
1952 for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
1953 // iterate over all wallet transactions...
1954 const CWalletTx &wtx = (*it).second;
1955 std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
1956 if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
1957 // ... which are already in a block
1958 int nHeight = blit->second->nHeight;
1959 BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
1960 // iterate over all their outputs
1961 ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
1962 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
1963 // ... and all their affected keys
1964 std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
1965 if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
1966 rit->second = blit->second;
1967 }
1968 vAffected.clear();
1969 }
1970 }
1971 }
1972
1973 // Extract block timestamps for those keys
1974 for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
1975 mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
1976}
This page took 0.423767 seconds and 4 git commands to generate.