wallet.cpp 65.1 KB
Newer Older
Matt Corallo's avatar
Matt Corallo committed
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
Gavin Andresen's avatar
Gavin Andresen committed
2
// Copyright (c) 2009-2012 The Bitcoin developers
3
// Distributed under the MIT/X11 software license, see the accompanying
Fordy's avatar
Fordy committed
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5

6
7
#include "wallet.h"
#include "walletdb.h"
Matt Corallo's avatar
Matt Corallo committed
8
#include "crypter.h"
9
#include "ui_interface.h"
10
#include "base58.h"
11
#include <boost/algorithm/string/replace.hpp>
12
13
14
15
16
17
18
19
20

using namespace std;


//////////////////////////////////////////////////////////////////////////////
//
// mapWallet
//

21
22
23
24
25
26
27
28
29
struct CompareValueOnly
{
    bool operator()(const pair<int64, pair<const CWalletTx*, unsigned int> >& t1,
                    const pair<int64, pair<const CWalletTx*, unsigned int> >& t2) const
    {
        return t1.first < t2.first;
    }
};

30
CPubKey CWallet::GenerateNewKey()
31
{
32
    bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
33

34
    RandAddSeedPerfmon();
35
36
    CKey secret;
    secret.MakeNewKey(fCompressed);
37
38
39

    // Compressed public keys were introduced in version 0.6.0
    if (fCompressed)
40
        SetMinVersion(FEATURE_COMPRPUBKEY);
41

42
    CPubKey pubkey = secret.GetPubKey();
43
44
45
46
47
48
49

    // Create new metadata
    int64 nCreationTime = GetTime();
    mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
    if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
        nTimeFirstKey = nCreationTime;

50
    if (!AddKeyPubKey(secret, pubkey))
51
        throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
52
    return pubkey;
53
}
54

55
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
56
{
57
    if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
58
        return false;
59
60
    if (!fFileBacked)
        return true;
61
    if (!IsCrypted()) {
62
63
        return CWalletDB(strWalletFile).WriteKey(pubkey,
                                                 secret.GetPrivKey(),
64
                                                 mapKeyMetadata[pubkey.GetID()]);
65
    }
66
    return true;
Matt Corallo's avatar
Matt Corallo committed
67
68
}

69
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
70
                            const vector<unsigned char> &vchCryptedSecret)
Matt Corallo's avatar
Matt Corallo committed
71
72
73
74
75
{
    if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
        return false;
    if (!fFileBacked)
        return true;
76
    {
77
        LOCK(cs_wallet);
78
        if (pwalletdbEncryption)
79
80
            return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
                                                        vchCryptedSecret,
81
                                                        mapKeyMetadata[vchPubKey.GetID()]);
82
        else
83
84
            return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
                                                            vchCryptedSecret,
85
                                                            mapKeyMetadata[vchPubKey.GetID()]);
86
    }
87
    return false;
Matt Corallo's avatar
Matt Corallo committed
88
89
}

90
91
92
93
94
95
96
97
98
bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
{
    if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
        nTimeFirstKey = meta.nCreateTime;

    mapKeyMetadata[pubkey.GetID()] = meta;
    return true;
}

99
100
101
102
103
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
    return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
}

104
bool CWallet::AddCScript(const CScript& redeemScript)
Gavin Andresen's avatar
Gavin Andresen committed
105
{
106
    if (!CCryptoKeyStore::AddCScript(redeemScript))
Gavin Andresen's avatar
Gavin Andresen committed
107
108
109
        return false;
    if (!fFileBacked)
        return true;
110
    return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
Gavin Andresen's avatar
Gavin Andresen committed
111
112
}

113
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
114
{
Gavin Andresen's avatar
Gavin Andresen committed
115
116
    CCrypter crypter;
    CKeyingMaterial vMasterKey;
Matt Corallo's avatar
Matt Corallo committed
117

118
119
    {
        LOCK(cs_wallet);
Matt Corallo's avatar
Matt Corallo committed
120
121
122
123
124
        BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
        {
            if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
                return false;
            if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
125
                continue; // try another master key
Matt Corallo's avatar
Matt Corallo committed
126
127
128
            if (CCryptoKeyStore::Unlock(vMasterKey))
                return true;
        }
129
    }
Matt Corallo's avatar
Matt Corallo committed
130
131
132
    return false;
}

133
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
134
{
Gavin Andresen's avatar
Gavin Andresen committed
135
    bool fWasLocked = IsLocked();
Matt Corallo's avatar
Matt Corallo committed
136

Gavin Andresen's avatar
Gavin Andresen committed
137
    {
138
        LOCK(cs_wallet);
Matt Corallo's avatar
Matt Corallo committed
139
140
141
142
143
144
145
146
        Lock();

        CCrypter crypter;
        CKeyingMaterial vMasterKey;
        BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
        {
            if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
                return false;
Gavin Andresen's avatar
Gavin Andresen committed
147
            if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
Matt Corallo's avatar
Matt Corallo committed
148
149
150
                return false;
            if (CCryptoKeyStore::Unlock(vMasterKey))
            {
151
                int64 nStartTime = GetTimeMillis();
152
153
154
155
156
157
158
159
160
161
                crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
                pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));

                nStartTime = GetTimeMillis();
                crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
                pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;

                if (pMasterKey.second.nDeriveIterations < 25000)
                    pMasterKey.second.nDeriveIterations = 25000;

162
                LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
163

Matt Corallo's avatar
Matt Corallo committed
164
165
166
167
168
169
170
171
172
173
174
                if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
                    return false;
                if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
                    return false;
                CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
                if (fWasLocked)
                    Lock();
                return true;
            }
        }
    }
Gavin Andresen's avatar
Gavin Andresen committed
175

Matt Corallo's avatar
Matt Corallo committed
176
177
178
    return false;
}

Pieter Wuille's avatar
Pieter Wuille committed
179
180
181
182
183
void CWallet::SetBestChain(const CBlockLocator& loc)
{
    CWalletDB walletdb(strWalletFile);
    walletdb.WriteBestBlock(loc);
}
184
185
186
187
188
189
190
191
192
193
194
195
196

// This class implements an addrIncoming entry that causes pre-0.4
// clients to crash on startup if reading a private-key-encrypted wallet.
class CCorruptAddress
{
public:
    IMPLEMENT_SERIALIZE
    (
        if (nType & SER_DISK)
            READWRITE(nVersion);
    )
};

197
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
Pieter Wuille's avatar
Pieter Wuille committed
198
199
200
201
{
    if (nWalletVersion >= nVersion)
        return true;

202
203
204
205
    // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
    if (fExplicit && nVersion > nWalletMaxVersion)
            nVersion = FEATURE_LATEST;

Pieter Wuille's avatar
Pieter Wuille committed
206
207
    nWalletVersion = nVersion;

208
209
210
    if (nVersion > nWalletMaxVersion)
        nWalletMaxVersion = nVersion;

Pieter Wuille's avatar
Pieter Wuille committed
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
    if (fFileBacked)
    {
        CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
        if (nWalletVersion >= 40000)
        {
            // Versions prior to 0.4.0 did not support the "minversion" record.
            // Use a CCorruptAddress to make them crash instead.
            CCorruptAddress corruptAddress;
            pwalletdb->WriteSetting("addrIncoming", corruptAddress);
        }
        if (nWalletVersion > 40000)
            pwalletdb->WriteMinVersion(nWalletVersion);
        if (!pwalletdbIn)
            delete pwalletdb;
    }

    return true;
}

230
231
232
233
234
235
236
237
238
239
240
bool CWallet::SetMaxVersion(int nVersion)
{
    // cannot downgrade below current version
    if (nWalletVersion > nVersion)
        return false;

    nWalletMaxVersion = nVersion;

    return true;
}

