wallet.cpp 68.8 KB
Newer Older
Matt Corallo's avatar
Matt Corallo committed
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
// Copyright (c) 2009-2014 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
#include "wallet.h"
7

8
#include "base58.h"
Cozz Lovan's avatar
Cozz Lovan committed
9
#include "coincontrol.h"
10
#include "net.h"
11
12
13

#include <inttypes.h>

14
#include <boost/algorithm/string/replace.hpp>
15
#include <openssl/rand.h>
16
17
18

using namespace std;

19
20
// Settings
int64_t nTransactionFee = 0;
21
22
23
24
25
26

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

27
28
struct CompareValueOnly
{
29
30
    bool operator()(const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t1,
                    const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t2) const
31
32
33
34
35
    {
        return t1.first < t2.first;
    }
};

36
CPubKey CWallet::GenerateNewKey()
37
{
38
    AssertLockHeld(cs_wallet); // mapKeyMetadata
39
    bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
40

41
    RandAddSeedPerfmon();
42
43
    CKey secret;
    secret.MakeNewKey(fCompressed);
44
45
46

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

49
    CPubKey pubkey = secret.GetPubKey();
50
51

    // Create new metadata
52
    int64_t nCreationTime = GetTime();
53
54
55
56
    mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
    if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
        nTimeFirstKey = nCreationTime;

57
    if (!AddKeyPubKey(secret, pubkey))
58
        throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
59
    return pubkey;
60
}
61

62
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
63
{
64
    AssertLockHeld(cs_wallet); // mapKeyMetadata
65
    if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
66
        return false;
67
68
    if (!fFileBacked)
        return true;
69
    if (!IsCrypted()) {
70
71
        return CWalletDB(strWalletFile).WriteKey(pubkey,
                                                 secret.GetPrivKey(),
72
                                                 mapKeyMetadata[pubkey.GetID()]);
73
    }
74
    return true;
Matt Corallo's avatar
Matt Corallo committed
75
76
}

77
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
78
                            const vector<unsigned char> &vchCryptedSecret)
Matt Corallo's avatar
Matt Corallo committed
79
80
81
82
83
{
    if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
        return false;
    if (!fFileBacked)
        return true;
84
    {
85
        LOCK(cs_wallet);
86
        if (pwalletdbEncryption)
87
88
            return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
                                                        vchCryptedSecret,
89
                                                        mapKeyMetadata[vchPubKey.GetID()]);
90
        else
91
92
            return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
                                                            vchCryptedSecret,
93
                                                            mapKeyMetadata[vchPubKey.GetID()]);
94
    }
95
    return false;
Matt Corallo's avatar
Matt Corallo committed
96
97
}

98
99
bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
{
100
    AssertLockHeld(cs_wallet); // mapKeyMetadata
101
102
103
104
105
106
107
    if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
        nTimeFirstKey = meta.nCreateTime;

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

108
109
110
111
112
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
    return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
}

113
bool CWallet::AddCScript(const CScript& redeemScript)
Gavin Andresen's avatar
Gavin Andresen committed
114
{
115
    if (!CCryptoKeyStore::AddCScript(redeemScript))
Gavin Andresen's avatar
Gavin Andresen committed
116
117
118
        return false;
    if (!fFileBacked)
        return true;
119
    return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
Gavin Andresen's avatar
Gavin Andresen committed
120
121
}

122
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
123
{
Gavin Andresen's avatar
Gavin Andresen committed
124
125
    CCrypter crypter;
    CKeyingMaterial vMasterKey;
Matt Corallo's avatar
Matt Corallo committed
126

127
128
    {
        LOCK(cs_wallet);
Matt Corallo's avatar
Matt Corallo committed
129
130
131
132
133
        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))
134
                continue; // try another master key
Matt Corallo's avatar
Matt Corallo committed
135
136
137
            if (CCryptoKeyStore::Unlock(vMasterKey))
                return true;
        }
138
    }
Matt Corallo's avatar
Matt Corallo committed
139
140
141
    return false;
}

142
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
143
{
Gavin Andresen's avatar
Gavin Andresen committed
144
    bool fWasLocked = IsLocked();
Matt Corallo's avatar
Matt Corallo committed
145

Gavin Andresen's avatar
Gavin Andresen committed
146
    {
147
        LOCK(cs_wallet);
Matt Corallo's avatar
Matt Corallo committed
148
149
150
151
152
153
154
155
        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
156
            if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
Matt Corallo's avatar
Matt Corallo committed
157
158
159
                return false;
            if (CCryptoKeyStore::Unlock(vMasterKey))
            {
160
                int64_t nStartTime = GetTimeMillis();
161
162
163
164
165
166
167
168
169
170
                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;

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

Matt Corallo's avatar
Matt Corallo committed
173
174
175
176
177
178
179
180
181
182
183
                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
184

Matt Corallo's avatar
Matt Corallo committed
185
186
187
    return false;
}

Pieter Wuille's avatar
Pieter Wuille committed
188
189
190
191
192
void CWallet::SetBestChain(const CBlockLocator& loc)
{
    CWalletDB walletdb(strWalletFile);
    walletdb.WriteBestBlock(loc);
}
193
194
195
196
197
198
199
200
201
202
203
204
205

// 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);
    )
};

206
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
Pieter Wuille's avatar
Pieter Wuille committed
207
{
208
    AssertLockHeld(cs_wallet); // nWalletVersion
Pieter Wuille's avatar
Pieter Wuille committed
209
210
211
    if (nWalletVersion >= nVersion)
        return true;

212
213
214
215
    // 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
216
217
    nWalletVersion = nVersion;

218
219
220
    if (nVersion > nWalletMaxVersion)
        nWalletMaxVersion = nVersion;

Pieter Wuille's avatar
Pieter Wuille committed
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
    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;
}

240
241
bool CWallet::SetMaxVersion(int nVersion)
{
242
    AssertLockHeld(cs_wallet); // nWalletVersion, nWalletMaxVersion
243
244
245
246
247
248
249
250
251
    // cannot downgrade below current version
    if (nWalletVersion > nVersion)
        return false;

    nWalletMaxVersion = nVersion;

    return true;
}

