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