]> Git Repo - VerusCoin.git/blame - src/wallet.cpp
Merge pull request #2792 from sipa/coreimpl
[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
162 printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
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
6cc4a62c 270 printf("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
GA
370 if (txin.prevout.n >= wtx.vout.size())
371 printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
372 else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
e8ef3da7
WL
373 {
374 printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
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
449 printf("AddToWallet() : found %s in block %s not in index\n",
1c06aa98 450 wtxIn.GetHash().ToString().c_str(),
c3f95ef1
LD
451 wtxIn.hashBlock.ToString().c_str());
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
1c06aa98 479 printf("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
CF
495 CPubKey newDefaultKey;
496 if (GetKeyFromPool(newDefaultKey, false))
497 {
498 SetDefaultKey(newDefaultKey);
499 SetAddressBookName(vchDefaultKey.GetID(), "");
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
WL
679 {
680 printf("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 {
10254401 720 map<CTxDestination, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
e8ef3da7
WL
721 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
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 {
852 printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
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();
1c06aa98 885 printf("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.
bde280b9 895 static int64 nNextTime;
e8ef3da7
WL
896 if (GetTime() < nNextTime)
897 return;
898 bool fFirst = (nNextTime == 0);
899 nNextTime = GetTime() + GetRand(30 * 60);
900 if (fFirst)
901 return;
902
903 // Only do it if there's been a new block since last time
bde280b9 904 static int64 nLastTime;
e8ef3da7
WL
905 if (nTimeBestReceived < nLastTime)
906 return;
907 nLastTime = GetTime();
908
909 // Rebroadcast any of our txes that aren't in a block yet
910 printf("ResendWalletTransactions()\n");
e8ef3da7 911 {
f8dcd5ca 912 LOCK(cs_wallet);
e8ef3da7
WL
913 // Sort them in chronological order
914 multimap<unsigned int, CWalletTx*> mapSorted;
915 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
916 {
917 CWalletTx& wtx = item.second;
918 // Don't rebroadcast until it's had plenty of time that
919 // it should have gotten in already by now.
bde280b9 920 if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
e8ef3da7
WL
921 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
922 }
923 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
924 {
925 CWalletTx& wtx = *item.second;
ae8bfd12 926 wtx.RelayWalletTransaction();
e8ef3da7
WL
927 }
928 }
929}
930
931
932
933
934
935
936//////////////////////////////////////////////////////////////////////////////
937//
938// Actions
939//
940
941
bde280b9 942int64 CWallet::GetBalance() const
e8ef3da7 943{
bde280b9 944 int64 nTotal = 0;
e8ef3da7 945 {
f8dcd5ca 946 LOCK(cs_wallet);
e8ef3da7
WL
947 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
948 {
949 const CWalletTx* pcoin = &(*it).second;
d28bd8b7 950 if (pcoin->IsConfirmed())
8fdb7e10 951 nTotal += pcoin->GetAvailableCredit();
e8ef3da7
WL
952 }
953 }
954
e8ef3da7
WL
955 return nTotal;
956}
957
bde280b9 958int64 CWallet::GetUnconfirmedBalance() const
df5ccbd2 959{
bde280b9 960 int64 nTotal = 0;
df5ccbd2 961 {
f8dcd5ca 962 LOCK(cs_wallet);
df5ccbd2
WL
963 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
964 {
965 const CWalletTx* pcoin = &(*it).second;
05df3fc6 966 if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
8fdb7e10 967 nTotal += pcoin->GetAvailableCredit();
968 }
969 }
970 return nTotal;
971}
972
973int64 CWallet::GetImmatureBalance() const
974{
975 int64 nTotal = 0;
976 {
977 LOCK(cs_wallet);
978 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
979 {
966a0e8c
PK
980 const CWalletTx* pcoin = &(*it).second;
981 nTotal += pcoin->GetImmatureCredit();
df5ccbd2
WL
982 }
983 }
984 return nTotal;
985}
e8ef3da7 986
831f59ce 987// populate vCoins with vector of spendable COutputs
a2709fad 988void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
9b0369c7
CM
989{
990 vCoins.clear();
991
992 {
993 LOCK(cs_wallet);
994 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
995 {
996 const CWalletTx* pcoin = &(*it).second;
997
05df3fc6 998 if (!IsFinalTx(*pcoin))
a2709fad
GA
999 continue;
1000
1001 if (fOnlyConfirmed && !pcoin->IsConfirmed())
9b0369c7
CM
1002 continue;
1003
1004 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1005 continue;
1006
fdbb537d
JG
1007 for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
1008 if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) &&
1009 !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0)
9b0369c7 1010 vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
fdbb537d 1011 }
9b0369c7
CM
1012 }
1013 }
1014}
1015
831f59ce
CM
1016static void ApproximateBestSubset(vector<pair<int64, pair<const CWalletTx*,unsigned int> > >vValue, int64 nTotalLower, int64 nTargetValue,
1017 vector<char>& vfBest, int64& nBest, int iterations = 1000)
1018{
1019 vector<char> vfIncluded;
1020
1021 vfBest.assign(vValue.size(), true);
1022 nBest = nTotalLower;
1023
907a2aa4
GM
1024 seed_insecure_rand();
1025
831f59ce
CM
1026 for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
1027 {
1028 vfIncluded.assign(vValue.size(), false);
1029 int64 nTotal = 0;
1030 bool fReachedTarget = false;
1031 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
1032 {
1033 for (unsigned int i = 0; i < vValue.size(); i++)
1034 {
907a2aa4
GM
1035 //The solver here uses a randomized algorithm,
1036 //the randomness serves no real security purpose but is just
1037 //needed to prevent degenerate behavior and it is important
1038 //that the rng fast. We do not use a constant random sequence,
1039 //because there may be some privacy improvement by making
1040 //the selection random.
1041 if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
831f59ce
CM
1042 {
1043 nTotal += vValue[i].first;
1044 vfIncluded[i] = true;
1045 if (nTotal >= nTargetValue)
1046 {
1047 fReachedTarget = true;
1048 if (nTotal < nBest)
1049 {
1050 nBest = nTotal;
1051 vfBest = vfIncluded;
1052 }
1053 nTotal -= vValue[i].first;
1054 vfIncluded[i] = false;
1055 }
1056 }
1057 }
1058 }
1059 }
1060}
1061
9b0369c7
CM
1062bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
1063 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
e8ef3da7
WL
1064{
1065 setCoinsRet.clear();
1066 nValueRet = 0;
1067
1068 // List of values less than target
bde280b9
WL
1069 pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
1070 coinLowestLarger.first = std::numeric_limits<int64>::max();
e8ef3da7 1071 coinLowestLarger.second.first = NULL;
bde280b9
WL
1072 vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
1073 int64 nTotalLower = 0;
e8ef3da7 1074
e333ab56
CM
1075 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
1076
9b0369c7 1077 BOOST_FOREACH(COutput output, vCoins)
e8ef3da7 1078 {
9b0369c7 1079 const CWalletTx *pcoin = output.tx;
e8ef3da7 1080
9b0369c7
CM
1081 if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
1082 continue;
e8ef3da7 1083
9b0369c7
CM
1084 int i = output.i;
1085 int64 n = pcoin->vout[i].nValue;
e8ef3da7 1086
9b0369c7 1087 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
e8ef3da7 1088
9b0369c7
CM
1089 if (n == nTargetValue)
1090 {
1091 setCoinsRet.insert(coin.second);
1092 nValueRet += coin.first;
1093 return true;
1094 }
1095 else if (n < nTargetValue + CENT)
1096 {
1097 vValue.push_back(coin);
1098 nTotalLower += n;
1099 }
1100 else if (n < coinLowestLarger.first)
1101 {
1102 coinLowestLarger = coin;
e8ef3da7
WL
1103 }
1104 }
1105
831f59ce 1106 if (nTotalLower == nTargetValue)
e8ef3da7 1107 {
c376ac35 1108 for (unsigned int i = 0; i < vValue.size(); ++i)
e8ef3da7
WL
1109 {
1110 setCoinsRet.insert(vValue[i].second);
1111 nValueRet += vValue[i].first;
1112 }
1113 return true;
1114 }
1115
831f59ce 1116 if (nTotalLower < nTargetValue)
e8ef3da7
WL
1117 {
1118 if (coinLowestLarger.second.first == NULL)
1119 return false;
1120 setCoinsRet.insert(coinLowestLarger.second);
1121 nValueRet += coinLowestLarger.first;
1122 return true;
1123 }
1124
e8ef3da7 1125 // Solve subset sum by stochastic approximation
d650f96d 1126 sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
831f59ce
CM
1127 vector<char> vfBest;
1128 int64 nBest;
e8ef3da7 1129
831f59ce
CM
1130 ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
1131 if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
1132 ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
e8ef3da7 1133
831f59ce
CM
1134 // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
1135 // or the next bigger coin is closer), return the bigger coin
1136 if (coinLowestLarger.second.first &&
1137 ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
e8ef3da7
WL
1138 {
1139 setCoinsRet.insert(coinLowestLarger.second);
1140 nValueRet += coinLowestLarger.first;
1141 }
1142 else {
c376ac35 1143 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7
WL
1144 if (vfBest[i])
1145 {
1146 setCoinsRet.insert(vValue[i].second);
1147 nValueRet += vValue[i].first;
1148 }
1149
1150 //// debug print
1151 printf("SelectCoins() best subset: ");
c376ac35 1152 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7
WL
1153 if (vfBest[i])
1154 printf("%s ", FormatMoney(vValue[i].first).c_str());
1155 printf("total %s\n", FormatMoney(nBest).c_str());
1156 }
1157
1158 return true;
1159}
1160
bde280b9 1161bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
e8ef3da7 1162{
9b0369c7
CM
1163 vector<COutput> vCoins;
1164 AvailableCoins(vCoins);
1165
1166 return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
1167 SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
1168 SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet));
e8ef3da7
WL
1169}
1170
1171
1172
1173
1f00f4e9
GA
1174bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
1175 CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
e8ef3da7 1176{
bde280b9
WL
1177 int64 nValue = 0;
1178 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
e8ef3da7
WL
1179 {
1180 if (nValue < 0)
1f00f4e9
GA
1181 {
1182 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 1183 return false;
1f00f4e9 1184 }
e8ef3da7
WL
1185 nValue += s.second;
1186 }
1187 if (vecSend.empty() || nValue < 0)
1f00f4e9
GA
1188 {
1189 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 1190 return false;
1f00f4e9 1191 }
e8ef3da7 1192
4c6e2295 1193 wtxNew.BindWallet(this);
e8ef3da7 1194
e8ef3da7 1195 {
f8dcd5ca 1196 LOCK2(cs_main, cs_wallet);
e8ef3da7
WL
1197 {
1198 nFeeRet = nTransactionFee;
1199 loop
1200 {
1201 wtxNew.vin.clear();
1202 wtxNew.vout.clear();
1203 wtxNew.fFromMe = true;
1204
bde280b9 1205 int64 nTotalValue = nValue + nFeeRet;
e8ef3da7
WL
1206 double dPriority = 0;
1207 // vouts to the payees
bde280b9 1208 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
8de9bb53
GA
1209 {
1210 CTxOut txout(s.second, s.first);
05df3fc6 1211 if (txout.IsDust(CTransaction::nMinRelayTxFee))
1f00f4e9
GA
1212 {
1213 strFailReason = _("Transaction amount too small");
8de9bb53 1214 return false;
1f00f4e9 1215 }
8de9bb53
GA
1216 wtxNew.vout.push_back(txout);
1217 }
e8ef3da7
WL
1218
1219 // Choose coins to use
1220 set<pair<const CWalletTx*,unsigned int> > setCoins;
bde280b9 1221 int64 nValueIn = 0;
e8ef3da7 1222 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
1f00f4e9
GA
1223 {
1224 strFailReason = _("Insufficient funds");
e8ef3da7 1225 return false;
1f00f4e9 1226 }
e8ef3da7
WL
1227 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1228 {
bde280b9 1229 int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
d7836552
GM
1230 //The priority after the next block (depth+1) is used instead of the current,
1231 //reflecting an assumption the user would accept a bit more delay for
1232 //a chance at a free transaction.
1233 dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1);
e8ef3da7
WL
1234 }
1235
bde280b9 1236 int64 nChange = nValueIn - nValue - nFeeRet;
000dc551 1237 // if sub-cent change is required, the fee must be raised to at least nMinTxFee
a7dd11c6 1238 // or until nChange becomes zero
dbbf1d4a 1239 // NOTE: this depends on the exact behaviour of GetMinFee
000dc551 1240 if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
a7dd11c6 1241 {
000dc551 1242 int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
a7dd11c6
PW
1243 nChange -= nMoveToFee;
1244 nFeeRet += nMoveToFee;
1245 }
1246
1247 if (nChange > 0)
e8ef3da7
WL
1248 {
1249 // Note: We use a new key here to keep it from being obvious which side is the change.
1250 // The drawback is that by not reusing a previous key, the change may be lost if a
1251 // backup is restored, if the backup doesn't have the new private key for the change.
1252 // If we reused the old key, it would be possible to add code to look for and
1253 // rediscover unknown transactions that were written with keys of ours to recover
1254 // post-backup change.
1255
1256 // Reserve a new key pair from key pool
360cfe14
PW
1257 CPubKey vchPubKey;
1258 assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
e8ef3da7 1259
bf798734
GA
1260 // Fill a vout to ourself
1261 // TODO: pass in scriptChange instead of reservekey so
1262 // change transaction isn't always pay-to-bitcoin-address
e8ef3da7 1263 CScript scriptChange;
10254401 1264 scriptChange.SetDestination(vchPubKey.GetID());
e8ef3da7 1265
8de9bb53
GA
1266 CTxOut newTxOut(nChange, scriptChange);
1267
1268 // Never create dust outputs; if we would, just
1269 // add the dust to the fee.
05df3fc6 1270 if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
8de9bb53
GA
1271 {
1272 nFeeRet += nChange;
1273 reservekey.ReturnKey();
1274 }
1275 else
1276 {
1277 // Insert change txn at random position:
1278 vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
1279 wtxNew.vout.insert(position, newTxOut);
1280 }
e8ef3da7
WL
1281 }
1282 else
1283 reservekey.ReturnKey();
1284
1285 // Fill vin
1286 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1287 wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1288
1289 // Sign
1290 int nIn = 0;
1291 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1292 if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1f00f4e9
GA
1293 {
1294 strFailReason = _("Signing transaction failed");
e8ef3da7 1295 return false;
1f00f4e9 1296 }
e8ef3da7
WL
1297
1298 // Limit size
6b6aaa16 1299 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
41e1a0d7 1300 if (nBytes >= MAX_STANDARD_TX_SIZE)
1f00f4e9
GA
1301 {
1302 strFailReason = _("Transaction too large");
e8ef3da7 1303 return false;
1f00f4e9 1304 }
e8ef3da7
WL
1305 dPriority /= nBytes;
1306
1307 // Check that enough fee is included
bde280b9 1308 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
05df3fc6 1309 bool fAllowFree = AllowFree(dPriority);
87cce04c 1310 int64 nMinFee = GetMinFee(wtxNew, fAllowFree, GMF_SEND);
e8ef3da7
WL
1311 if (nFeeRet < max(nPayFee, nMinFee))
1312 {
1313 nFeeRet = max(nPayFee, nMinFee);
1314 continue;
1315 }
1316
1317 // Fill vtxPrev by copying from previous transactions vtxPrev
450cbb09 1318 wtxNew.AddSupportingTransactions();
e8ef3da7
WL
1319 wtxNew.fTimeReceivedIsTxTime = true;
1320
1321 break;
1322 }
1323 }
1324 }
1325 return true;
1326}
1327
1f00f4e9
GA
1328bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue,
1329 CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
e8ef3da7 1330{
bde280b9 1331 vector< pair<CScript, int64> > vecSend;
e8ef3da7 1332 vecSend.push_back(make_pair(scriptPubKey, nValue));
1f00f4e9 1333 return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason);
e8ef3da7
WL
1334}
1335
1336// Call after CreateTransaction unless you want to abort
1337bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1338{
e8ef3da7 1339 {
f8dcd5ca 1340 LOCK2(cs_main, cs_wallet);
e8ef3da7 1341 printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
e8ef3da7
WL
1342 {
1343 // This is only to keep the database open to defeat the auto-flush for the
1344 // duration of this scope. This is the only place where this optimization
1345 // maybe makes sense; please don't do it anywhere else.
1346 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1347
1348 // Take key pair from key pool so it won't be used again
1349 reservekey.KeepKey();
1350
1351 // Add tx to wallet, because if it has change it's also ours,
1352 // otherwise just for transaction history.
1353 AddToWallet(wtxNew);
1354
1355 // Mark old coins as spent
1356 set<CWalletTx*> setCoins;
1357 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1358 {
1359 CWalletTx &coin = mapWallet[txin.prevout.hash];
4c6e2295 1360 coin.BindWallet(this);
e8ef3da7
WL
1361 coin.MarkSpent(txin.prevout.n);
1362 coin.WriteToDisk();
fe4a6550 1363 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
e8ef3da7
WL
1364 }
1365
1366 if (fFileBacked)
1367 delete pwalletdb;
1368 }
1369
1370 // Track how many getdata requests our transaction gets
6cc4a62c 1371 mapRequestCount[wtxNew.GetHash()] = 0;
e8ef3da7
WL
1372
1373 // Broadcast
b1f15b21 1374 if (!wtxNew.AcceptToMemoryPool(false))
e8ef3da7
WL
1375 {
1376 // This must not fail. The transaction has already been signed and recorded.
1377 printf("CommitTransaction() : Error: Transaction not valid");
1378 return false;
1379 }
1380 wtxNew.RelayWalletTransaction();
1381 }
e8ef3da7
WL
1382 return true;
1383}
1384
1385
1386
1387
bde280b9 1388string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
e8ef3da7
WL
1389{
1390 CReserveKey reservekey(this);
bde280b9 1391 int64 nFeeRequired;
6cc4a62c
GA
1392
1393 if (IsLocked())
e8ef3da7 1394 {
6b3783a9 1395 string strError = _("Error: Wallet locked, unable to create transaction!");
6cc4a62c
GA
1396 printf("SendMoney() : %s", strError.c_str());
1397 return strError;
1398 }
1f00f4e9
GA
1399 string strError;
1400 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
6cc4a62c 1401 {
6cc4a62c 1402 if (nValue + nFeeRequired > GetBalance())
6b3783a9 1403 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());
1f00f4e9 1404 printf("SendMoney() : %s\n", strError.c_str());
6cc4a62c 1405 return strError;
e8ef3da7
WL
1406 }
1407
15d8ff20 1408 if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired))
e8ef3da7
WL
1409 return "ABORTED";
1410
1411 if (!CommitTransaction(wtxNew, reservekey))
6b3783a9 1412 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 1413
e8ef3da7
WL
1414 return "";
1415}
1416
1417
1418
10254401 1419string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
e8ef3da7
WL
1420{
1421 // Check amount
1422 if (nValue <= 0)
1423 return _("Invalid amount");
1424 if (nValue + nTransactionFee > GetBalance())
1425 return _("Insufficient funds");
1426
ff0ee876 1427 // Parse Bitcoin address
e8ef3da7 1428 CScript scriptPubKey;
10254401 1429 scriptPubKey.SetDestination(address);
e8ef3da7
WL
1430
1431 return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1432}
1433
1434
1435
1436
eed1785f 1437DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
e8ef3da7
WL
1438{
1439 if (!fFileBacked)
4f76be1d 1440 return DB_LOAD_OK;
e8ef3da7 1441 fFirstRunRet = false;
eed1785f 1442 DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
d764d916 1443 if (nLoadWalletRet == DB_NEED_REWRITE)
9e9869d0 1444 {
d764d916
GA
1445 if (CDB::Rewrite(strWalletFile, "\x04pool"))
1446 {
1447 setKeyPool.clear();
1448 // Note: can't top-up keypool here, because wallet is locked.
1449 // User will be prompted to unlock wallet the next operation
1450 // the requires a new key.
1451 }
9e9869d0
PW
1452 }
1453
7ec55267
MC
1454 if (nLoadWalletRet != DB_LOAD_OK)
1455 return nLoadWalletRet;
fd61d6f5 1456 fFirstRunRet = !vchDefaultKey.IsValid();
e8ef3da7 1457
116df55e 1458 return DB_LOAD_OK;
e8ef3da7
WL
1459}
1460
ae3d0aba 1461
10254401 1462bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
ae3d0aba 1463{
10254401 1464 std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
2ffba736 1465 mapAddressBook[address] = strName;
10254401 1466 NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
ae3d0aba
WL
1467 if (!fFileBacked)
1468 return false;
10254401 1469 return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
ae3d0aba
WL
1470}
1471
10254401 1472bool CWallet::DelAddressBookName(const CTxDestination& address)
ae3d0aba 1473{
2ffba736 1474 mapAddressBook.erase(address);
10254401 1475 NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
ae3d0aba
WL
1476 if (!fFileBacked)
1477 return false;
10254401 1478 return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
ae3d0aba
WL
1479}
1480
1481
e8ef3da7
WL
1482void CWallet::PrintWallet(const CBlock& block)
1483{
e8ef3da7 1484 {
f8dcd5ca 1485 LOCK(cs_wallet);
e8ef3da7
WL
1486 if (mapWallet.count(block.vtx[0].GetHash()))
1487 {
1488 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
d210f4f5 1489 printf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
e8ef3da7
WL
1490 }
1491 }
1492 printf("\n");
1493}
1494
1495bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1496{
e8ef3da7 1497 {
f8dcd5ca 1498 LOCK(cs_wallet);
e8ef3da7
WL
1499 map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1500 if (mi != mapWallet.end())
1501 {
1502 wtx = (*mi).second;
1503 return true;
1504 }
1505 }
1506 return false;
1507}
1508
fd61d6f5 1509bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
ae3d0aba
WL
1510{
1511 if (fFileBacked)
1512 {
1513 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1514 return false;
1515 }
1516 vchDefaultKey = vchPubKey;
1517 return true;
1518}
1519
e8ef3da7
WL
1520bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1521{
1522 if (!pwallet->fFileBacked)
1523 return false;
1524 strWalletFileOut = pwallet->strWalletFile;
1525 return true;
1526}
1527
37971fcc
GA
1528//
1529// Mark old keypool keys as used,
1530// and generate all new keys
1531//
1532bool CWallet::NewKeyPool()
1533{
37971fcc 1534 {
f8dcd5ca 1535 LOCK(cs_wallet);
37971fcc 1536 CWalletDB walletdb(strWalletFile);
bde280b9 1537 BOOST_FOREACH(int64 nIndex, setKeyPool)
37971fcc
GA
1538 walletdb.ErasePool(nIndex);
1539 setKeyPool.clear();
1540
1541 if (IsLocked())
1542 return false;
1543
bde280b9 1544 int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
37971fcc
GA
1545 for (int i = 0; i < nKeys; i++)
1546 {
bde280b9 1547 int64 nIndex = i+1;
37971fcc
GA
1548 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1549 setKeyPool.insert(nIndex);
1550 }
1551 printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1552 }
1553 return true;
1554}
1555
4e87d341 1556bool CWallet::TopUpKeyPool()
e8ef3da7 1557{
e8ef3da7 1558 {
f8dcd5ca
PW
1559 LOCK(cs_wallet);
1560
4e87d341
MC
1561 if (IsLocked())
1562 return false;
1563
e8ef3da7
WL
1564 CWalletDB walletdb(strWalletFile);
1565
1566 // Top up key pool
faf705a4
JG
1567 unsigned int nTargetSize = max(GetArg("-keypool", 100), 0LL);
1568 while (setKeyPool.size() < (nTargetSize + 1))
e8ef3da7 1569 {
bde280b9 1570 int64 nEnd = 1;
e8ef3da7
WL
1571 if (!setKeyPool.empty())
1572 nEnd = *(--setKeyPool.end()) + 1;
1573 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
4e87d341 1574 throw runtime_error("TopUpKeyPool() : writing generated key failed");
e8ef3da7 1575 setKeyPool.insert(nEnd);
d210f4f5 1576 printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
e8ef3da7 1577 }
4e87d341
MC
1578 }
1579 return true;
1580}
1581
bde280b9 1582void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
4e87d341
MC
1583{
1584 nIndex = -1;
fd61d6f5 1585 keypool.vchPubKey = CPubKey();
4e87d341 1586 {
f8dcd5ca
PW
1587 LOCK(cs_wallet);
1588
4e87d341
MC
1589 if (!IsLocked())
1590 TopUpKeyPool();
e8ef3da7
WL
1591
1592 // Get the oldest key
4e87d341
MC
1593 if(setKeyPool.empty())
1594 return;
1595
1596 CWalletDB walletdb(strWalletFile);
1597
e8ef3da7
WL
1598 nIndex = *(setKeyPool.begin());
1599 setKeyPool.erase(setKeyPool.begin());
1600 if (!walletdb.ReadPool(nIndex, keypool))
1601 throw runtime_error("ReserveKeyFromKeyPool() : read failed");
fd61d6f5 1602 if (!HaveKey(keypool.vchPubKey.GetID()))
e8ef3da7 1603 throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
fd61d6f5 1604 assert(keypool.vchPubKey.IsValid());
e8ef3da7
WL
1605 printf("keypool reserve %"PRI64d"\n", nIndex);
1606 }
1607}
1608
bde280b9 1609int64 CWallet::AddReserveKey(const CKeyPool& keypool)
30ab2c9c 1610{
30ab2c9c 1611 {
f8dcd5ca 1612 LOCK2(cs_main, cs_wallet);
30ab2c9c
PW
1613 CWalletDB walletdb(strWalletFile);
1614
bde280b9 1615 int64 nIndex = 1 + *(--setKeyPool.end());
30ab2c9c
PW
1616 if (!walletdb.WritePool(nIndex, keypool))
1617 throw runtime_error("AddReserveKey() : writing added key failed");
1618 setKeyPool.insert(nIndex);
1619 return nIndex;
1620 }
1621 return -1;
1622}
1623
bde280b9 1624void CWallet::KeepKey(int64 nIndex)
e8ef3da7
WL
1625{
1626 // Remove from key pool
1627 if (fFileBacked)
1628 {
1629 CWalletDB walletdb(strWalletFile);
6cc4a62c 1630 walletdb.ErasePool(nIndex);
e8ef3da7
WL
1631 }
1632 printf("keypool keep %"PRI64d"\n", nIndex);
1633}
1634
bde280b9 1635void CWallet::ReturnKey(int64 nIndex)
e8ef3da7
WL
1636{
1637 // Return to key pool
f8dcd5ca
PW
1638 {
1639 LOCK(cs_wallet);
e8ef3da7 1640 setKeyPool.insert(nIndex);
f8dcd5ca 1641 }
e8ef3da7
WL
1642 printf("keypool return %"PRI64d"\n", nIndex);
1643}
1644
fd61d6f5 1645bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
e8ef3da7 1646{
bde280b9 1647 int64 nIndex = 0;
e8ef3da7 1648 CKeyPool keypool;
7db3b75b 1649 {
f8dcd5ca 1650 LOCK(cs_wallet);
ed02c95d
GA
1651 ReserveKeyFromKeyPool(nIndex, keypool);
1652 if (nIndex == -1)
7db3b75b 1653 {
fd61d6f5 1654 if (fAllowReuse && vchDefaultKey.IsValid())
ed02c95d
GA
1655 {
1656 result = vchDefaultKey;
1657 return true;
1658 }
1659 if (IsLocked()) return false;
1660 result = GenerateNewKey();
7db3b75b
GA
1661 return true;
1662 }
ed02c95d
GA
1663 KeepKey(nIndex);
1664 result = keypool.vchPubKey;
7db3b75b 1665 }
7db3b75b 1666 return true;
e8ef3da7
WL
1667}
1668
bde280b9 1669int64 CWallet::GetOldestKeyPoolTime()
e8ef3da7 1670{
bde280b9 1671 int64 nIndex = 0;
e8ef3da7
WL
1672 CKeyPool keypool;
1673 ReserveKeyFromKeyPool(nIndex, keypool);
4e87d341
MC
1674 if (nIndex == -1)
1675 return GetTime();
e8ef3da7
WL
1676 ReturnKey(nIndex);
1677 return keypool.nTime;
1678}
1679
b1093efa 1680std::map<CTxDestination, int64> CWallet::GetAddressBalances()
22dfd735 1681{
b1093efa 1682 map<CTxDestination, int64> balances;
22dfd735 1683
1684 {
1685 LOCK(cs_wallet);
1686 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1687 {
1688 CWalletTx *pcoin = &walletEntry.second;
1689
05df3fc6 1690 if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
22dfd735 1691 continue;
1692
1693 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1694 continue;
1695
1696 int nDepth = pcoin->GetDepthInMainChain();
1697 if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
1698 continue;
1699
b1093efa 1700 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 1701 {
b1093efa 1702 CTxDestination addr;
22dfd735 1703 if (!IsMine(pcoin->vout[i]))
1704 continue;
b1093efa
GM
1705 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
1706 continue;
22dfd735 1707
1708 int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
1709
22dfd735 1710 if (!balances.count(addr))
1711 balances[addr] = 0;
1712 balances[addr] += n;
1713 }
1714 }
1715 }
1716
1717 return balances;
1718}
1719
b1093efa 1720set< set<CTxDestination> > CWallet::GetAddressGroupings()
22dfd735 1721{
b1093efa
GM
1722 set< set<CTxDestination> > groupings;
1723 set<CTxDestination> grouping;
22dfd735 1724
1725 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1726 {
1727 CWalletTx *pcoin = &walletEntry.second;
1728
a3fad211 1729 if (pcoin->vin.size() > 0)
22dfd735 1730 {
a3fad211 1731 bool any_mine = false;
22dfd735 1732 // group all input addresses with each other
1733 BOOST_FOREACH(CTxIn txin, pcoin->vin)
b1093efa
GM
1734 {
1735 CTxDestination address;
a3fad211
GM
1736 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
1737 continue;
b1093efa
GM
1738 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
1739 continue;
1740 grouping.insert(address);
a3fad211 1741 any_mine = true;
b1093efa 1742 }
22dfd735 1743
1744 // group change with input addresses
a3fad211
GM
1745 if (any_mine)
1746 {
1747 BOOST_FOREACH(CTxOut txout, pcoin->vout)
1748 if (IsChange(txout))
1749 {
1750 CTxDestination txoutAddr;
1751 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
1752 continue;
1753 grouping.insert(txoutAddr);
1754 }
1755 }
1756 if (grouping.size() > 0)
1757 {
1758 groupings.insert(grouping);
1759 grouping.clear();
1760 }
22dfd735 1761 }
1762
1763 // group lone addrs by themselves
b1093efa 1764 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 1765 if (IsMine(pcoin->vout[i]))
1766 {
b1093efa
GM
1767 CTxDestination address;
1768 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
1769 continue;
1770 grouping.insert(address);
22dfd735 1771 groupings.insert(grouping);
1772 grouping.clear();
1773 }
1774 }
1775
b1093efa
GM
1776 set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
1777 map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
1778 BOOST_FOREACH(set<CTxDestination> grouping, groupings)
22dfd735 1779 {
1780 // make a set of all the groups hit by this new group
b1093efa
GM
1781 set< set<CTxDestination>* > hits;
1782 map< CTxDestination, set<CTxDestination>* >::iterator it;
1783 BOOST_FOREACH(CTxDestination address, grouping)
22dfd735 1784 if ((it = setmap.find(address)) != setmap.end())
1785 hits.insert((*it).second);
1786
1787 // merge all hit groups into a new single group and delete old groups
b1093efa
GM
1788 set<CTxDestination>* merged = new set<CTxDestination>(grouping);
1789 BOOST_FOREACH(set<CTxDestination>* hit, hits)
22dfd735 1790 {
1791 merged->insert(hit->begin(), hit->end());
1792 uniqueGroupings.erase(hit);
1793 delete hit;
1794 }
1795 uniqueGroupings.insert(merged);
1796
1797 // update setmap
b1093efa 1798 BOOST_FOREACH(CTxDestination element, *merged)
22dfd735 1799 setmap[element] = merged;
1800 }
1801
b1093efa
GM
1802 set< set<CTxDestination> > ret;
1803 BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
22dfd735 1804 {
1805 ret.insert(*uniqueGrouping);
1806 delete uniqueGrouping;
1807 }
1808
1809 return ret;
1810}
1811
360cfe14 1812bool CReserveKey::GetReservedKey(CPubKey& pubkey)
e8ef3da7
WL
1813{
1814 if (nIndex == -1)
1815 {
1816 CKeyPool keypool;
1817 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
0d7b28e5
MC
1818 if (nIndex != -1)
1819 vchPubKey = keypool.vchPubKey;
360cfe14
PW
1820 else {
1821 if (pwallet->vchDefaultKey.IsValid()) {
1822 printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
1823 vchPubKey = pwallet->vchDefaultKey;
1824 } else
1825 return false;
cee69980 1826 }
e8ef3da7 1827 }
fd61d6f5 1828 assert(vchPubKey.IsValid());
360cfe14
PW
1829 pubkey = vchPubKey;
1830 return true;
e8ef3da7
WL
1831}
1832
1833void CReserveKey::KeepKey()
1834{
1835 if (nIndex != -1)
1836 pwallet->KeepKey(nIndex);
1837 nIndex = -1;
fd61d6f5 1838 vchPubKey = CPubKey();
e8ef3da7
WL
1839}
1840
1841void CReserveKey::ReturnKey()
1842{
1843 if (nIndex != -1)
1844 pwallet->ReturnKey(nIndex);
1845 nIndex = -1;
fd61d6f5 1846 vchPubKey = CPubKey();
e8ef3da7 1847}
ae3d0aba 1848
434e4273 1849void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
30ab2c9c
PW
1850{
1851 setAddress.clear();
1852
1853 CWalletDB walletdb(strWalletFile);
1854
f8dcd5ca 1855 LOCK2(cs_main, cs_wallet);
bde280b9 1856 BOOST_FOREACH(const int64& id, setKeyPool)
30ab2c9c
PW
1857 {
1858 CKeyPool keypool;
1859 if (!walletdb.ReadPool(id, keypool))
1860 throw runtime_error("GetAllReserveKeyHashes() : read failed");
fd61d6f5 1861 assert(keypool.vchPubKey.IsValid());
10254401
PW
1862 CKeyID keyID = keypool.vchPubKey.GetID();
1863 if (!HaveKey(keyID))
30ab2c9c 1864 throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
10254401 1865 setAddress.insert(keyID);
30ab2c9c
PW
1866 }
1867}
fe4a6550
WL
1868
1869void CWallet::UpdatedTransaction(const uint256 &hashTx)
1870{
1871 {
1872 LOCK(cs_wallet);
1873 // Only notify UI if this transaction is in this wallet
1874 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
1875 if (mi != mapWallet.end())
1876 NotifyTransactionChanged(this, hashTx, CT_UPDATED);
1877 }
1878}
fdbb537d
JG
1879
1880void CWallet::LockCoin(COutPoint& output)
1881{
1882 setLockedCoins.insert(output);
1883}
1884
1885void CWallet::UnlockCoin(COutPoint& output)
1886{
1887 setLockedCoins.erase(output);
1888}
1889
1890void CWallet::UnlockAllCoins()
1891{
1892 setLockedCoins.clear();
1893}
1894
1895bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
1896{
1897 COutPoint outpt(hash, n);
1898
1899 return (setLockedCoins.count(outpt) > 0);
1900}
1901
1902void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
1903{
1904 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
1905 it != setLockedCoins.end(); it++) {
1906 COutPoint outpt = (*it);
1907 vOutpts.push_back(outpt);
1908 }
1909}
1910
434e4273
PW
1911void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
1912 mapKeyBirth.clear();
1913
1914 // get birth times for keys with metadata
1915 for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
1916 if (it->second.nCreateTime)
1917 mapKeyBirth[it->first] = it->second.nCreateTime;
1918
1919 // map in which we'll infer heights of other keys
1920 CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
1921 std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
1922 std::set<CKeyID> setKeys;
1923 GetKeys(setKeys);
1924 BOOST_FOREACH(const CKeyID &keyid, setKeys) {
1925 if (mapKeyBirth.count(keyid) == 0)
1926 mapKeyFirstBlock[keyid] = pindexMax;
1927 }
1928 setKeys.clear();
1929
1930 // if there are no such keys, we're done
1931 if (mapKeyFirstBlock.empty())
1932 return;
1933
1934 // find first block that affects those keys, if there are any left
1935 std::vector<CKeyID> vAffected;
1936 for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
1937 // iterate over all wallet transactions...
1938 const CWalletTx &wtx = (*it).second;
1939 std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
1940 if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
1941 // ... which are already in a block
1942 int nHeight = blit->second->nHeight;
1943 BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
1944 // iterate over all their outputs
1945 ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
1946 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
1947 // ... and all their affected keys
1948 std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
1949 if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
1950 rit->second = blit->second;
1951 }
1952 vAffected.clear();
1953 }
1954 }
1955 }
1956
1957 // Extract block timestamps for those keys
1958 for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
1959 mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
1960}
This page took 0.406666 seconds and 4 git commands to generate.