252
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
253
{
Gavin Andresen's avatar
Gavin Andresen committed
254
255
    if (IsCrypted())
        return false;
Matt Corallo's avatar
Matt Corallo committed
256

Gavin Andresen's avatar
Gavin Andresen committed
257
258
    CKeyingMaterial vMasterKey;
    RandAddSeedPerfmon();
Matt Corallo's avatar
Matt Corallo committed
259

Gavin Andresen's avatar
Gavin Andresen committed
260
261
    vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
    RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
Matt Corallo's avatar
Matt Corallo committed
262

Gavin Andresen's avatar
Gavin Andresen committed
263
    CMasterKey kMasterKey;
Matt Corallo's avatar
Matt Corallo committed
264

Gavin Andresen's avatar
Gavin Andresen committed
265
266
267
    RandAddSeedPerfmon();
    kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
    RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
Matt Corallo's avatar
Matt Corallo committed
268

Gavin Andresen's avatar
Gavin Andresen committed
269
    CCrypter crypter;
270
    int64_t nStartTime = GetTimeMillis();
Gavin Andresen's avatar
Gavin Andresen committed
271
272
    crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
    kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
273

Gavin Andresen's avatar
Gavin Andresen committed
274
275
276
    nStartTime = GetTimeMillis();
    crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
    kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
277

Gavin Andresen's avatar
Gavin Andresen committed
278
279
    if (kMasterKey.nDeriveIterations < 25000)
        kMasterKey.nDeriveIterations = 25000;
280

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

Gavin Andresen's avatar
Gavin Andresen committed
283
284
285
286
    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
287

Gavin Andresen's avatar
Gavin Andresen committed
288
    {
289
        LOCK(cs_wallet);
Matt Corallo's avatar
Matt Corallo committed
290
291
292
        mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
        if (fFileBacked)
        {
293
            pwalletdbEncryption = new CWalletDB(strWalletFile);
294
295
            if (!pwalletdbEncryption->TxnBegin())
                return false;
296
            pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
Matt Corallo's avatar
Matt Corallo committed
297
298
299
        }

        if (!EncryptKeys(vMasterKey))
300
301
302
303
304
305
        {
            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
306
        // Encryption was introduced in version 0.4.0
307
        SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
Pieter Wuille's avatar
Pieter Wuille committed
308

309
310
311
312
313
        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.

314
            delete pwalletdbEncryption;
315
316
            pwalletdbEncryption = NULL;
        }
Matt Corallo's avatar
Matt Corallo committed
317

318
319
320
        Lock();
        Unlock(strWalletPassphrase);
        NewKeyPool();
Matt Corallo's avatar
Matt Corallo committed
321
        Lock();
Gavin Andresen's avatar
Gavin Andresen committed
322

323
324
        // 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.
325
        CDB::Rewrite(strWalletFile);
326

327
    }
328
    NotifyStatusChanged(this);
Pieter Wuille's avatar
Pieter Wuille committed
329

Matt Corallo's avatar
Matt Corallo committed
330
    return true;
331
332
}

333
int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
334
{
335
    AssertLockHeld(cs_wallet); // nOrderPosNext
336
    int64_t nRet = nOrderPosNext++;
337
338
339
340
341
    if (pwalletdb) {
        pwalletdb->WriteOrderPosNext(nOrderPosNext);
    } else {
        CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
    }
342
343
344
    return nRet;
}

345
CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
346
{
347
    AssertLockHeld(cs_wallet); // mapWallet
348
349
350
351
352
353
354
355
356
357
358
359
    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)));
    }
360
    acentries.clear();
361
362
363
364
365
366
367
368
369
    walletdb.ListAccountCreditDebit(strAccount, acentries);
    BOOST_FOREACH(CAccountingEntry& entry, acentries)
    {
        txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
    }

    return txOrdered;
}

370
371
372
373
374
375
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.
    {
376
        LOCK(cs_wallet);
377
378
379
380
381
382
        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;
383
                if (txin.prevout.n >= wtx.vout.size())
384
                    LogPrintf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString());
385
                else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
386
                {
387
                    LogPrintf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()), wtx.GetHash().ToString());
388
389
                    wtx.MarkSpent(txin.prevout.n);
                    wtx.WriteToDisk();
390
                    NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
391
392
393
394
395
396
                }
            }
        }
    }
}

Pieter Wuille's avatar
Pieter Wuille committed
397
398
399
void CWallet::MarkDirty()
{
    {
400
        LOCK(cs_wallet);
Pieter Wuille's avatar
Pieter Wuille committed
401
402
403
404
405
        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
            item.second.MarkDirty();
    }
}

406
407
408
409
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
    uint256 hash = wtxIn.GetHash();
    {
410
        LOCK(cs_wallet);
411
412
413
        // 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;
414
        wtx.BindWallet(this);
415
416
        bool fInsertedNew = ret.second;
        if (fInsertedNew)
417
        {
418
            wtx.nTimeReceived = GetAdjustedTime();
419
            wtx.nOrderPos = IncOrderPosNext();
420
421
422
423
424
425
426
427
428
429

            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
430
                        int64_t latestTolerated = latestNow + 300;
431
432
                        std::list<CAccountingEntry> acentries;
                        TxItems txOrdered = OrderedTxItems(acentries);
433
434
435
436
437
438
                        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;
439
                            int64_t nSmartTime;
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
                            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
462
                    LogPrintf("AddToWallet() : found %s in block %s not in index\n",
463
464
                             wtxIn.GetHash().ToString(),
                             wtxIn.hashBlock.ToString());
465
            }
466
        }
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

        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
492
        LogPrintf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
493
494
495
496
497

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

499
500
501
        // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
        WalletUpdateSpent(wtx);

502
503
        // Notify UI of new or updated transaction
        NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
504
505
506
507
508
509
510
511
512
513

        // 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
        }

514
    }
515
516
517
    return true;
}

Pieter Wuille's avatar
Pieter Wuille committed
518
519
520
// 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.
521
bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
522
523
{
    {
524
        LOCK(cs_wallet);
Gavin Andresen's avatar
Gavin Andresen committed
525
526
527
528
529
530
531
532
533
534
535
536
        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);
537
538
539
540
    }
    return false;
}

541
542
543
544
545
void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock) {
    AddToWalletIfInvolvingMe(hash, tx, pblock, true);
}

