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