241
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
242
{
Gavin Andresen's avatar
Gavin Andresen committed
243
244
    if (IsCrypted())
        return false;
Matt Corallo's avatar
Matt Corallo committed
245

Gavin Andresen's avatar
Gavin Andresen committed
246
247
    CKeyingMaterial vMasterKey;
    RandAddSeedPerfmon();
Matt Corallo's avatar
Matt Corallo committed
248

Gavin Andresen's avatar
Gavin Andresen committed
249
250
    vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
    RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
Matt Corallo's avatar
Matt Corallo committed
251

Gavin Andresen's avatar
Gavin Andresen committed
252
    CMasterKey kMasterKey;
Matt Corallo's avatar
Matt Corallo committed
253

Gavin Andresen's avatar
Gavin Andresen committed
254
255
256
    RandAddSeedPerfmon();
    kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
    RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
Matt Corallo's avatar
Matt Corallo committed
257

Gavin Andresen's avatar
Gavin Andresen committed
258
    CCrypter crypter;
259
    int64 nStartTime = GetTimeMillis();
Gavin Andresen's avatar
Gavin Andresen committed
260
261
    crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
    kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
262

Gavin Andresen's avatar
Gavin Andresen committed
263
264
265
    nStartTime = GetTimeMillis();
    crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
    kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
266

Gavin Andresen's avatar
Gavin Andresen committed
267
268
    if (kMasterKey.nDeriveIterations < 25000)
        kMasterKey.nDeriveIterations = 25000;
269

270
    LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
271

Gavin Andresen's avatar
Gavin Andresen committed
272
273
274
275
    if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
        return false;
    if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
        return false;
Matt Corallo's avatar
Matt Corallo committed
276

Gavin Andresen's avatar
Gavin Andresen committed
277
    {
278
        LOCK(cs_wallet);
Matt Corallo's avatar
Matt Corallo committed
279
280
281
        mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
        if (fFileBacked)
        {
282
            pwalletdbEncryption = new CWalletDB(strWalletFile);
283
284
            if (!pwalletdbEncryption->TxnBegin())
                return false;
285
            pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
Matt Corallo's avatar
Matt Corallo committed
286
287
288
        }

        if (!EncryptKeys(vMasterKey))
289
290
291
292
293
294
        {
            if (fFileBacked)
                pwalletdbEncryption->TxnAbort();
            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.
        }

Pieter Wuille's avatar
Pieter Wuille committed
295
        // Encryption was introduced in version 0.4.0
296
        SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
Pieter Wuille's avatar
Pieter Wuille committed
297

298
299
300
301
302
        if (fFileBacked)
        {
            if (!pwalletdbEncryption->TxnCommit())
                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.

303
            delete pwalletdbEncryption;
304
305
            pwalletdbEncryption = NULL;
        }
Matt Corallo's avatar
Matt Corallo committed
306

307
308
309
        Lock();
        Unlock(strWalletPassphrase);
        NewKeyPool();
Matt Corallo's avatar
Matt Corallo committed
310
        Lock();
Gavin Andresen's avatar
Gavin Andresen committed
311

312
313
        // Need to completely rewrite the wallet file; if we don't, bdb might keep
        // bits of the unencrypted private key in slack space in the database file.
314
        CDB::Rewrite(strWalletFile);
315

316
    }
317
    NotifyStatusChanged(this);
Pieter Wuille's avatar
Pieter Wuille committed
318

Matt Corallo's avatar
Matt Corallo committed
319
    return true;
320
321
}

322
int64 CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
323
{
324
325
326
327
328
329
    int64 nRet = nOrderPosNext++;
    if (pwalletdb) {
        pwalletdb->WriteOrderPosNext(nOrderPosNext);
    } else {
        CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
    }
330
331
332
    return nRet;
}

333
CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
334
335
336
337
338
339
340
341
342
343
344
345
346
{
    CWalletDB walletdb(strWalletFile);

    // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
    TxItems txOrdered;

    // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
    // would make this much faster for applications that do this a lot.
    for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
    {
        CWalletTx* wtx = &((*it).second);
        txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
    }
347
    acentries.clear();
348
349
350
351
352
353
354
355
356
    walletdb.ListAccountCreditDebit(strAccount, acentries);
    BOOST_FOREACH(CAccountingEntry& entry, acentries)
    {
        txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
    }

    return txOrdered;
}

357
358
359
360
361
362
void CWallet::WalletUpdateSpent(const CTransaction &tx)
{
    // Anytime a signature is successfully verified, it's proof the outpoint is spent.
    // Update the wallet spent flag if it doesn't know due to wallet.dat being
    // restored from backup or the user making copies of wallet.dat.
    {
363
        LOCK(cs_wallet);
364
365
366
367
368
369
        BOOST_FOREACH(const CTxIn& txin, tx.vin)
        {
            map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
            if (mi != mapWallet.end())
            {
                CWalletTx& wtx = (*mi).second;
370
                if (txin.prevout.n >= wtx.vout.size())
371
                    LogPrintf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
372
                else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
373
                {
374
                    LogPrintf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
375
376
                    wtx.MarkSpent(txin.prevout.n);
                    wtx.WriteToDisk();
377
                    NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
378
379
380
381
382
383
                }
            }
        }
    }
}

Pieter Wuille's avatar
Pieter Wuille committed
384
385
386
void CWallet::MarkDirty()
{
    {
387
        LOCK(cs_wallet);
Pieter Wuille's avatar
Pieter Wuille committed
388
389
390
391
392
        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
            item.second.MarkDirty();
    }
}

393
394
395
396
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
    uint256 hash = wtxIn.GetHash();
    {
397
        LOCK(cs_wallet);
398
399
400
        // Inserts only if not already there, returns tx inserted or tx found
        pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
        CWalletTx& wtx = (*ret.first).second;
401
        wtx.BindWallet(this);
402
403
        bool fInsertedNew = ret.second;
        if (fInsertedNew)
404
        {
405
            wtx.nTimeReceived = GetAdjustedTime();
406
            wtx.nOrderPos = IncOrderPosNext();
407
408
409
410
411
412
413
414
415
416
417

            wtx.nTimeSmart = wtx.nTimeReceived;
            if (wtxIn.hashBlock != 0)
            {
                if (mapBlockIndex.count(wtxIn.hashBlock))
                {
                    unsigned int latestNow = wtx.nTimeReceived;
                    unsigned int latestEntry = 0;
                    {
                        // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
                        int64 latestTolerated = latestNow + 300;
418
419
                        std::list<CAccountingEntry> acentries;
                        TxItems txOrdered = OrderedTxItems(acentries);
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
                        for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
                        {
                            CWalletTx *const pwtx = (*it).second.first;
                            if (pwtx == &wtx)
                                continue;
                            CAccountingEntry *const pacentry = (*it).second.second;
                            int64 nSmartTime;
                            if (pwtx)
                            {
                                nSmartTime = pwtx->nTimeSmart;
                                if (!nSmartTime)
                                    nSmartTime = pwtx->nTimeReceived;
                            }
                            else
                                nSmartTime = pacentry->nTime;
                            if (nSmartTime <= latestTolerated)
                            {
                                latestEntry = nSmartTime;
                                if (nSmartTime > latestNow)
                                    latestNow = nSmartTime;
                                break;
                            }
                        }
                    }

                    unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime;
                    wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
                }
                else
449
450
451
                    LogPrintf("AddToWallet() : found %s in block %s not in index\n",
                             wtxIn.GetHash().ToString().c_str(),
                             wtxIn.hashBlock.ToString().c_str());
452
            }
453
        }
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

        bool fUpdated = false;
        if (!fInsertedNew)
        {
            // Merge
            if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
            {
                wtx.hashBlock = wtxIn.hashBlock;
                fUpdated = true;
            }
            if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
            {
                wtx.vMerkleBranch = wtxIn.vMerkleBranch;
                wtx.nIndex = wtxIn.nIndex;
                fUpdated = true;
            }
            if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
            {
                wtx.fFromMe = wtxIn.fFromMe;
                fUpdated = true;
            }
            fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
        }

        //// debug print
479
        LogPrintf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
480
481
482
483
484

        // Write to disk
        if (fInsertedNew || fUpdated)
            if (!wtx.WriteToDisk())
                return false;
485
486

        if (!fHaveGUI) {
487
488
489
490
491
            // If default receiving address gets used, replace it with a new one
            if (vchDefaultKey.IsValid()) {
                CScript scriptDefaultKey;
                scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
                BOOST_FOREACH(const CTxOut& txout, wtx.vout)
492
                {
493
                    if (txout.scriptPubKey == scriptDefaultKey)
494
                    {
495
                        CPubKey newDefaultKey;
496
                        if (GetKeyFromPool(newDefaultKey))
497
498
                        {
                            SetDefaultKey(newDefaultKey);
499
                            SetAddressBook(vchDefaultKey.GetID(), "", "receive");
500
                        }
501
                    }
502
                }
503
            }
504
505
506
507
        }
        // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
        WalletUpdateSpent(wtx);

508
509
        // Notify UI of new or updated transaction
        NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
510
511
512
513
514
515
516
517
518
519

        // notify an external script when a wallet transaction comes in or is updated
        std::string strCmd = GetArg("-walletnotify", "");

        if ( !strCmd.empty())
        {
            boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
            boost::thread t(runCommand, strCmd); // thread runs free
        }

520
    }