void CWallet::EraseFromWallet(const uint256 &hash)
546
547
{
    if (!fFileBacked)
548
        return;
549
    {
550
        LOCK(cs_wallet);
551
552
553
        if (mapWallet.erase(hash))
            CWalletDB(strWalletFile).EraseTx(hash);
    }
554
    return;
555
556
557
558
559
560
}


bool CWallet::IsMine(const CTxIn &txin) const
{
    {
561
        LOCK(cs_wallet);
562
563
564
565
566
567
568
569
570
571
572
573
        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;
}

574
int64_t CWallet::GetDebit(const CTxIn &txin) const
575
576
{
    {
577
        LOCK(cs_wallet);
578
579
580
581
582
583
584
585
586
587
588
589
        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
590
591
bool CWallet::IsChange(const CTxOut& txout) const
{
592
    CTxDestination address;
593
594
595
596
597
598
599
600

    // 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).
601
    if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
602
603
604
605
606
    {
        LOCK(cs_wallet);
        if (!mapAddressBook.count(address))
            return true;
    }
Gavin Andresen's avatar
Gavin Andresen committed
607
608
609
    return false;
}

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

int CWalletTx::GetRequestCount() const
{
    // Returns -1 if it wasn't being tracked
    int nRequests = -1;
    {
621
        LOCK(pwallet->cs_wallet);
622
623
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
        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;
}

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

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

Gavin Andresen's avatar
Gavin Andresen committed
671
    // Sent/received.
672
673
    BOOST_FOREACH(const CTxOut& txout, vout)
    {
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
        bool fIsMine;
        // Only need to handle txouts if AT LEAST one of these is true:
        //   1) they debit from us (sent)
        //   2) the output is to us (received)
        if (nDebit > 0)
        {
            // Don't report 'change' txouts
            if (pwallet->IsChange(txout))
                continue;
            fIsMine = pwallet->IsMine(txout);
        }
        else if (!(fIsMine = pwallet->IsMine(txout)))
            continue;

        // In either case, we need to get the destination address
689
690
        CTxDestination address;
        if (!ExtractDestination(txout.scriptPubKey, address))
691
        {
692
            LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
693
                     this->GetHash().ToString());
694
            address = CNoDestination();
695
696
        }

697
        // If we are debited by the transaction, add the output as a "sent" entry
698
699
700
        if (nDebit > 0)
            listSent.push_back(make_pair(address, txout.nValue));

701
702
        // If we are receiving the output, add it as a "received" entry
        if (fIsMine)
703
704
705
706
707
            listReceived.push_back(make_pair(address, txout.nValue));
    }

}

708
709
void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived,
                                  int64_t& nSent, int64_t& nFee) const
710
{
711
    nReceived = nSent = nFee = 0;
712

713
    int64_t allFee;
714
    string strSentAccount;
715
716
    list<pair<CTxDestination, int64_t> > listReceived;
    list<pair<CTxDestination, int64_t> > listSent;
717
    GetAmounts(listReceived, listSent, allFee, strSentAccount);
718
719
720

    if (strAccount == strSentAccount)
    {
721
        BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& s, listSent)
722
723
724
725
            nSent += s.second;
        nFee = allFee;
    }
    {
726
        LOCK(pwallet->cs_wallet);
727
        BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived)
728
729
730
        {
            if (pwallet->mapAddressBook.count(r.first))
            {
731
732
                map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
                if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
733
734
735
736
737
738
739
740
741
742
                    nReceived += r.second;
            }
            else if (strAccount.empty())
            {
                nReceived += r.second;
            }
        }
    }
}

Pieter Wuille's avatar
Pieter Wuille committed
743
void CWalletTx::AddSupportingTransactions()
744
745
746
747
748
749
750
751
752
753
754
{
    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);

        {
755
            LOCK(pwallet->cs_wallet);
756
757
            map<uint256, const CMerkleTx*> mapWalletPrev;
            set<uint256> setAlreadyDone;
758
            for (unsigned int i = 0; i < vWorkQueue.size(); i++)
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
            {
                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];
                }
777
778
779
780
                else
                {
                    continue;
                }
781
782
783
784
785

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

                if (nDepth < COPY_DEPTH)
786
                {
787
788
                    BOOST_FOREACH(const CTxIn& txin, tx.vin)
                        vWorkQueue.push_back(txin.prevout.hash);
789
                }
790
791
792
793
794
795
796
            }
        }
    }

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

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
bool CWalletTx::AcceptWalletTransaction()
{
    {
        LOCK(mempool.cs);
        // Add previous supporting transactions first
        BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
        {
            if (!tx.IsCoinBase())
            {
                uint256 hash = tx.GetHash();
                if (!mempool.exists(hash) && pcoinsTip->HaveCoins(hash))
                    tx.AcceptToMemoryPool(false);
            }
        }
        return AcceptToMemoryPool(false);
    }
    return false;
}

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

Pieter Wuille's avatar
Pieter Wuille committed
821
822
823
// 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.
824
825
826
827
828
829
int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
{
    int ret = 0;

    CBlockIndex* pindex = pindexStart;
    {
830
        LOCK(cs_wallet);
831
832
        while (pindex)
        {
833
834
835
            // 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))) {
836
                pindex = chainActive.Next(pindex);
837
838
839
                continue;
            }

840
            CBlock block;
841
            ReadBlockFromDisk(block, pindex);
842
843
            BOOST_FOREACH(CTransaction& tx, block.vtx)
            {
Pieter Wuille's avatar
Pieter Wuille committed
844
                if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
845
846
                    ret++;
            }
847
            pindex = chainActive.Next(pindex);
848
849
850
851
852
853
854
855
        }
    }
    return ret;
}

void CWallet::ReacceptWalletTransactions()
{
    bool fRepeat = true;
856
    while (fRepeat)
857
    {
858
        LOCK(cs_wallet);
859
        fRepeat = false;
Pieter Wuille's avatar
Pieter Wuille committed
860
        bool fMissing = false;
861
862
863
864
865
866
        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
867
            CCoins coins;
868
            bool fUpdated = false;
869
870
            bool fFound = pcoinsTip->GetCoins(wtx.GetHash(), coins);
            if (fFound || wtx.GetDepthInMainChain() > 0)
871
872
            {
                // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
Pieter Wuille's avatar
Pieter Wuille committed
873
                for (unsigned int i = 0; i < wtx.vout.size(); i++)
874
875
876
                {
                    if (wtx.IsSpent(i))
                        continue;
Pieter Wuille's avatar
Pieter Wuille committed
877
                    if ((i >= coins.vout.size() || coins.vout[i].IsNull()) && IsMine(wtx.vout[i]))
878
879
880
                    {
                        wtx.MarkSpent(i);
                        fUpdated = true;
Pieter Wuille's avatar
Pieter Wuille committed
881
                        fMissing = true;
882
883
884
885
                    }
                }
                if (fUpdated)
                {
886
                    LogPrintf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()), wtx.GetHash().ToString());
887
888
889
890
891
892
                    wtx.MarkDirty();
                    wtx.WriteToDisk();
                }
            }
            else
            {
893
                // Re-accept any txes of ours that aren't already in a block
894
                if (!wtx.IsCoinBase())
895
                    wtx.AcceptWalletTransaction();
896
897
            }
        }
Pieter Wuille's avatar
Pieter Wuille committed
898
        if (fMissing)
899
900
        {
            // TODO: optimize this to scan just part of the block chain?
901
            if (ScanForWalletTransactions(chainActive.Genesis()))
902
                fRepeat = true;  // Found missing transactions: re-do re-accept.
903
904
905
906
        }
    }
}

907
void CWalletTx::RelayWalletTransaction()
908
909
910
{
    BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
    {
911
912
913
914
        // Important: versions of bitcoin before 0.8.6 had a bug that inserted
        // empty transactions into the vtxPrev, which will cause the node to be
        // banned when retransmitted, hence the check for !tx.vin.empty()
        if (!tx.IsCoinBase() && !tx.vin.empty())
915
            if (tx.GetDepthInMainChain() == 0)
916
                RelayTransaction((CTransaction)tx, tx.GetHash());
917
918
919
    }
    if (!IsCoinBase())
    {
920
921
        if (GetDepthInMainChain() == 0) {
            uint256 hash = GetHash();
922
            LogPrintf("Relaying wtx %s\n", hash.ToString());
923
            RelayTransaction((CTransaction)*this, hash);
924
925
926
927
928
929
930
931
        }
    }
}

void CWallet::ResendWalletTransactions()
{
    // Do this infrequently and randomly to avoid giving away
    // that these are our transactions.
932
    if (GetTime() < nNextResend)
933
        return;
934
935
    bool fFirst = (nNextResend == 0);
    nNextResend = GetTime() + GetRand(30 * 60);
936
937
938
939
    if (fFirst)
        return;

    // Only do it if there's been a new block since last time
940
    if (nTimeBestReceived < nLastResend)
941
        return;
942
    nLastResend = GetTime();
943
944

    // Rebroadcast any of our txes that aren't in a block yet
945
    LogPrintf("ResendWalletTransactions()\n");
946
    {
947
        LOCK(cs_wallet);
948
949
950
951
952
953
954
        // 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.
955
            if (nTimeBestReceived - (int64_t)wtx.nTimeReceived > 5 * 60)
956
957
958
959
960
                mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
        }
        BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
        {
            CWalletTx& wtx = *item.second;
961
            wtx.RelayWalletTransaction();
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
        }
    }
}






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


977
int64_t CWallet::GetBalance() const
978
{
979
    int64_t nTotal = 0;
980
    {
981
        LOCK(cs_wallet);
982
983
984
        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
985
            if (pcoin->IsConfirmed())
986
                nTotal += pcoin->GetAvailableCredit();
987
988
989
990
991
992
        }
    }

    return nTotal;
}

993
int64_t CWallet::GetUnconfirmedBalance() const
994
{
995
    int64_t nTotal = 0;
996
    {
997
        LOCK(cs_wallet);
998
999
1000
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
            const CWalletTx* pcoin = &(*it).second;
1001
            if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
1002
1003
1004
1005
1006
1007
                nTotal += pcoin->GetAvailableCredit();
        }
    }
    return nTotal;
}

1008
int64_t CWallet::GetImmatureBalance() const
1009
{
1010
    int64_t nTotal = 0;
1011
1012
1013
1014
    {
        LOCK(cs_wallet);
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
1015
1016
            const CWalletTx* pcoin = &(*it).second;
            nTotal += pcoin->GetImmatureCredit();
1017
1018
1019
1020
        }
    }
    return nTotal;
}
1021

1022
// populate vCoins with vector of spendable COutputs
Cozz Lovan's avatar
Cozz Lovan committed
1023
void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const
1024
1025
1026
1027
1028
1029
1030
1031
1032
{
    vCoins.clear();

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

1033
            if (!IsFinalTx(*pcoin))
1034
1035
1036
                continue;

            if (fOnlyConfirmed && !pcoin->IsConfirmed())
1037
1038
1039
1040
1041
                continue;

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

1042
1043
            for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
                if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) &&
Cozz Lovan's avatar
Cozz Lovan committed
1044
1045
1046
                    !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 &&
                    (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
                        vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
1047
            }
1048
1049
1050
1051
        }
    }
}

1052
1053
static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > >vValue, int64_t nTotalLower, int64_t nTargetValue,
                                  vector<char>& vfBest, int64_t& nBest, int iterations = 1000)
1054
1055
1056
1057
1058
1059
{
    vector<char> vfIncluded;

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

1060
1061
    seed_insecure_rand();

1062
1063
1064
    for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
    {
        vfIncluded.assign(vValue.size(), false);
1065
        int64_t nTotal = 0;
1066
1067
1068
1069
1070
        bool fReachedTarget = false;
        for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
        {
            for (unsigned int i = 0; i < vValue.size(); i++)
            {
1071
1072
1073
1074
1075
1076
1077
                //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])
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
                {
                    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;
                    }
                }
            }
        }
    }
}

1098
1099
bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
                                 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const
1100
1101
1102
1103
1104
{
    setCoinsRet.clear();
    nValueRet = 0;

    // List of values less than target
1105
1106
    pair<int64_t, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
    coinLowestLarger.first = std::numeric_limits<int64_t>::max();
1107
    coinLowestLarger.second.first = NULL;
1108
1109
    vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > > vValue;
    int64_t nTotalLower = 0;
1110

1111
1112
    random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);