521
522
523
    return true;
}

Pieter Wuille's avatar
Pieter Wuille committed
524
525
526
// Add a transaction to the wallet, or update it.
// pblock is optional, but should be provided if the transaction is known to be in a block.
// If fUpdate is true, existing transactions will be updated.
Pieter Wuille's avatar
Pieter Wuille committed
527
bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
528
529
{
    {
530
        LOCK(cs_wallet);
Gavin Andresen's avatar
Gavin Andresen committed
531
532
533
534
535
536
537
538
539
540
541
542
        bool fExisted = mapWallet.count(hash);
        if (fExisted && !fUpdate) return false;
        if (fExisted || IsMine(tx) || IsFromMe(tx))
        {
            CWalletTx wtx(this,tx);
            // Get merkle branch if transaction was found in a block
            if (pblock)
                wtx.SetMerkleBranch(pblock);
            return AddToWallet(wtx);
        }
        else
            WalletUpdateSpent(tx);
543
544
545
546
547
548
549
550
551
    }
    return false;
}

bool CWallet::EraseFromWallet(uint256 hash)
{
    if (!fFileBacked)
        return false;
    {
552
        LOCK(cs_wallet);
553
554
555
556
557
558
559
560
561
562
        if (mapWallet.erase(hash))
            CWalletDB(strWalletFile).EraseTx(hash);
    }
    return true;
}


bool CWallet::IsMine(const CTxIn &txin) const
{
    {
563
        LOCK(cs_wallet);
564
565
566
567
568
569
570
571
572
573
574
575
        map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
        if (mi != mapWallet.end())
        {
            const CWalletTx& prev = (*mi).second;
            if (txin.prevout.n < prev.vout.size())
                if (IsMine(prev.vout[txin.prevout.n]))
                    return true;
        }
    }
    return false;
}

576
int64 CWallet::GetDebit(const CTxIn &txin) const
577
578
{
    {
579
        LOCK(cs_wallet);
580
581
582
583
584
585
586
587
588
589
590
591
        map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
        if (mi != mapWallet.end())
        {
            const CWalletTx& prev = (*mi).second;
            if (txin.prevout.n < prev.vout.size())
                if (IsMine(prev.vout[txin.prevout.n]))
                    return prev.vout[txin.prevout.n].nValue;
        }
    }
    return 0;
}

Gavin Andresen's avatar
Gavin Andresen committed
592
593
bool CWallet::IsChange(const CTxOut& txout) const
{
594
    CTxDestination address;
595
596
597
598
599
600
601
602

    // TODO: fix handling of 'change' outputs. The assumption is that any
    // payment to a TX_PUBKEYHASH that is mine but isn't in the address book
    // is change. That assumption is likely to break when we implement multisignature
    // wallets that return change back into a multi-signature-protected address;
    // a better way of identifying which outputs are 'the send' and which are
    // 'the change' will need to be implemented (maybe extend CWalletTx to remember
    // which output, if any, was change).
603
    if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
604
605
606
607
608
    {
        LOCK(cs_wallet);
        if (!mapAddressBook.count(address))
            return true;
    }
Gavin Andresen's avatar
Gavin Andresen committed
609
610
611
    return false;
}

612
int64 CWalletTx::GetTxTime() const
613
{
614
615
    int64 n = nTimeSmart;
    return n ? n : nTimeReceived;
616
617
618
619
620
621
622
}

int CWalletTx::GetRequestCount() const
{
    // Returns -1 if it wasn't being tracked
    int nRequests = -1;
    {
623
        LOCK(pwallet->cs_wallet);
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
        if (IsCoinBase())
        {
            // Generated block
            if (hashBlock != 0)
            {
                map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
                if (mi != pwallet->mapRequestCount.end())
                    nRequests = (*mi).second;
            }
        }
        else
        {
            // Did anyone request this transaction?
            map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
            if (mi != pwallet->mapRequestCount.end())
            {
                nRequests = (*mi).second;

                // How about the block it's in?
                if (nRequests == 0 && hashBlock != 0)
                {
                    map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
                    if (mi != pwallet->mapRequestCount.end())
                        nRequests = (*mi).second;
                    else
                        nRequests = 1; // If it's in someone else's block it must have got out
                }
            }
        }
    }
    return nRequests;
}

657
void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
658
                           list<pair<CTxDestination, int64> >& listSent, int64& nFee, string& strSentAccount) const
659
{
660
    nFee = 0;
661
662
663
664
665
    listReceived.clear();
    listSent.clear();
    strSentAccount = strFromAccount;

    // Compute fee:
666
    int64 nDebit = GetDebit();
667
668
    if (nDebit > 0) // debit>0 means we signed/sent this transaction
    {
669
        int64 nValueOut = GetValueOut(*this);
670
671
672
        nFee = nDebit - nValueOut;
    }

Gavin Andresen's avatar
Gavin Andresen committed
673
    // Sent/received.
674
675
    BOOST_FOREACH(const CTxOut& txout, vout)
    {
676
        CTxDestination address;
677
        vector<unsigned char> vchPubKey;
678
        if (!ExtractDestination(txout.scriptPubKey, address))
679
        {
680
681
            LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
                     this->GetHash().ToString().c_str());
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
        }

        // Don't report 'change' txouts
        if (nDebit > 0 && pwallet->IsChange(txout))
            continue;

        if (nDebit > 0)
            listSent.push_back(make_pair(address, txout.nValue));

        if (pwallet->IsMine(txout))
            listReceived.push_back(make_pair(address, txout.nValue));
    }

}

697
void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nReceived,
698
                                  int64& nSent, int64& nFee) const
699
{
700
    nReceived = nSent = nFee = 0;
701

702
    int64 allFee;
703
    string strSentAccount;
704
705
    list<pair<CTxDestination, int64> > listReceived;
    list<pair<CTxDestination, int64> > listSent;
706
    GetAmounts(listReceived, listSent, allFee, strSentAccount);
707
708
709

    if (strAccount == strSentAccount)
    {
710
        BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& s, listSent)
711
712
713
714
            nSent += s.second;
        nFee = allFee;
    }
    {
715
        LOCK(pwallet->cs_wallet);
716
        BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listReceived)