1113
    BOOST_FOREACH(COutput output, vCoins)
1114
    {
1115
        const CWalletTx *pcoin = output.tx;
1116

1117
1118
        if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
            continue;
1119

1120
        int i = output.i;
1121
        int64_t n = pcoin->vout[i].nValue;
1122

1123
        pair<int64_t,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
1124

1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
        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;
1139
1140
1141
        }
    }

1142
    if (nTotalLower == nTargetValue)
1143
    {
1144
        for (unsigned int i = 0; i < vValue.size(); ++i)
1145
1146
1147
1148
1149
1150
1151
        {
            setCoinsRet.insert(vValue[i].second);
            nValueRet += vValue[i].first;
        }
        return true;
    }

1152
    if (nTotalLower < nTargetValue)
1153
1154
1155
1156
1157
1158
1159
1160
1161
    {
        if (coinLowestLarger.second.first == NULL)
            return false;
        setCoinsRet.insert(coinLowestLarger.second);
        nValueRet += coinLowestLarger.first;
        return true;
    }

    // Solve subset sum by stochastic approximation
1162
    sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
1163
    vector<char> vfBest;
1164
    int64_t nBest;
1165

1166
1167
1168
    ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
    if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
        ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
1169

1170
1171
1172
1173
    // 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))
1174
1175
1176
1177
1178
    {
        setCoinsRet.insert(coinLowestLarger.second);
        nValueRet += coinLowestLarger.first;
    }
    else {
1179
        for (unsigned int i = 0; i < vValue.size(); i++)
1180
1181
1182
1183
1184
1185
            if (vfBest[i])
            {
                setCoinsRet.insert(vValue[i].second);
                nValueRet += vValue[i].first;
            }

1186
        LogPrint("selectcoins", "SelectCoins() best subset: ");
1187
        for (unsigned int i = 0; i < vValue.size(); i++)
1188
            if (vfBest[i])
1189
1190
                LogPrint("selectcoins", "%s ", FormatMoney(vValue[i].first));
        LogPrint("selectcoins", "total %s\n", FormatMoney(nBest));
1191
1192
1193
1194
1195
    }

    return true;
}

Cozz Lovan's avatar
Cozz Lovan committed
1196
bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const
1197
{
1198
    vector<COutput> vCoins;
Cozz Lovan's avatar
Cozz Lovan committed
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
    AvailableCoins(vCoins, true, coinControl);

    // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
    if (coinControl && coinControl->HasSelected())
    {
        BOOST_FOREACH(const COutput& out, vCoins)
        {
            nValueRet += out.tx->vout[out.i].nValue;
            setCoinsRet.insert(make_pair(out.tx, out.i));
        }
        return (nValueRet >= nTargetValue);
    }
1211
1212
1213
1214

    return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
            SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
            SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet));
1215
1216
1217
1218
1219
}




1220
bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
Cozz Lovan's avatar
Cozz Lovan committed
1221
                                CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
1222
{
1223
1224
    int64_t nValue = 0;
    BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
1225
1226
    {
        if (nValue < 0)
1227
1228
        {
            strFailReason = _("Transaction amounts must be positive");
1229
            return false;
1230
        }
1231
1232
1233
        nValue += s.second;
    }
    if (vecSend.empty() || nValue < 0)
1234
1235
    {
        strFailReason = _("Transaction amounts must be positive");
1236
        return false;
1237
    }
1238

1239
    wtxNew.BindWallet(this);
1240
1241

    {
1242
        LOCK2(cs_main, cs_wallet);
1243
1244
        {
            nFeeRet = nTransactionFee;
1245
            while (true)
1246
1247
1248
1249
1250
            {
                wtxNew.vin.clear();
                wtxNew.vout.clear();
                wtxNew.fFromMe = true;

1251
                int64_t nTotalValue = nValue + nFeeRet;
1252
1253
                double dPriority = 0;
                // vouts to the payees
1254
                BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
1255
1256
                {
                    CTxOut txout(s.second, s.first);
1257
                    if (txout.IsDust(CTransaction::nMinRelayTxFee))
1258
1259
                    {
                        strFailReason = _("Transaction amount too small");
1260
                        return false;
1261
                    }
1262
1263
                    wtxNew.vout.push_back(txout);
                }
1264
1265
1266

                // Choose coins to use
                set<pair<const CWalletTx*,unsigned int> > setCoins;
1267
                int64_t nValueIn = 0;
Cozz Lovan's avatar
Cozz Lovan committed
1268
                if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl))
1269
1270
                {
                    strFailReason = _("Insufficient funds");
1271
                    return false;
1272
                }
1273
1274
                BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
                {
1275
                    int64_t nCredit = pcoin.first->vout[pcoin.second].nValue;
1276
1277
1278
1279
                    //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);
1280
1281
                }

1282
                int64_t nChange = nValueIn - nValue - nFeeRet;
1283
1284
1285
1286
                // The following if statement should be removed once enough miners
                // have upgraded to the 0.9 GetMinFee() rules. Until then, this avoids
                // creating free transactions that have change outputs less than
                // CENT bitcoins.
Gavin Andresen's avatar
Gavin Andresen committed
1287
                if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
Pieter Wuille's avatar
Pieter Wuille committed
1288
                {
1289
                    int64_t nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
Pieter Wuille's avatar
Pieter Wuille committed
1290
1291
1292
1293
1294
                    nChange -= nMoveToFee;
                    nFeeRet += nMoveToFee;
                }

                if (nChange > 0)
1295
                {
1296
1297
1298
                    // Fill a vout to ourself
                    // TODO: pass in scriptChange instead of reservekey so
                    // change transaction isn't always pay-to-bitcoin-address
1299
                    CScript scriptChange;
Cozz Lovan's avatar
Cozz Lovan committed
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316

                    // coin control: send change to custom address
                    if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
                        scriptChange.SetDestination(coinControl->destChange);

                    // no coin control: send change to newly generated address
                    else
                    {
                        // 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
                        CPubKey vchPubKey;
1317
1318
1319
                        bool ret;
                        ret = reservekey.GetReservedKey(vchPubKey);
                        assert(ret); // should never fail, as we just unlocked
Cozz Lovan's avatar
Cozz Lovan committed
1320
1321
1322

                        scriptChange.SetDestination(vchPubKey.GetID());
                    }
1323

1324
1325
1326
1327
                    CTxOut newTxOut(nChange, scriptChange);

                    // Never create dust outputs; if we would, just
                    // add the dust to the fee.
1328
                    if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
                    {
                        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);
                    }
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
                }
                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++))
1351
1352
                    {
                        strFailReason = _("Signing transaction failed");
1353
                        return false;
1354
                    }
1355
1356

                // Limit size
1357
                unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
1358
                if (nBytes >= MAX_STANDARD_TX_SIZE)
1359
1360
                {
                    strFailReason = _("Transaction too large");
1361
                    return false;
1362
                }
1363
                dPriority = wtxNew.ComputePriority(dPriority, nBytes);
1364
1365

                // Check that enough fee is included
1366
                int64_t nPayFee = nTransactionFee * (1 + (int64_t)nBytes / 1000);
1367
                bool fAllowFree = AllowFree(dPriority);
1368
                int64_t nMinFee = GetMinFee(wtxNew, nBytes, fAllowFree, GMF_SEND);
1369
1370
1371
1372
1373
1374
1375
                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
1376
                wtxNew.AddSupportingTransactions();
1377
1378
1379
1380
1381
1382
1383
1384
1385
                wtxNew.fTimeReceivedIsTxTime = true;

                break;
            }
        }
    }
    return true;
}

1386
bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue,
Cozz Lovan's avatar
Cozz Lovan committed
1387
                                CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
1388
{
1389
    vector< pair<CScript, int64_t> > vecSend;
1390
    vecSend.push_back(make_pair(scriptPubKey, nValue));
Cozz Lovan's avatar
Cozz Lovan committed
1391
    return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl);
1392
1393
1394
1395
1396
1397
}

// Call after CreateTransaction unless you want to abort
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
    {
1398
        LOCK2(cs_main, cs_wallet);
1399
        LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
        {
            // 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];
1418
                coin.BindWallet(this);
1419
1420
                coin.MarkSpent(txin.prevout.n);
                coin.WriteToDisk();
1421
                NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
1422
1423
1424
1425
1426
1427
1428
            }

            if (fFileBacked)
                delete pwalletdb;
        }

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

        // Broadcast
1432
        if (!wtxNew.AcceptToMemoryPool(false))
1433
1434
        {
            // This must not fail. The transaction has already been signed and recorded.
1435
            LogPrintf("CommitTransaction() : Error: Transaction not valid");
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
            return false;
        }
        wtxNew.RelayWalletTransaction();
    }
    return true;
}




1446
string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew)
1447
1448
{
    CReserveKey reservekey(this);
1449
    int64_t nFeeRequired;
Gavin Andresen's avatar
Gavin Andresen committed
1450
1451

    if (IsLocked())
1452
    {
1453
        string strError = _("Error: Wallet locked, unable to create transaction!");
1454
        LogPrintf("SendMoney() : %s", strError);
Gavin Andresen's avatar
Gavin Andresen committed
1455
1456
        return strError;
    }
1457
1458
    string strError;
    if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
Gavin Andresen's avatar
Gavin Andresen committed
1459
1460
    {
        if (nValue + nFeeRequired > GetBalance())
1461
1462
            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));
        LogPrintf("SendMoney() : %s\n", strError);
Gavin Andresen's avatar
Gavin Andresen committed
1463
        return strError;
1464
1465
1466
    }

    if (!CommitTransaction(wtxNew, reservekey))
1467
        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.");
1468
1469
1470
1471
1472
1473

    return "";
}



1474
string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew)
1475
1476
1477
1478
1479
1480
1481
{
    // Check amount
    if (nValue <= 0)
        return _("Invalid amount");
    if (nValue + nTransactionFee > GetBalance())
        return _("Insufficient funds");

1482
    // Parse Bitcoin address
1483
    CScript scriptPubKey;
1484
    scriptPubKey.SetDestination(address);
1485

1486
    return SendMoney(scriptPubKey, nValue, wtxNew);
1487
1488
1489
1490
1491
}




1492
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1493
1494
{
    if (!fFileBacked)
1495
        return DB_LOAD_OK;
1496
    fFirstRunRet = false;
1497
    DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1498
    if (nLoadWalletRet == DB_NEED_REWRITE)
Pieter Wuille's avatar
Pieter Wuille committed
1499
    {
1500
1501
        if (CDB::Rewrite(strWalletFile, "\x04pool"))
        {
1502
            LOCK(cs_wallet);
1503
1504
1505
1506
1507
            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
1508
1509
    }

Matt Corallo's avatar
Matt Corallo committed
1510
1511
    if (nLoadWalletRet != DB_LOAD_OK)
        return nLoadWalletRet;
1512
    fFirstRunRet = !vchDefaultKey.IsValid();
1513

1514
    return DB_LOAD_OK;
1515
1516
}

1517

1518
bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
1519
{
1520
    AssertLockHeld(cs_wallet); // mapAddressBook
1521
1522
    std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
    mapAddressBook[address].name = strName;
1523
1524
1525
1526
1527
    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);
1528
1529
    if (!fFileBacked)
        return false;
1530
1531
    if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
        return false;
1532
    return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1533
1534
}

1535
bool CWallet::DelAddressBook(const CTxDestination& address)
1536
{
1537

1538
    AssertLockHeld(cs_wallet); // mapAddressBook
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

    if(fFileBacked)
    {
        // Delete destdata tuples associated with address
        std::string strAddress = CBitcoinAddress(address).ToString();
        BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
        {
            CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
        }
    }

1550
    mapAddressBook.erase(address);
1551
    NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
1552
1553
    if (!fFileBacked)
        return false;
1554
    CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
1555
    return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1556
1557
}

1558
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
{
    if (fFileBacked)
    {
        if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
            return false;
    }
    vchDefaultKey = vchPubKey;
    return true;
}