717
718
719
        {
            if (pwallet->mapAddressBook.count(r.first))
            {
720
721
                map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
                if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
722
723
724
725
726
727
728
729
730
731
                    nReceived += r.second;
            }
            else if (strAccount.empty())
            {
                nReceived += r.second;
            }
        }
    }
}

Pieter Wuille's avatar
Pieter Wuille committed
732
void CWalletTx::AddSupportingTransactions()
733
734
735
736
737
738
739
740
741
742
743
{
    vtxPrev.clear();

    const int COPY_DEPTH = 3;
    if (SetMerkleBranch() < COPY_DEPTH)
    {
        vector<uint256> vWorkQueue;
        BOOST_FOREACH(const CTxIn& txin, vin)
            vWorkQueue.push_back(txin.prevout.hash);

        {
744
            LOCK(pwallet->cs_wallet);
745
746
            map<uint256, const CMerkleTx*> mapWalletPrev;
            set<uint256> setAlreadyDone;
747
            for (unsigned int i = 0; i < vWorkQueue.size(); i++)
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
            {
                uint256 hash = vWorkQueue[i];
                if (setAlreadyDone.count(hash))
                    continue;
                setAlreadyDone.insert(hash);

                CMerkleTx tx;
                map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
                if (mi != pwallet->mapWallet.end())
                {
                    tx = (*mi).second;
                    BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
                        mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
                }
                else if (mapWalletPrev.count(hash))
                {
                    tx = *mapWalletPrev[hash];
                }

                int nDepth = tx.SetMerkleBranch();
                vtxPrev.push_back(tx);

                if (nDepth < COPY_DEPTH)
771
                {
772
773
                    BOOST_FOREACH(const CTxIn& txin, tx.vin)
                        vWorkQueue.push_back(txin.prevout.hash);
774
                }
775
776
777
778
779
780
781
782
783
784
785
786
            }
        }
    }

    reverse(vtxPrev.begin(), vtxPrev.end());
}

bool CWalletTx::WriteToDisk()
{
    return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
}

Pieter Wuille's avatar
Pieter Wuille committed
787
788
789
// Scan the block chain (starting in pindexStart) for transactions
// from or to us. If fUpdate is true, found transactions that already
// exist in the wallet will be updated.
790
791
792
793
794
795
int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
{
    int ret = 0;

    CBlockIndex* pindex = pindexStart;
    {
796
        LOCK(cs_wallet);
797
798
        while (pindex)
        {
799
800
801
            // no need to read and scan block, if block was created before
            // our wallet birthday (as adjusted for block time variability)
            if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
802
                pindex = chainActive.Next(pindex);
803
804
805
                continue;
            }

806
            CBlock block;
807
            ReadBlockFromDisk(block, pindex);
808
809
            BOOST_FOREACH(CTransaction& tx, block.vtx)
            {
Pieter Wuille's avatar
Pieter Wuille committed
810
                if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
811
812
                    ret++;
            }
813
            pindex = chainActive.Next(pindex);
814
815
816
817
818
819
820
821
        }
    }
    return ret;
}

void CWallet::ReacceptWalletTransactions()
{
    bool fRepeat = true;
822
    while (fRepeat)
823
    {
824
        LOCK(cs_wallet);
825
        fRepeat = false;
Pieter Wuille's avatar
Pieter Wuille committed
826
        bool fMissing = false;
827
828
829
830
831
832
        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
        {
            CWalletTx& wtx = item.second;
            if (wtx.IsCoinBase() && wtx.IsSpent(0))
                continue;

Pieter Wuille's avatar
Pieter Wuille committed
833
            CCoins coins;
834
            bool fUpdated = false;
835
836
            bool fFound = pcoinsTip->GetCoins(wtx.GetHash(), coins);
            if (fFound || wtx.GetDepthInMainChain() > 0)
837
838
            {
                // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
Pieter Wuille's avatar
Pieter Wuille committed
839
                for (unsigned int i = 0; i < wtx.vout.size(); i++)
840
841
842
                {
                    if (wtx.IsSpent(i))
                        continue;
Pieter Wuille's avatar
Pieter Wuille committed
843
                    if ((i >= coins.vout.size() || coins.vout[i].IsNull()) && IsMine(wtx.vout[i]))
844
845
846
                    {
                        wtx.MarkSpent(i);
                        fUpdated = true;
Pieter Wuille's avatar
Pieter Wuille committed
847
                        fMissing = true;
848
849
850
851
                    }
                }
                if (fUpdated)
                {
852
                    LogPrintf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
853
854
855
856
857
858
                    wtx.MarkDirty();
                    wtx.WriteToDisk();
                }
            }
            else
            {
859
                // Re-accept any txes of ours that aren't already in a block
860
                if (!wtx.IsCoinBase())
861
                    wtx.AcceptWalletTransaction();
862
863
            }
        }
Pieter Wuille's avatar
Pieter Wuille committed
864
        if (fMissing)
865
866
        {
            // TODO: optimize this to scan just part of the block chain?
867
            if (ScanForWalletTransactions(chainActive.Genesis()))
868
                fRepeat = true;  // Found missing transactions: re-do re-accept.
869
870
871
872
        }
    }
}

873
void CWalletTx::RelayWalletTransaction()
874
875
876
{
    BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
    {
877
        if (!tx.IsCoinBase())
878
            if (tx.GetDepthInMainChain() == 0)
879
                RelayTransaction((CTransaction)tx, tx.GetHash());
880
881
882
    }
    if (!IsCoinBase())
    {
883
884
        if (GetDepthInMainChain() == 0) {
            uint256 hash = GetHash();
885
            LogPrintf("Relaying wtx %s\n", hash.ToString().c_str());
886
            RelayTransaction((CTransaction)*this, hash);
887
888
889
890
891
892
893
894
        }
    }
}

void CWallet::ResendWalletTransactions()
{
    // Do this infrequently and randomly to avoid giving away
    // that these are our transactions.
895
    if (GetTime() < nNextResend)
896
        return;
897
898
    bool fFirst = (nNextResend == 0);
    nNextResend = GetTime() + GetRand(30 * 60);
899
900
901
902
    if (fFirst)
        return;

    // Only do it if there's been a new block since last time
903
    if (nTimeBestReceived < nLastResend)
904
        return;
905
    nLastResend = GetTime();
906
907

    // Rebroadcast any of our txes that aren't in a block yet
908
    LogPrintf("ResendWalletTransactions()\n");
909
    {
910
        LOCK(cs_wallet);
911
912
913
914
915
916
917
        // Sort them in chronological order
        multimap<unsigned int, CWalletTx*> mapSorted;
        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
        {
            CWalletTx& wtx = item.second;
            // Don't rebroadcast until it's had plenty of time that
            // it should have gotten in already by now.
918
            if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
919
920
921
922
923
                mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
        }
        BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
        {
            CWalletTx& wtx = *item.second;
924
            wtx.RelayWalletTransaction();
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
        }
    }
}






//////////////////////////////////////////////////////////////////////////////
//
// Actions
//


940
int64 CWallet::GetBalance() const
941
{
942
    int64 nTotal = 0;
943
    {
944
        LOCK(cs_wallet);
945
946
947
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
            const CWalletTx* pcoin = &(*it).second;
Gavin Andresen's avatar
Gavin Andresen committed
948
            if (pcoin->IsConfirmed())
949
                nTotal += pcoin->GetAvailableCredit();
950
951
952
953
954
955
        }
    }

    return nTotal;
}

956
int64 CWallet::GetUnconfirmedBalance() const
957
{
958
    int64 nTotal = 0;
959
    {
960
        LOCK(cs_wallet);
961
962
963
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
            const CWalletTx* pcoin = &(*it).second;
964
            if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
965
966
967
968
969
970
971
972
973
974
975
976
977
                nTotal += pcoin->GetAvailableCredit();
        }
    }
    return nTotal;
}