1569
1570
1571
1572
1573
1574
1575
//
// Mark old keypool keys as used,
// and generate all new keys
//
bool CWallet::NewKeyPool()
{
    {
1576
        LOCK(cs_wallet);
1577
        CWalletDB walletdb(strWalletFile);
1578
        BOOST_FOREACH(int64_t nIndex, setKeyPool)
1579
1580
1581
1582
1583
1584
            walletdb.ErasePool(nIndex);
        setKeyPool.clear();

        if (IsLocked())
            return false;

1585
        int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
1586
1587
        for (int i = 0; i < nKeys; i++)
        {
1588
            int64_t nIndex = i+1;
1589
1590
1591
            walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
            setKeyPool.insert(nIndex);
        }
1592
        LogPrintf("CWallet::NewKeyPool wrote %"PRId64" new keys\n", nKeys);
1593
1594
1595
1596
    }
    return true;
}

1597
bool CWallet::TopUpKeyPool(unsigned int kpSize)
1598
1599
{
    {
1600
1601
        LOCK(cs_wallet);

Matt Corallo's avatar
Matt Corallo committed
1602
1603
1604
        if (IsLocked())
            return false;

1605
1606
1607
        CWalletDB walletdb(strWalletFile);

        // Top up key pool
1608
1609
1610
1611
        unsigned int nTargetSize;
        if (kpSize > 0)
            nTargetSize = kpSize;
        else
1612
            nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
1613

1614
        while (setKeyPool.size() < (nTargetSize + 1))
1615
        {
1616
            int64_t nEnd = 1;
1617
1618
1619
            if (!setKeyPool.empty())
                nEnd = *(--setKeyPool.end()) + 1;
            if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
Matt Corallo's avatar
Matt Corallo committed
1620
                throw runtime_error("TopUpKeyPool() : writing generated key failed");
1621
            setKeyPool.insert(nEnd);
1622
            LogPrintf("keypool added key %"PRId64", size=%"PRIszu"\n", nEnd, setKeyPool.size());
1623
        }
Matt Corallo's avatar
Matt Corallo committed
1624
1625
1626
1627
    }
    return true;
}

1628
void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
Matt Corallo's avatar
Matt Corallo committed
1629
1630
{
    nIndex = -1;
1631
    keypool.vchPubKey = CPubKey();
Matt Corallo's avatar
Matt Corallo committed
1632
    {
1633
1634
        LOCK(cs_wallet);

Matt Corallo's avatar
Matt Corallo committed
1635
1636
        if (!IsLocked())
            TopUpKeyPool();
1637
1638

        // Get the oldest key
Matt Corallo's avatar
Matt Corallo committed
1639
1640
1641
1642
1643
        if(setKeyPool.empty())
            return;

        CWalletDB walletdb(strWalletFile);

1644
1645
1646
1647
        nIndex = *(setKeyPool.begin());
        setKeyPool.erase(setKeyPool.begin());
        if (!walletdb.ReadPool(nIndex, keypool))
            throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1648
        if (!HaveKey(keypool.vchPubKey.GetID()))
1649
            throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1650
        assert(keypool.vchPubKey.IsValid());
1651
        LogPrintf("keypool reserve %"PRId64"\n", nIndex);
1652
1653
1654
    }
}

1655
int64_t CWallet::AddReserveKey(const CKeyPool& keypool)
1656
1657
{
    {
1658
        LOCK2(cs_main, cs_wallet);
1659
1660
        CWalletDB walletdb(strWalletFile);

1661
        int64_t nIndex = 1 + *(--setKeyPool.end());
1662
1663
1664
1665
1666
1667
1668
1669
        if (!walletdb.WritePool(nIndex, keypool))
            throw runtime_error("AddReserveKey() : writing added key failed");
        setKeyPool.insert(nIndex);
        return nIndex;
    }
    return -1;
}

1670
void CWallet::KeepKey(int64_t nIndex)
1671
1672
1673
1674
1675
{
    // Remove from key pool
    if (fFileBacked)
    {
        CWalletDB walletdb(strWalletFile);
Gavin Andresen's avatar
Gavin Andresen committed
1676
        walletdb.ErasePool(nIndex);
1677
    }
1678
    LogPrintf("keypool keep %"PRId64"\n", nIndex);
1679
1680
}

1681
void CWallet::ReturnKey(int64_t nIndex)
1682
1683
{
    // Return to key pool
1684
1685
    {
        LOCK(cs_wallet);
1686
        setKeyPool.insert(nIndex);
1687
    }
1688
    LogPrintf("keypool return %"PRId64"\n", nIndex);
1689
1690
}

1691
bool CWallet::GetKeyFromPool(CPubKey& result)
1692
{
1693
    int64_t nIndex = 0;
1694
    CKeyPool keypool;
1695
    {
1696
        LOCK(cs_wallet);
1697
1698
        ReserveKeyFromKeyPool(nIndex, keypool);
        if (nIndex == -1)
1699
        {
1700
1701
            if (IsLocked()) return false;
            result = GenerateNewKey();
1702
1703
            return true;
        }
1704
1705
        KeepKey(nIndex);
        result = keypool.vchPubKey;
1706
1707
    }
    return true;
1708
1709
}

1710
int64_t CWallet::GetOldestKeyPoolTime()
1711
{
1712
    int64_t nIndex = 0;
1713
1714
    CKeyPool keypool;
    ReserveKeyFromKeyPool(nIndex, keypool);
Matt Corallo's avatar
Matt Corallo committed
1715
1716
    if (nIndex == -1)
        return GetTime();
1717
1718
1719
1720
    ReturnKey(nIndex);
    return keypool.nTime;
}

1721
std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
1722
{
1723
    map<CTxDestination, int64_t> balances;
1724
1725
1726
1727
1728
1729
1730

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

1731
            if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
1732
1733
1734
1735
1736
1737
1738
1739
1740
                continue;

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

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

1741
            for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1742
            {
1743
                CTxDestination addr;
1744
1745
                if (!IsMine(pcoin->vout[i]))
                    continue;
1746
1747
                if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
                    continue;
1748

1749
                int64_t n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760

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

    return balances;
}

1761
set< set<CTxDestination> > CWallet::GetAddressGroupings()
1762
{
1763
    AssertLockHeld(cs_wallet); // mapWallet
1764
1765
    set< set<CTxDestination> > groupings;
    set<CTxDestination> grouping;
1766
1767
1768
1769
1770

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

1771
        if (pcoin->vin.size() > 0)
1772
        {
1773
            bool any_mine = false;
1774
1775
            // group all input addresses with each other
            BOOST_FOREACH(CTxIn txin, pcoin->vin)
1776
1777
            {
                CTxDestination address;
1778
1779
                if(!IsMine(txin)) /* If this input isn't mine, ignore it */
                    continue;
1780
1781
1782
                if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
                    continue;
                grouping.insert(address);
1783
                any_mine = true;
1784
            }
1785
1786

            // group change with input addresses
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
            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();
            }
1803
1804
1805
        }

        // group lone addrs by themselves
1806
        for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1807
1808
            if (IsMine(pcoin->vout[i]))
            {
1809
1810
1811
1812
                CTxDestination address;
                if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
                    continue;
                grouping.insert(address);
1813
1814
1815
1816
1817
                groupings.insert(grouping);
                grouping.clear();
            }
    }