int64 CWallet::GetImmatureBalance() const
{
    int64 nTotal = 0;
    {
        LOCK(cs_wallet);
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
978
979
            const CWalletTx* pcoin = &(*it).second;
            nTotal += pcoin->GetImmatureCredit();
980
981
982
983
        }
    }
    return nTotal;
}
984

985
// populate vCoins with vector of spendable COutputs
986
void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
987
988
989
990
991
992
993
994
995
{
    vCoins.clear();

    {
        LOCK(cs_wallet);
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
            const CWalletTx* pcoin = &(*it).second;

996
            if (!IsFinalTx(*pcoin))
997
998
999
                continue;

            if (fOnlyConfirmed && !pcoin->IsConfirmed())
1000
1001
1002
1003
1004
                continue;

            if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
                continue;

1005
1006
1007
            for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
                if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) &&
                    !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0)
1008
                    vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
1009
            }
1010
1011
1012
1013
        }
    }
}

1014
1015
1016
1017
1018
1019
1020
1021
static void ApproximateBestSubset(vector<pair<int64, pair<const CWalletTx*,unsigned int> > >vValue, int64 nTotalLower, int64 nTargetValue,
                                  vector<char>& vfBest, int64& nBest, int iterations = 1000)
{
    vector<char> vfIncluded;

    vfBest.assign(vValue.size(), true);
    nBest = nTotalLower;

1022
1023
    seed_insecure_rand();

1024
1025
1026
1027
1028
1029
1030
1031
1032
    for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
    {
        vfIncluded.assign(vValue.size(), false);
        int64 nTotal = 0;
        bool fReachedTarget = false;
        for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
        {
            for (unsigned int i = 0; i < vValue.size(); i++)
            {
1033
1034
1035
1036
1037
1038
1039
                //The solver here uses a randomized algorithm,
                //the randomness serves no real security purpose but is just
                //needed to prevent degenerate behavior and it is important
                //that the rng fast. We do not use a constant random sequence,
                //because there may be some privacy improvement by making
                //the selection random.
                if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
                {
                    nTotal += vValue[i].first;
                    vfIncluded[i] = true;
                    if (nTotal >= nTargetValue)
                    {
                        fReachedTarget = true;
                        if (nTotal < nBest)
                        {
                            nBest = nTotal;
                            vfBest = vfIncluded;
                        }
                        nTotal -= vValue[i].first;
                        vfIncluded[i] = false;
                    }
                }
            }
        }
    }
}

1060
1061
bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
                                 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
1062
1063
1064
1065
1066
{
    setCoinsRet.clear();
    nValueRet = 0;

    // List of values less than target
1067
1068
    pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
    coinLowestLarger.first = std::numeric_limits<int64>::max();
1069
    coinLowestLarger.second.first = NULL;
1070
1071
    vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
    int64 nTotalLower = 0;
1072

1073
1074
    random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);

1075
    BOOST_FOREACH(COutput output, vCoins)
1076
    {
1077
        const CWalletTx *pcoin = output.tx;
1078

1079
1080
        if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
            continue;
1081

1082
1083
        int i = output.i;
        int64 n = pcoin->vout[i].nValue;
1084

1085
        pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
1086

1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
        if (n == nTargetValue)
        {
            setCoinsRet.insert(coin.second);
            nValueRet += coin.first;
            return true;
        }
        else if (n < nTargetValue + CENT)
        {
            vValue.push_back(coin);
            nTotalLower += n;
        }
        else if (n < coinLowestLarger.first)
        {
            coinLowestLarger = coin;
1101
1102
1103
        }
    }

1104
    if (nTotalLower == nTargetValue)
1105
    {
1106
        for (unsigned int i = 0; i < vValue.size(); ++i)
1107
1108
1109
1110
1111
1112
1113
        {
            setCoinsRet.insert(vValue[i].second);
            nValueRet += vValue[i].first;
        }
        return true;
    }

1114
    if (nTotalLower < nTargetValue)
1115
1116
1117
1118
1119
1120
1121
1122
1123
    {
        if (coinLowestLarger.second.first == NULL)
            return false;
        setCoinsRet.insert(coinLowestLarger.second);
        nValueRet += coinLowestLarger.first;
        return true;
    }

    // Solve subset sum by stochastic approximation
1124
    sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
1125
1126
    vector<char> vfBest;
    int64 nBest;
1127

1128
1129
1130
    ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
    if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
        ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
1131

1132
1133
1134
1135
    // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
    //                                   or the next bigger coin is closer), return the bigger coin
    if (coinLowestLarger.second.first &&
        ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
1136
1137
1138
1139
1140
    {
        setCoinsRet.insert(coinLowestLarger.second);
        nValueRet += coinLowestLarger.first;
    }
    else {
1141
        for (unsigned int i = 0; i < vValue.size(); i++)
1142
1143
1144
1145
1146
1147
            if (vfBest[i])
            {
                setCoinsRet.insert(vValue[i].second);
                nValueRet += vValue[i].first;
            }

1148
        LogPrint("selectcoins", "SelectCoins() best subset: ");
1149
        for (unsigned int i = 0; i < vValue.size(); i++)
1150
            if (vfBest[i])
1151
1152
                LogPrint("selectcoins", "%s ", FormatMoney(vValue[i].first).c_str());
        LogPrint("selectcoins", "total %s\n", FormatMoney(nBest).c_str());
1153
1154
1155
1156
1157
    }

    return true;
}

1158
bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
1159
{
1160
1161
1162
1163
1164
1165
    vector<COutput> vCoins;
    AvailableCoins(vCoins);

    return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
            SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
            SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet));
1166
1167
1168
1169
1170
}




1171
1172
bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
                                CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
1173
{
1174
1175
    int64 nValue = 0;
    BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1176
1177
    {
        if (nValue < 0)
1178
1179
        {
            strFailReason = _("Transaction amounts must be positive");
1180
            return false;
1181
        }
1182
1183
1184
        nValue += s.second;
    }
    if (vecSend.empty() || nValue < 0)
1185
1186
    {
        strFailReason = _("Transaction amounts must be positive");
1187
        return false;
1188
    }
1189

1190
    wtxNew.BindWallet(this);
1191
1192

    {
1193
        LOCK2(cs_main, cs_wallet);
1194
1195
        {
            nFeeRet = nTransactionFee;
1196
            while (true)
1197
1198
1199
1200
1201
            {
                wtxNew.vin.clear();
                wtxNew.vout.clear();
                wtxNew.fFromMe = true;

1202
                int64 nTotalValue = nValue + nFeeRet;
1203
1204
                double dPriority = 0;
                // vouts to the payees
1205
                BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1206
1207
                {
                    CTxOut txout(s.second, s.first);
1208
                    if (txout.IsDust(CTransaction::nMinRelayTxFee))
1209
1210
                    {
                        strFailReason = _("Transaction amount too small");
1211
                        return false;
1212
                    }
1213
1214
                    wtxNew.vout.push_back(txout);
                }
1215
1216
1217

                // Choose coins to use
                set<pair<const CWalletTx*,unsigned int> > setCoins;
1218
                int64 nValueIn = 0;
1219
                if (!SelectCoins(nTotalValue, setCoins, nValueIn))
1220
1221
                {
                    strFailReason = _("Insufficient funds");
1222
                    return false;
1223
                }
1224
1225
                BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
                {
1226
                    int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
1227
1228
1229
1230
                    //The priority after the next block (depth+1) is used instead of the current,
                    //reflecting an assumption the user would accept a bit more delay for
                    //a chance at a free transaction.
                    dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1);
1231
1232
                }

1233
                int64 nChange = nValueIn - nValue - nFeeRet;
Gavin Andresen's avatar
Gavin Andresen committed
1234
                // if sub-cent change is required, the fee must be raised to at least nMinTxFee
Pieter Wuille's avatar
Pieter Wuille committed
1235
                // or until nChange becomes zero
1236
                // NOTE: this depends on the exact behaviour of GetMinFee
Gavin Andresen's avatar
Gavin Andresen committed
1237
                if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
Pieter Wuille's avatar
Pieter Wuille committed
1238
                {
Gavin Andresen's avatar
Gavin Andresen committed
1239
                    int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
Pieter Wuille's avatar
Pieter Wuille committed
1240
1241
1242
1243
1244
                    nChange -= nMoveToFee;
                    nFeeRet += nMoveToFee;
                }

                if (nChange > 0)
1245
1246
1247
1248
1249
1250
1251
1252
1253
                {
                    // Note: We use a new key here to keep it from being obvious which side is the change.
                    //  The drawback is that by not reusing a previous key, the change may be lost if a
                    //  backup is restored, if the backup doesn't have the new private key for the change.
                    //  If we reused the old key, it would be possible to add code to look for and
                    //  rediscover unknown transactions that were written with keys of ours to recover
                    //  post-backup change.

                    // Reserve a new key pair from key pool
1254
1255
                    CPubKey vchPubKey;
                    assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked
1256

1257
1258
1259
                    // Fill a vout to ourself
                    // TODO: pass in scriptChange instead of reservekey so
                    // change transaction isn't always pay-to-bitcoin-address
1260
                    CScript scriptChange;
1261
                    scriptChange.SetDestination(vchPubKey.GetID());
1262

1263
1264
1265
1266
                    CTxOut newTxOut(nChange, scriptChange);

                    // Never create dust outputs; if we would, just
                    // add the dust to the fee.
1267
                    if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
                    {
                        nFeeRet += nChange;
                        reservekey.ReturnKey();
                    }
                    else
                    {
                        // Insert change txn at random position:
                        vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
                        wtxNew.vout.insert(position, newTxOut);
                    }
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
                }
                else
                    reservekey.ReturnKey();

                // Fill vin
                BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
                    wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));

                // Sign
                int nIn = 0;
                BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
                    if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1290
1291
                    {
                        strFailReason = _("Signing transaction failed");
1292
                        return false;
1293
                    }
1294
1295

                // Limit size
1296
                unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
1297
                if (nBytes >= MAX_STANDARD_TX_SIZE)
1298
1299
                {
                    strFailReason = _("Transaction too large");
1300
                    return false;
1301
                }
1302
1303
1304
                dPriority /= nBytes;

                // Check that enough fee is included
1305
                int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
1306
                bool fAllowFree = AllowFree(dPriority);
1307
                int64 nMinFee = GetMinFee(wtxNew, fAllowFree, GMF_SEND);
1308
1309
1310
1311
1312
1313
1314
                if (nFeeRet < max(nPayFee, nMinFee))
                {
                    nFeeRet = max(nPayFee, nMinFee);
                    continue;
                }

                // Fill vtxPrev by copying from previous transactions vtxPrev
Pieter Wuille's avatar
Pieter Wuille committed
1315
                wtxNew.AddSupportingTransactions();
1316
1317
1318
1319
1320
1321
1322
1323
1324
                wtxNew.fTimeReceivedIsTxTime = true;

                break;
            }
        }
    }
    return true;
}

1325
1326
bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue,
                                CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason)
1327
{
1328
    vector< pair<CScript, int64> > vecSend;
1329
    vecSend.push_back(make_pair(scriptPubKey, nValue));
1330
    return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason);
1331
1332
1333
1334
1335
1336
}

// Call after CreateTransaction unless you want to abort
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
    {
1337
        LOCK2(cs_main, cs_wallet);
1338
        LogPrintf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
        {
            // This is only to keep the database open to defeat the auto-flush for the
            // duration of this scope.  This is the only place where this optimization
            // maybe makes sense; please don't do it anywhere else.
            CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;

            // Take key pair from key pool so it won't be used again
            reservekey.KeepKey();

            // Add tx to wallet, because if it has change it's also ours,
            // otherwise just for transaction history.
            AddToWallet(wtxNew);

            // Mark old coins as spent
            set<CWalletTx*> setCoins;
            BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
            {
                CWalletTx &coin = mapWallet[txin.prevout.hash];
1357
                coin.BindWallet(this);
1358
1359
                coin.MarkSpent(txin.prevout.n);
                coin.WriteToDisk();
1360
                NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
1361
1362
1363
1364
1365
1366
1367
            }

            if (fFileBacked)
                delete pwalletdb;
        }

        // Track how many getdata requests our transaction gets
Gavin Andresen's avatar
Gavin Andresen committed
1368
        mapRequestCount[wtxNew.GetHash()] = 0;
1369
1370

        // Broadcast
1371
        if (!wtxNew.AcceptToMemoryPool(false))
1372
1373
        {
            // This must not fail. The transaction has already been signed and recorded.
1374
            LogPrintf("CommitTransaction() : Error: Transaction not valid");
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
            return false;
        }
        wtxNew.RelayWalletTransaction();
    }
    return true;
}




1385
string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1386
1387
{
    CReserveKey reservekey(this);
1388
    int64 nFeeRequired;
Gavin Andresen's avatar
Gavin Andresen committed
1389
1390

    if (IsLocked())
1391
    {
1392
        string strError = _("Error: Wallet locked, unable to create transaction!");
1393
        LogPrintf("SendMoney() : %s", strError.c_str());
Gavin Andresen's avatar
Gavin Andresen committed
1394
1395
        return strError;
    }
1396
1397
    string strError;
    if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
Gavin Andresen's avatar
Gavin Andresen committed
1398
1399
    {
        if (nValue + nFeeRequired > GetBalance())
1400
            strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired).c_str());
1401
        LogPrintf("SendMoney() : %s\n", strError.c_str());
Gavin Andresen's avatar
Gavin Andresen committed
1402
        return strError;
1403
1404
    }

1405
    if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired))
1406
1407
1408
        return "ABORTED";

    if (!CommitTransaction(wtxNew, reservekey))
1409
        return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
1410
1411
1412
1413
1414
1415

    return "";
}



1416
string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1417
1418
1419
1420
1421
1422
1423
{
    // Check amount
    if (nValue <= 0)
        return _("Invalid amount");
    if (nValue + nTransactionFee > GetBalance())
        return _("Insufficient funds");

1424
    // Parse Bitcoin address
1425
    CScript scriptPubKey;
1426
    scriptPubKey.SetDestination(address);
1427
1428
1429
1430
1431
1432
1433

    return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
}




1434
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1435
1436
{
    if (!fFileBacked)
1437
        return DB_LOAD_OK;
1438
    fFirstRunRet = false;
1439
    DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1440
    if (nLoadWalletRet == DB_NEED_REWRITE)
Pieter Wuille's avatar
Pieter Wuille committed
1441
    {
1442
1443
1444
1445
1446
1447
1448
        if (CDB::Rewrite(strWalletFile, "\x04pool"))
        {
            setKeyPool.clear();
            // Note: can't top-up keypool here, because wallet is locked.
            // User will be prompted to unlock wallet the next operation
            // the requires a new key.
        }
Pieter Wuille's avatar
Pieter Wuille committed
1449
1450
    }

Matt Corallo's avatar
Matt Corallo committed
1451
1452
    if (nLoadWalletRet != DB_LOAD_OK)
        return nLoadWalletRet;
1453
    fFirstRunRet = !vchDefaultKey.IsValid();
1454

1455
    return DB_LOAD_OK;
1456
1457
}

1458