1818
1819
1820
    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)
1821
1822
    {
        // make a set of all the groups hit by this new group
1823
1824
1825
        set< set<CTxDestination>* > hits;
        map< CTxDestination, set<CTxDestination>* >::iterator it;
        BOOST_FOREACH(CTxDestination address, grouping)
1826
1827
1828
1829
            if ((it = setmap.find(address)) != setmap.end())
                hits.insert((*it).second);

        // merge all hit groups into a new single group and delete old groups
1830
1831
        set<CTxDestination>* merged = new set<CTxDestination>(grouping);
        BOOST_FOREACH(set<CTxDestination>* hit, hits)
1832
1833
1834
1835
1836
1837
1838
1839
        {
            merged->insert(hit->begin(), hit->end());
            uniqueGroupings.erase(hit);
            delete hit;
        }
        uniqueGroupings.insert(merged);

        // update setmap
1840
        BOOST_FOREACH(CTxDestination element, *merged)
1841
1842
1843
            setmap[element] = merged;
    }

1844
1845
    set< set<CTxDestination> > ret;
    BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
1846
1847
1848
1849
1850
1851
1852
1853
    {
        ret.insert(*uniqueGrouping);
        delete uniqueGrouping;
    }

    return ret;
}

1854
1855
set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
{
1856
    AssertLockHeld(cs_wallet); // mapWallet
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
    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;
}

1868
bool CReserveKey::GetReservedKey(CPubKey& pubkey)
1869
1870
1871
1872
1873
{
    if (nIndex == -1)
    {
        CKeyPool keypool;
        pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1874
1875
        if (nIndex != -1)
            vchPubKey = keypool.vchPubKey;
1876
1877
        else {
            if (pwallet->vchDefaultKey.IsValid()) {
1878
                LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
1879
1880
1881
                vchPubKey = pwallet->vchDefaultKey;
            } else
                return false;
1882
        }
1883
    }
1884
    assert(vchPubKey.IsValid());
1885
1886
    pubkey = vchPubKey;
    return true;
1887
1888
1889
1890
1891
1892
1893
}

void CReserveKey::KeepKey()
{
    if (nIndex != -1)
        pwallet->KeepKey(nIndex);
    nIndex = -1;
1894
    vchPubKey = CPubKey();
1895
1896
1897
1898
1899
1900
1901
}

void CReserveKey::ReturnKey()
{
    if (nIndex != -1)
        pwallet->ReturnKey(nIndex);
    nIndex = -1;
1902
    vchPubKey = CPubKey();
1903
}
1904

Pieter Wuille's avatar
Pieter Wuille committed
1905
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
1906
1907
1908
1909
1910
{
    setAddress.clear();

    CWalletDB walletdb(strWalletFile);

1911
    LOCK2(cs_main, cs_wallet);
1912
    BOOST_FOREACH(const int64_t& id, setKeyPool)
1913
1914
1915
1916
    {
        CKeyPool keypool;
        if (!walletdb.ReadPool(id, keypool))
            throw runtime_error("GetAllReserveKeyHashes() : read failed");
1917
        assert(keypool.vchPubKey.IsValid());
1918
1919
        CKeyID keyID = keypool.vchPubKey.GetID();
        if (!HaveKey(keyID))
1920
            throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
1921
        setAddress.insert(keyID);
1922
1923
    }
}
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934

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);
    }
}
1935
1936
1937

void CWallet::LockCoin(COutPoint& output)
{
1938
    AssertLockHeld(cs_wallet); // setLockedCoins
1939
1940
1941
1942
1943
    setLockedCoins.insert(output);
}

void CWallet::UnlockCoin(COutPoint& output)
{
1944
    AssertLockHeld(cs_wallet); // setLockedCoins
1945
1946
1947
1948
1949
    setLockedCoins.erase(output);
}

void CWallet::UnlockAllCoins()
{
1950
    AssertLockHeld(cs_wallet); // setLockedCoins
1951
1952
1953
1954
1955
    setLockedCoins.clear();
}

bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
{
1956
    AssertLockHeld(cs_wallet); // setLockedCoins
1957
1958
1959
1960
1961
1962
1963
    COutPoint outpt(hash, n);

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

void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
{
1964
    AssertLockHeld(cs_wallet); // setLockedCoins
1965
1966
1967
1968
1969
1970
1971
    for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
         it != setLockedCoins.end(); it++) {
        COutPoint outpt = (*it);
        vOutpts.push_back(outpt);
    }
}

1972
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
1973
    AssertLockHeld(cs_wallet); // mapKeyMetadata
Pieter Wuille's avatar
Pieter Wuille committed
1974
1975
1976
1977
1978
1979
1980
1981
    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
1982
    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
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
    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);
2002
        if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
Pieter Wuille's avatar
Pieter Wuille committed
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
            // ... 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
}
2023
2024
2025

bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
{
2026
2027
2028
    if (boost::get<CNoDestination>(&dest))
        return false;

2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
    mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
    if (!fFileBacked)
        return true;
    return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
}

bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
{
    if (!mapAddressBook[dest].destdata.erase(key))
        return false;
    if (!fFileBacked)
        return true;
    return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key);
}

bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
{
    mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
    return true;
}

bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
{
    std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
    if(i != mapAddressBook.end())
    {
        CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
        if(j != i->second.destdata.end())
        {
            if(value)
                *value = j->second;
            return true;
        }
    }
    return false;
}