1459
bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
1460
{
1461
1462
    std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
    mapAddressBook[address].name = strName;
1463
1464
1465
1466
1467
    if (!strPurpose.empty()) /* update purpose only if requested */
        mapAddressBook[address].purpose = strPurpose;
    NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address),
            mapAddressBook[address].purpose,
            (mi == mapAddressBook.end()) ?  CT_NEW : CT_UPDATED);
1468
1469
    if (!fFileBacked)
        return false;
1470
1471
    if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
        return false;
1472
    return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1473
1474
}

1475
bool CWallet::DelAddressBook(const CTxDestination& address)
1476
{
1477
    mapAddressBook.erase(address);
1478
    NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
1479
1480
    if (!fFileBacked)
        return false;
1481
    CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
1482
    return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1483
1484
}

1485
1486
1487
void CWallet::PrintWallet(const CBlock& block)
{
    {
1488
        LOCK(cs_wallet);
1489
1490
1491
        if (mapWallet.count(block.vtx[0].GetHash()))
        {
            CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1492
            LogPrintf("    mine:  %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1493
1494
        }
    }
1495
    LogPrintf("\n");
1496
1497
1498
1499
1500
}

bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
{
    {
1501
        LOCK(cs_wallet);
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
        map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
        if (mi != mapWallet.end())
        {
            wtx = (*mi).second;
            return true;
        }
    }
    return false;
}

1512
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
{
    if (fFileBacked)
    {
        if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
            return false;
    }
    vchDefaultKey = vchPubKey;
    return true;
}

1523
1524
1525
1526
1527
1528
1529
1530
bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
{
    if (!pwallet->fFileBacked)
        return false;
    strWalletFileOut = pwallet->strWalletFile;
    return true;
}

1531
1532
1533
1534
1535
1536
1537
//
// Mark old keypool keys as used,
// and generate all new keys
//
bool CWallet::NewKeyPool()
{
    {
1538
        LOCK(cs_wallet);
1539
        CWalletDB walletdb(strWalletFile);
1540
        BOOST_FOREACH(int64 nIndex, setKeyPool)
1541
1542
1543
1544
1545
1546
            walletdb.ErasePool(nIndex);
        setKeyPool.clear();

        if (IsLocked())
            return false;

1547
        int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
1548
1549
        for (int i = 0; i < nKeys; i++)
        {
1550
            int64 nIndex = i+1;
1551
1552
1553
            walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
            setKeyPool.insert(nIndex);
        }
1554
        LogPrintf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1555
1556
1557
1558
    }
    return true;
}

1559
bool CWallet::TopUpKeyPool(unsigned int kpSize)
1560
1561
{
    {
1562
1563
        LOCK(cs_wallet);

Matt Corallo's avatar
Matt Corallo committed
1564
1565
1566
        if (IsLocked())
            return false;

1567
1568
1569
        CWalletDB walletdb(strWalletFile);

        // Top up key pool
1570
1571
1572
1573
1574
1575
        unsigned int nTargetSize;
        if (kpSize > 0)
            nTargetSize = kpSize;
        else
            nTargetSize = max(GetArg("-keypool", 100), 0LL);

1576
        while (setKeyPool.size() < (nTargetSize + 1))
1577
        {
1578
            int64 nEnd = 1;
1579
1580
1581
            if (!setKeyPool.empty())
                nEnd = *(--setKeyPool.end()) + 1;
            if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
Matt Corallo's avatar
Matt Corallo committed
1582
                throw runtime_error("TopUpKeyPool() : writing generated key failed");
1583
            setKeyPool.insert(nEnd);
1584
            LogPrintf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
1585
        }
Matt Corallo's avatar
Matt Corallo committed
1586
1587
1588
1589
    }
    return true;
}

1590
void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
Matt Corallo's avatar
Matt Corallo committed
1591
1592
{
    nIndex = -1;
1593
    keypool.vchPubKey = CPubKey();
Matt Corallo's avatar
Matt Corallo committed
1594
    {
1595
1596
        LOCK(cs_wallet);

Matt Corallo's avatar
Matt Corallo committed
1597
1598
        if (!IsLocked())
            TopUpKeyPool();
1599
1600

        // Get the oldest key
Matt Corallo's avatar
Matt Corallo committed
1601
1602
1603
1604
1605
        if(setKeyPool.empty())
            return;

        CWalletDB walletdb(strWalletFile);

1606
1607
1608
1609
        nIndex = *(setKeyPool.begin());
        setKeyPool.erase(setKeyPool.begin());
        if (!walletdb.ReadPool(nIndex, keypool))
            throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1610
        if (!HaveKey(keypool.vchPubKey.GetID()))
1611
            throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1612
        assert(keypool.vchPubKey.IsValid());
1613
        LogPrintf("keypool reserve %"PRI64d"\n", nIndex);
1614
1615
1616
    }
}

1617
int64 CWallet::AddReserveKey(const CKeyPool& keypool)
1618
1619
{
    {
1620
        LOCK2(cs_main, cs_wallet);
1621
1622
        CWalletDB walletdb(strWalletFile);

1623
        int64 nIndex = 1 + *(--setKeyPool.end());
1624
1625
1626
1627
1628
1629
1630
1631
        if (!walletdb.WritePool(nIndex, keypool))
            throw runtime_error("AddReserveKey() : writing added key failed");
        setKeyPool.insert(nIndex);
        return nIndex;
    }
    return -1;
}

1632
void CWallet::KeepKey(int64 nIndex)
1633
1634
1635
1636
1637
{
    // Remove from key pool
    if (fFileBacked)
    {
        CWalletDB walletdb(strWalletFile);
Gavin Andresen's avatar
Gavin Andresen committed
1638
        walletdb.ErasePool(nIndex);
1639
    }
1640
    LogPrintf("keypool keep %"PRI64d"\n", nIndex);
1641
1642
}

1643
void CWallet::ReturnKey(int64 nIndex)
1644
1645
{
    // Return to key pool
1646
1647
    {
        LOCK(cs_wallet);
1648
        setKeyPool.insert(nIndex);
1649
    }
1650
    LogPrintf("keypool return %"PRI64d"\n", nIndex);
1651
1652
}

1653
bool CWallet::GetKeyFromPool(CPubKey& result)
1654
{
1655
    int64 nIndex = 0;
1656
    CKeyPool keypool;
1657
    {
1658
        LOCK(cs_wallet);
1659
1660
        ReserveKeyFromKeyPool(nIndex, keypool);
        if (nIndex == -1)
1661
        {
1662
1663
            if (IsLocked()) return false;
            result = GenerateNewKey();
1664
1665
            return true;
        }
1666
1667
        KeepKey(nIndex);
        result = keypool.vchPubKey;
1668
1669
    }
    return true;
1670
1671
}

1672
int64 CWallet::GetOldestKeyPoolTime()
1673
{
1674
    int64 nIndex = 0;
1675
1676
    CKeyPool keypool;
    ReserveKeyFromKeyPool(nIndex, keypool);
Matt Corallo's avatar
Matt Corallo committed
1677
1678
    if (nIndex == -1)
        return GetTime();
1679
1680
1681
1682
    ReturnKey(nIndex);
    return keypool.nTime;
}

1683
std::map<CTxDestination, int64> CWallet::GetAddressBalances()
1684
{
1685
    map<CTxDestination, int64> balances;
1686
1687
1688
1689
1690
1691
1692

    {
        LOCK(cs_wallet);
        BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
        {
            CWalletTx *pcoin = &walletEntry.second;

1693
            if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
1694
1695
1696
1697
1698
1699
1700
1701
1702
                continue;

            if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
                continue;

            int nDepth = pcoin->GetDepthInMainChain();
            if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
                continue;

1703
            for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1704
            {
1705
                CTxDestination addr;
1706
1707
                if (!IsMine(pcoin->vout[i]))
                    continue;
1708
1709
                if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
                    continue;
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722

                int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;

                if (!balances.count(addr))
                    balances[addr] = 0;
                balances[addr] += n;
            }
        }
    }

    return balances;
}

1723
set< set<CTxDestination> > CWallet::GetAddressGroupings()
1724
{
1725
1726
    set< set<CTxDestination> > groupings;
    set<CTxDestination> grouping;
1727
1728
1729
1730
1731

    BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
    {
        CWalletTx *pcoin = &walletEntry.second;

1732
        if (pcoin->vin.size() > 0)
1733
        {
1734
            bool any_mine = false;
1735
1736
            // group all input addresses with each other
            BOOST_FOREACH(CTxIn txin, pcoin->vin)
1737
1738
            {
                CTxDestination address;
1739
1740
                if(!IsMine(txin)) /* If this input isn't mine, ignore it */
                    continue;
1741
1742
1743
                if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
                    continue;
                grouping.insert(address);
1744
                any_mine = true;
1745
            }
1746
1747

            // group change with input addresses
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
            if (any_mine)
            {
               BOOST_FOREACH(CTxOut txout, pcoin->vout)
                   if (IsChange(txout))
                   {
                       CTxDestination txoutAddr;
                       if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
                           continue;
                       grouping.insert(txoutAddr);
                   }
            }
            if (grouping.size() > 0)
            {
                groupings.insert(grouping);
                grouping.clear();
            }
1764
1765
1766
        }

        // group lone addrs by themselves
1767
        for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1768
1769
            if (IsMine(pcoin->vout[i]))
            {
1770
1771
1772
1773
                CTxDestination address;
                if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
                    continue;
                grouping.insert(address);
1774
1775
1776
1777
1778
                groupings.insert(grouping);
                grouping.clear();
            }
    }

1779
1780
1781
    set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
    map< CTxDestination, set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
    BOOST_FOREACH(set<CTxDestination> grouping, groupings)
1782
1783
    {
        // make a set of all the groups hit by this new group
1784
1785
1786
        set< set<CTxDestination>* > hits;
        map< CTxDestination, set<CTxDestination>* >::iterator it;
        BOOST_FOREACH(CTxDestination address, grouping)
1787
1788
1789
1790
            if ((it = setmap.find(address)) != setmap.end())
                hits.insert((*it).second);

        // merge all hit groups into a new single group and delete old groups
1791
1792
        set<CTxDestination>* merged = new set<CTxDestination>(grouping);
        BOOST_FOREACH(set<CTxDestination>* hit, hits)
1793
1794
1795
1796
1797
1798
1799
1800
        {
            merged->insert(hit->begin(), hit->end());
            uniqueGroupings.erase(hit);
            delete hit;
        }
        uniqueGroupings.insert(merged);

        // update setmap
1801
        BOOST_FOREACH(CTxDestination element, *merged)
1802
1803
1804
            setmap[element] = merged;
    }

1805
1806
    set< set<CTxDestination> > ret;
    BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
1807
1808
1809
1810
1811
1812
1813
1814
    {
        ret.insert(*uniqueGrouping);
        delete uniqueGrouping;
    }

    return ret;
}

1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
{
    set<CTxDestination> result;
    BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
    {
        const CTxDestination& address = item.first;
        const string& strName = item.second.name;
        if (strName == strAccount)
            result.insert(address);
    }
    return result;
}

1828
bool CReserveKey::GetReservedKey(CPubKey& pubkey)
1829
1830
1831
1832
1833
{
    if (nIndex == -1)
    {
        CKeyPool keypool;
        pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1834
1835
        if (nIndex != -1)
            vchPubKey = keypool.vchPubKey;
1836
1837
        else {
            if (pwallet->vchDefaultKey.IsValid()) {
1838
                LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
1839
1840
1841
                vchPubKey = pwallet->vchDefaultKey;
            } else
                return false;
1842
        }
1843
    }
1844
    assert(vchPubKey.IsValid());
1845
1846
    pubkey = vchPubKey;
    return true;
1847
1848
1849
1850
1851
1852
1853
}

void CReserveKey::KeepKey()
{
    if (nIndex != -1)
        pwallet->KeepKey(nIndex);
    nIndex = -1;
1854
    vchPubKey = CPubKey();
1855
1856
1857
1858
1859
1860
1861
}

void CReserveKey::ReturnKey()
{
    if (nIndex != -1)
        pwallet->ReturnKey(nIndex);
    nIndex = -1;
1862
    vchPubKey = CPubKey();
1863
}
1864

Pieter Wuille's avatar
Pieter Wuille committed
1865
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
1866
1867
1868
1869
1870
{
    setAddress.clear();

    CWalletDB walletdb(strWalletFile);

1871
    LOCK2(cs_main, cs_wallet);
1872
    BOOST_FOREACH(const int64& id, setKeyPool)
1873
1874
1875
1876
    {
        CKeyPool keypool;
        if (!walletdb.ReadPool(id, keypool))
            throw runtime_error("GetAllReserveKeyHashes() : read failed");
1877
        assert(keypool.vchPubKey.IsValid());
1878
1879
        CKeyID keyID = keypool.vchPubKey.GetID();
        if (!HaveKey(keyID))
1880
            throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
1881
        setAddress.insert(keyID);
1882
1883
    }
}
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894

void CWallet::UpdatedTransaction(const uint256 &hashTx)
{
    {
        LOCK(cs_wallet);
        // Only notify UI if this transaction is in this wallet
        map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
        if (mi != mapWallet.end())
            NotifyTransactionChanged(this, hashTx, CT_UPDATED);
    }
}
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

void CWallet::LockCoin(COutPoint& output)
{
    setLockedCoins.insert(output);
}

void CWallet::UnlockCoin(COutPoint& output)
{
    setLockedCoins.erase(output);
}

void CWallet::UnlockAllCoins()
{
    setLockedCoins.clear();
}

bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
{
    COutPoint outpt(hash, n);

    return (setLockedCoins.count(outpt) > 0);
}

void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
{
    for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
         it != setLockedCoins.end(); it++) {
        COutPoint outpt = (*it);
        vOutpts.push_back(outpt);
    }
}

Pieter Wuille's avatar
Pieter Wuille committed
1927
1928
1929
1930
1931
1932
1933
1934
1935
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
    mapKeyBirth.clear();

    // get birth times for keys with metadata
    for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
        if (it->second.nCreateTime)
            mapKeyBirth[it->first] = it->second.nCreateTime;

    // map in which we'll infer heights of other keys
1936
    CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
Pieter Wuille's avatar
Pieter Wuille committed
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
    std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
    std::set<CKeyID> setKeys;
    GetKeys(setKeys);
    BOOST_FOREACH(const CKeyID &keyid, setKeys) {
        if (mapKeyBirth.count(keyid) == 0)
            mapKeyFirstBlock[keyid] = pindexMax;
    }
    setKeys.clear();

    // if there are no such keys, we're done
    if (mapKeyFirstBlock.empty())
        return;

    // find first block that affects those keys, if there are any left
    std::vector<CKeyID> vAffected;
    for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
        // iterate over all wallet transactions...
        const CWalletTx &wtx = (*it).second;
        std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
1956
        if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
Pieter Wuille's avatar
Pieter Wuille committed
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
            // ... which are already in a block
            int nHeight = blit->second->nHeight;
            BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
                // iterate over all their outputs
                ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
                BOOST_FOREACH(const CKeyID &keyid, vAffected) {
                    // ... and all their affected keys
                    std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
                    if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
                        rit->second = blit->second;
                }
                vAffected.clear();
            }
        }
    }

    // Extract block timestamps for those keys
    for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
        mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
}