wallet.cpp 66.3 KB
Newer Older
Matt Corallo's avatar
Matt Corallo committed
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
super3's avatar
super3 committed
2
// Copyright (c) 2009-2013 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
19
20
21
22
23
24

using namespace std;


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

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

34
CPubKey CWallet::GenerateNewKey()
35
{
36
    bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
37

38
    RandAddSeedPerfmon();
39
40
    CKey secret;
    secret.MakeNewKey(fCompressed);
41
42
43

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

46
    CPubKey pubkey = secret.GetPubKey();
47
48

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

54
    if (!AddKeyPubKey(secret, pubkey))
55
        throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
56
    return pubkey;
57
}
58

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

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

94
95
96
97
98
99
100
101
102
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;
}

103
104
105
106
107
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
    return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
}

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

117
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
118
{
Gavin Andresen's avatar
Gavin Andresen committed
119
120
    CCrypter crypter;
    CKeyingMaterial vMasterKey;
Matt Corallo's avatar
Matt Corallo committed
121

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

137
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
138
{
Gavin Andresen's avatar
Gavin Andresen committed
139
    bool fWasLocked = IsLocked();
Matt Corallo's avatar
Matt Corallo committed
140

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

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

Matt Corallo's avatar
Matt Corallo committed
168
169
170
171
172
173
174
175
176
177
178
                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
179

Matt Corallo's avatar
Matt Corallo committed
180
181
182
    return false;
}

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

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

201
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
Pieter Wuille's avatar
Pieter Wuille committed
202
203
204
205
{
    if (nWalletVersion >= nVersion)
        return true;

206
207
208
209
    // 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
210
211
    nWalletVersion = nVersion;

212
213
214
    if (nVersion > nWalletMaxVersion)
        nWalletMaxVersion = nVersion;

Pieter Wuille's avatar
Pieter Wuille committed
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    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;
}

234
235
236
237
238
239
240
241
242
243
244
bool CWallet::SetMaxVersion(int nVersion)
{
    // cannot downgrade below current version
    if (nWalletVersion > nVersion)
        return false;

    nWalletMaxVersion = nVersion;

    return true;
}

245
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Matt Corallo's avatar
Matt Corallo committed
246
{
Gavin Andresen's avatar
Gavin Andresen committed
247
248
    if (IsCrypted())
        return false;
Matt Corallo's avatar
Matt Corallo committed
249

Gavin Andresen's avatar
Gavin Andresen committed
250
251
    CKeyingMaterial vMasterKey;
    RandAddSeedPerfmon();
Matt Corallo's avatar
Matt Corallo committed
252

Gavin Andresen's avatar
Gavin Andresen committed
253
254
    vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
    RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
Matt Corallo's avatar
Matt Corallo committed
255

Gavin Andresen's avatar
Gavin Andresen committed
256
    CMasterKey kMasterKey;
Matt Corallo's avatar
Matt Corallo committed
257

Gavin Andresen's avatar
Gavin Andresen committed
258
259
260
    RandAddSeedPerfmon();
    kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
    RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
Matt Corallo's avatar
Matt Corallo committed
261

Gavin Andresen's avatar
Gavin Andresen committed
262
    CCrypter crypter;
263
    int64_t nStartTime = GetTimeMillis();
Gavin Andresen's avatar
Gavin Andresen committed
264
265
    crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
    kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
266

Gavin Andresen's avatar
Gavin Andresen committed
267
268
269
    nStartTime = GetTimeMillis();
    crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
    kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
270

Gavin Andresen's avatar
Gavin Andresen committed
271
272
    if (kMasterKey.nDeriveIterations < 25000)
        kMasterKey.nDeriveIterations = 25000;
273

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

Gavin Andresen's avatar
Gavin Andresen committed
276
277
278
279
    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
280

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

        if (!EncryptKeys(vMasterKey))
293
294
295
296
297
298
        {
            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
299
        // Encryption was introduced in version 0.4.0
300
        SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
Pieter Wuille's avatar
Pieter Wuille committed
301

302
303
304
305
306
        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.

307
            delete pwalletdbEncryption;
308
309
            pwalletdbEncryption = NULL;
        }
Matt Corallo's avatar
Matt Corallo committed
310

311
312
313
        Lock();
        Unlock(strWalletPassphrase);
        NewKeyPool();
Matt Corallo's avatar
Matt Corallo committed
314
        Lock();
Gavin Andresen's avatar
Gavin Andresen committed
315

316
317
        // 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.
318
        CDB::Rewrite(strWalletFile);
319

320
    }
321
    NotifyStatusChanged(this);
Pieter Wuille's avatar
Pieter Wuille committed
322

Matt Corallo's avatar
Matt Corallo committed
323
    return true;
324
325
}

326
int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
327
{
328
    int64_t nRet = nOrderPosNext++;
329
330
331
332
333
    if (pwalletdb) {
        pwalletdb->WriteOrderPosNext(nOrderPosNext);
    } else {
        CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
    }
334
335
336
    return nRet;
}

337
CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
338
339
340
341
342
343
344
345
346
347
348
349
350
{
    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)));
    }
351
    acentries.clear();
352
353
354
355
356
357
358
359
360
    walletdb.ListAccountCreditDebit(strAccount, acentries);
    BOOST_FOREACH(CAccountingEntry& entry, acentries)
    {
        txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
    }

    return txOrdered;
}

361
362
363
364
365
366
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.
    {
367
        LOCK(cs_wallet);
368
369
370
371
372
373
        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;
374
                if (txin.prevout.n >= wtx.vout.size())
375
                    LogPrintf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
376
                else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
377
                {
378
                    LogPrintf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
379
380
                    wtx.MarkSpent(txin.prevout.n);
                    wtx.WriteToDisk();
381
                    NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
382
383
384
385
386
387
                }
            }
        }
    }
}

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

397
398
399
400
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
    uint256 hash = wtxIn.GetHash();
    {
401
        LOCK(cs_wallet);
402
403
404
        // 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;
405
        wtx.BindWallet(this);
406
407
        bool fInsertedNew = ret.second;
        if (fInsertedNew)
408
        {
409
            wtx.nTimeReceived = GetAdjustedTime();
410
            wtx.nOrderPos = IncOrderPosNext();
411
412
413
414
415
416
417
418
419
420

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

        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
483
        LogPrintf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
484
485
486
487
488

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

490
491
492
        // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
        WalletUpdateSpent(wtx);

493
494
        // Notify UI of new or updated transaction
        NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
495
496
497
498
499
500
501
502
503
504

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

505
    }
506
507
508
    return true;
}

Pieter Wuille's avatar
Pieter Wuille committed
509
510
511
// 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.
512
bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
513
514
{
    {
515
        LOCK(cs_wallet);
Gavin Andresen's avatar
Gavin Andresen committed
516
517
518
519
520
521
522
523
524
525
526
527
        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);
528
529
530
531
    }
    return false;
}

532
533
534
535
536
void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock) {
    AddToWalletIfInvolvingMe(hash, tx, pblock, true);
}

void CWallet::EraseFromWallet(const uint256 &hash)
537
538
{
    if (!fFileBacked)
539
        return;
540
    {
541
        LOCK(cs_wallet);
542
543
544
        if (mapWallet.erase(hash))
            CWalletDB(strWalletFile).EraseTx(hash);
    }
545
    return;
546
547
548
549
550
551
}


bool CWallet::IsMine(const CTxIn &txin) const
{
    {
552
        LOCK(cs_wallet);
553
554
555
556
557
558
559
560
561
562
563
564
        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;
}

565
int64_t CWallet::GetDebit(const CTxIn &txin) const
566
567
{
    {
568
        LOCK(cs_wallet);
569
570
571
572
573
574
575
576
577
578
579
580
        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
581
582
bool CWallet::IsChange(const CTxOut& txout) const
{
583
    CTxDestination address;
584
585
586
587
588
589
590
591

    // 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).
592
    if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
593
594
595
596
597
    {
        LOCK(cs_wallet);
        if (!mapAddressBook.count(address))
            return true;
    }
Gavin Andresen's avatar
Gavin Andresen committed
598
599
600
    return false;
}

601
int64_t CWalletTx::GetTxTime() const
602
{
603
    int64_t n = nTimeSmart;
604
    return n ? n : nTimeReceived;
605
606
607
608
609
610
611
}

int CWalletTx::GetRequestCount() const
{
    // Returns -1 if it wasn't being tracked
    int nRequests = -1;
    {
612
        LOCK(pwallet->cs_wallet);
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
        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;
}

646
647
void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
                           list<pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, string& strSentAccount) const
648
{
649
    nFee = 0;
650
651
652
653
654
    listReceived.clear();
    listSent.clear();
    strSentAccount = strFromAccount;

    // Compute fee:
655
    int64_t nDebit = GetDebit();
656
657
    if (nDebit > 0) // debit>0 means we signed/sent this transaction
    {
658
        int64_t nValueOut = GetValueOut();
659
660
661
        nFee = nDebit - nValueOut;
    }

Gavin Andresen's avatar
Gavin Andresen committed
662
    // Sent/received.
663
664
    BOOST_FOREACH(const CTxOut& txout, vout)
    {
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
        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
680
681
        CTxDestination address;
        if (!ExtractDestination(txout.scriptPubKey, address))
682
        {
683
684
            LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
                     this->GetHash().ToString().c_str());
685
            address = CNoDestination();
686
687
        }

688
        // If we are debited by the transaction, add the output as a "sent" entry
689
690
691
        if (nDebit > 0)
            listSent.push_back(make_pair(address, txout.nValue));

692
693
        // If we are receiving the output, add it as a "received" entry
        if (fIsMine)
694
695
696
697
698
            listReceived.push_back(make_pair(address, txout.nValue));
    }

}

699
700
void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived,
                                  int64_t& nSent, int64_t& nFee) const
701
{
702
    nReceived = nSent = nFee = 0;
703

704
    int64_t allFee;
705
    string strSentAccount;
706
707
    list<pair<CTxDestination, int64_t> > listReceived;
    list<pair<CTxDestination, int64_t> > listSent;
708
    GetAmounts(listReceived, listSent, allFee, strSentAccount);
709
710
711

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

Pieter Wuille's avatar
Pieter Wuille committed
734
void CWalletTx::AddSupportingTransactions()
735
736
737
738
739
740
741
742
743
744
745
{
    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);

        {
746
            LOCK(pwallet->cs_wallet);
747
748
            map<uint256, const CMerkleTx*> mapWalletPrev;
            set<uint256> setAlreadyDone;
749
            for (unsigned int i = 0; i < vWorkQueue.size(); i++)
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
            {
                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];
                }
768
769
770
771
                else
                {
                    continue;
                }
772
773
774
775
776

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

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

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

788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
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;
}

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

Pieter Wuille's avatar
Pieter Wuille committed
812
813
814
// 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.
815
816
817
818
819
820
int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
{
    int ret = 0;

    CBlockIndex* pindex = pindexStart;
    {
821
        LOCK(cs_wallet);
822
823
        while (pindex)
        {
824
825
826
            // 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))) {
827
                pindex = chainActive.Next(pindex);
828
829
830
                continue;
            }

831
            CBlock block;
832
            ReadBlockFromDisk(block, pindex);
833
834
            BOOST_FOREACH(CTransaction& tx, block.vtx)
            {
Pieter Wuille's avatar
Pieter Wuille committed
835
                if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
836
837
                    ret++;
            }
838
            pindex = chainActive.Next(pindex);
839
840
841
842
843
844
845
846
        }
    }
    return ret;
}

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

898
void CWalletTx::RelayWalletTransaction()
899
900
901
{
    BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
    {
902
903
904
905
        // 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())
906
            if (tx.GetDepthInMainChain() == 0)
907
                RelayTransaction((CTransaction)tx, tx.GetHash());
908
909
910
    }
    if (!IsCoinBase())
    {
911
912
        if (GetDepthInMainChain() == 0) {
            uint256 hash = GetHash();
913
            LogPrintf("Relaying wtx %s\n", hash.ToString().c_str());
914
            RelayTransaction((CTransaction)*this, hash);
915
916
917
918
919
920
921
922
        }
    }
}

void CWallet::ResendWalletTransactions()
{
    // Do this infrequently and randomly to avoid giving away
    // that these are our transactions.
923
    if (GetTime() < nNextResend)
924
        return;
925
926
    bool fFirst = (nNextResend == 0);
    nNextResend = GetTime() + GetRand(30 * 60);
927
928
929
930
    if (fFirst)
        return;

    // Only do it if there's been a new block since last time
931
    if (nTimeBestReceived < nLastResend)
932
        return;
933
    nLastResend = GetTime();
934
935

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






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


968
int64_t CWallet::GetBalance() const
969
{
970
    int64_t nTotal = 0;
971
    {
972
        LOCK(cs_wallet);
973
974
975
        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
976
            if (pcoin->IsConfirmed())
977
                nTotal += pcoin->GetAvailableCredit();
978
979
980
981
982
983
        }
    }

    return nTotal;
}

984
int64_t CWallet::GetUnconfirmedBalance() const
985
{
986
    int64_t nTotal = 0;
987
    {
988
        LOCK(cs_wallet);
989
990
991
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
            const CWalletTx* pcoin = &(*it).second;
992
            if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
993
994
995
996
997
998
                nTotal += pcoin->GetAvailableCredit();
        }
    }
    return nTotal;
}

999
int64_t CWallet::GetImmatureBalance() const
1000
{
1001
    int64_t nTotal = 0;
1002
1003
1004
1005
    {
        LOCK(cs_wallet);
        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
        {
1006
1007
            const CWalletTx* pcoin = &(*it).second;
            nTotal += pcoin->GetImmatureCredit();
1008
1009
1010
1011
        }
    }
    return nTotal;
}
1012

1013
// populate vCoins with vector of spendable COutputs
Cozz Lovan's avatar
Cozz Lovan committed
1014
void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const
1015
1016
1017
1018
1019
1020
1021
1022
1023
{
    vCoins.clear();

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

1024
            if (!IsFinalTx(*pcoin))
1025
1026
1027
                continue;

            if (fOnlyConfirmed && !pcoin->IsConfirmed())
1028
1029
1030
1031
1032
                continue;

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

1033
1034
            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
1035
1036
1037
                    !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()));
1038
            }
1039
1040
1041
1042
        }
    }
}

1043
1044
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)
1045
1046
1047
1048
1049
1050
{
    vector<char> vfIncluded;

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

1051
1052
    seed_insecure_rand();

1053
1054
1055
    for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
    {
        vfIncluded.assign(vValue.size(), false);
1056
        int64_t nTotal = 0;
1057
1058
1059
1060
1061
        bool fReachedTarget = false;
        for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
        {
            for (unsigned int i = 0; i < vValue.size(); i++)
            {
1062
1063
1064
1065
1066
1067
1068
                //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])
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
                {
                    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;
                    }
                }
            }
        }
    }
}

1089
1090
bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
                                 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const
1091
1092
1093
1094
1095
{
    setCoinsRet.clear();
    nValueRet = 0;

    // List of values less than target
1096
1097
    pair<int64_t, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
    coinLowestLarger.first = std::numeric_limits<int64_t>::max();
1098
    coinLowestLarger.second.first = NULL;
1099
1100
    vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > > vValue;
    int64_t nTotalLower = 0;
1101

1102
1103
    random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);

1104
    BOOST_FOREACH(COutput output, vCoins)
1105
    {
1106
        const CWalletTx *pcoin = output.tx;
1107

1108
1109
        if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
            continue;
1110

1111
        int i = output.i;
1112
        int64_t n = pcoin->vout[i].nValue;
1113

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

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
        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;
1130
1131
1132
        }
    }

1133
    if (nTotalLower == nTargetValue)
1134
    {
1135
        for (unsigned int i = 0; i < vValue.size(); ++i)
1136
1137
1138
1139
1140
1141
1142
        {
            setCoinsRet.insert(vValue[i].second);
            nValueRet += vValue[i].first;
        }
        return true;
    }

1143
    if (nTotalLower < nTargetValue)
1144
1145
1146
1147
1148
1149
1150
1151
1152
    {
        if (coinLowestLarger.second.first == NULL)
            return false;
        setCoinsRet.insert(coinLowestLarger.second);
        nValueRet += coinLowestLarger.first;
        return true;
    }

    // Solve subset sum by stochastic approximation
1153
    sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
1154
    vector<char> vfBest;
1155
    int64_t nBest;
1156

1157
1158
1159
    ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
    if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
        ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
1160

1161
1162
1163
1164
    // 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))
1165
1166
1167
1168
1169
    {
        setCoinsRet.insert(coinLowestLarger.second);
        nValueRet += coinLowestLarger.first;
    }
    else {
1170
        for (unsigned int i = 0; i < vValue.size(); i++)
1171
1172
1173
1174
1175
1176
            if (vfBest[i])
            {
                setCoinsRet.insert(vValue[i].second);
                nValueRet += vValue[i].first;
            }

1177
        LogPrint("selectcoins", "SelectCoins() best subset: ");
1178
        for (unsigned int i = 0; i < vValue.size(); i++)
1179
            if (vfBest[i])
1180
1181
                LogPrint("selectcoins", "%s ", FormatMoney(vValue[i].first).c_str());
        LogPrint("selectcoins", "total %s\n", FormatMoney(nBest).c_str());
1182
1183
1184
1185
1186
    }

    return true;
}

Cozz Lovan's avatar
Cozz Lovan committed
1187
bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const
1188
{
1189
    vector<COutput> vCoins;
Cozz Lovan's avatar
Cozz Lovan committed
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
    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);
    }
1202
1203
1204
1205

    return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
            SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
            SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet));
1206
1207
1208
1209
1210
}




1211
bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
Cozz Lovan's avatar
Cozz Lovan committed
1212
                                CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
1213
{
1214
1215
    int64_t nValue = 0;
    BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
1216
1217
    {
        if (nValue < 0)
1218
1219
        {
            strFailReason = _("Transaction amounts must be positive");
1220
            return false;
1221
        }
1222
1223
1224
        nValue += s.second;
    }
    if (vecSend.empty() || nValue < 0)
1225
1226
    {
        strFailReason = _("Transaction amounts must be positive");
1227
        return false;
1228
    }
1229

1230
    wtxNew.BindWallet(this);
1231
1232

    {
1233
        LOCK2(cs_main, cs_wallet);
1234
1235
        {
            nFeeRet = nTransactionFee;
1236
            while (true)
1237
1238
1239
1240
1241
            {
                wtxNew.vin.clear();
                wtxNew.vout.clear();
                wtxNew.fFromMe = true;

1242
                int64_t nTotalValue = nValue + nFeeRet;
1243
1244
                double dPriority = 0;
                // vouts to the payees
1245
                BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
1246
1247
                {
                    CTxOut txout(s.second, s.first);
1248
                    if (txout.IsDust(CTransaction::nMinRelayTxFee))
1249
1250
                    {
                        strFailReason = _("Transaction amount too small");
1251
                        return false;
1252
                    }
1253
1254
                    wtxNew.vout.push_back(txout);
                }
1255
1256
1257

                // Choose coins to use
                set<pair<const CWalletTx*,unsigned int> > setCoins;
1258
                int64_t nValueIn = 0;
Cozz Lovan's avatar
Cozz Lovan committed
1259
                if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl))
1260
1261
                {
                    strFailReason = _("Insufficient funds");
1262
                    return false;
1263
                }
1264
1265
                BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
                {
1266
                    int64_t nCredit = pcoin.first->vout[pcoin.second].nValue;
1267
1268
1269
1270
                    //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);
1271
1272
                }

1273
                int64_t nChange = nValueIn - nValue - nFeeRet;
1274
1275
1276
1277
                // 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
1278
                if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
Pieter Wuille's avatar
Pieter Wuille committed
1279
                {
1280
                    int64_t nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
Pieter Wuille's avatar
Pieter Wuille committed
1281
1282
1283
1284
1285
                    nChange -= nMoveToFee;
                    nFeeRet += nMoveToFee;
                }

                if (nChange > 0)
1286
                {
1287
1288
1289
                    // Fill a vout to ourself
                    // TODO: pass in scriptChange instead of reservekey so
                    // change transaction isn't always pay-to-bitcoin-address
1290
                    CScript scriptChange;
Cozz Lovan's avatar
Cozz Lovan committed
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307

                    // 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;
1308
1309
1310
                        bool ret;
                        ret = reservekey.GetReservedKey(vchPubKey);
                        assert(ret); // should never fail, as we just unlocked
Cozz Lovan's avatar
Cozz Lovan committed
1311
1312
1313

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

1315
1316
1317
1318
                    CTxOut newTxOut(nChange, scriptChange);

                    // Never create dust outputs; if we would, just
                    // add the dust to the fee.
1319
                    if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
                    {
                        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);
                    }
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
                }
                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++))
1342
1343
                    {
                        strFailReason = _("Signing transaction failed");
1344
                        return false;
1345
                    }
1346
1347

                // Limit size
1348
                unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
1349
                if (nBytes >= MAX_STANDARD_TX_SIZE)
1350
1351
                {
                    strFailReason = _("Transaction too large");
1352
                    return false;
1353
                }
1354
                dPriority = wtxNew.ComputePriority(dPriority, nBytes);
1355
1356

                // Check that enough fee is included
1357
                int64_t nPayFee = nTransactionFee * (1 + (int64_t)nBytes / 1000);
1358
                bool fAllowFree = AllowFree(dPriority);
1359
                int64_t nMinFee = GetMinFee(wtxNew, nBytes, fAllowFree, GMF_SEND);
1360
1361
1362
1363
1364
1365
1366
                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
1367
                wtxNew.AddSupportingTransactions();
1368
1369
1370
1371
1372
1373
1374
1375
1376
                wtxNew.fTimeReceivedIsTxTime = true;

                break;
            }
        }
    }
    return true;
}

1377
bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue,
Cozz Lovan's avatar
Cozz Lovan committed
1378
                                CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
1379
{
1380
    vector< pair<CScript, int64_t> > vecSend;
1381
    vecSend.push_back(make_pair(scriptPubKey, nValue));
Cozz Lovan's avatar
Cozz Lovan committed
1382
    return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl);
1383
1384
1385
1386
1387
1388
}

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

            if (fFileBacked)
                delete pwalletdb;
        }

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

        // Broadcast
1423
        if (!wtxNew.AcceptToMemoryPool(false))
1424
1425
        {
            // This must not fail. The transaction has already been signed and recorded.
1426
            LogPrintf("CommitTransaction() : Error: Transaction not valid");
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
            return false;
        }
        wtxNew.RelayWalletTransaction();
    }
    return true;
}




1437
string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew)
1438
1439
{
    CReserveKey reservekey(this);
1440
    int64_t nFeeRequired;
Gavin Andresen's avatar
Gavin Andresen committed
1441
1442

    if (IsLocked())
1443
    {
1444
        string strError = _("Error: Wallet locked, unable to create transaction!");
1445
        LogPrintf("SendMoney() : %s", strError.c_str());
Gavin Andresen's avatar
Gavin Andresen committed
1446
1447
        return strError;
    }
1448
1449
    string strError;
    if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
Gavin Andresen's avatar
Gavin Andresen committed
1450
1451
    {
        if (nValue + nFeeRequired > GetBalance())
1452
            strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired).c_str());
1453
        LogPrintf("SendMoney() : %s\n", strError.c_str());
Gavin Andresen's avatar
Gavin Andresen committed
1454
        return strError;
1455
1456
1457
    }

    if (!CommitTransaction(wtxNew, reservekey))
1458
        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.");
1459
1460
1461
1462
1463
1464

    return "";
}



1465
string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew)
1466
1467
1468
1469
1470
1471
1472
{
    // Check amount
    if (nValue <= 0)
        return _("Invalid amount");
    if (nValue + nTransactionFee > GetBalance())
        return _("Insufficient funds");

1473
    // Parse Bitcoin address
1474
    CScript scriptPubKey;
1475
    scriptPubKey.SetDestination(address);
1476

1477
    return SendMoney(scriptPubKey, nValue, wtxNew);
1478
1479
1480
1481
1482
}




1483
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1484
1485
{
    if (!fFileBacked)
1486
        return DB_LOAD_OK;
1487
    fFirstRunRet = false;
1488
    DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1489
    if (nLoadWalletRet == DB_NEED_REWRITE)
Pieter Wuille's avatar
Pieter Wuille committed
1490
    {
1491
1492
1493
1494
1495
1496
1497
        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
1498
1499
    }

Matt Corallo's avatar
Matt Corallo committed
1500
1501
    if (nLoadWalletRet != DB_LOAD_OK)
        return nLoadWalletRet;
1502
    fFirstRunRet = !vchDefaultKey.IsValid();
1503

1504
    return DB_LOAD_OK;
1505
1506
}

1507

1508
bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
1509
{
1510
1511
    std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
    mapAddressBook[address].name = strName;
1512
1513
1514
1515
1516
    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);
1517
1518
    if (!fFileBacked)
        return false;
1519
1520
    if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
        return false;
1521
    return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1522
1523
}

1524
bool CWallet::DelAddressBook(const CTxDestination& address)
1525
{
1526
    mapAddressBook.erase(address);
1527
    NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
1528
1529
    if (!fFileBacked)
        return false;
1530
    CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
1531
    return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1532
1533
}

1534
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
{
    if (fFileBacked)
    {
        if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
            return false;
    }
    vchDefaultKey = vchPubKey;
    return true;
}

1545
1546
1547
1548
1549
1550
1551
//
// Mark old keypool keys as used,
// and generate all new keys
//
bool CWallet::NewKeyPool()
{
    {
1552
        LOCK(cs_wallet);
1553
        CWalletDB walletdb(strWalletFile);
1554
        BOOST_FOREACH(int64_t nIndex, setKeyPool)
1555
1556
1557
1558
1559
1560
            walletdb.ErasePool(nIndex);
        setKeyPool.clear();

        if (IsLocked())
            return false;

1561
        int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
1562
1563
        for (int i = 0; i < nKeys; i++)
        {
1564
            int64_t nIndex = i+1;
1565
1566
1567
            walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
            setKeyPool.insert(nIndex);
        }
1568
        LogPrintf("CWallet::NewKeyPool wrote %"PRId64" new keys\n", nKeys);
1569
1570
1571
1572
    }
    return true;
}

1573
bool CWallet::TopUpKeyPool(unsigned int kpSize)
1574
1575
{
    {
1576
1577
        LOCK(cs_wallet);

Matt Corallo's avatar
Matt Corallo committed
1578
1579
1580
        if (IsLocked())
            return false;

1581
1582
1583
        CWalletDB walletdb(strWalletFile);

        // Top up key pool
1584
1585
1586
1587
        unsigned int nTargetSize;
        if (kpSize > 0)
            nTargetSize = kpSize;
        else
1588
            nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
1589

1590
        while (setKeyPool.size() < (nTargetSize + 1))
1591
        {
1592
            int64_t nEnd = 1;
1593
1594
1595
            if (!setKeyPool.empty())
                nEnd = *(--setKeyPool.end()) + 1;
            if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
Matt Corallo's avatar
Matt Corallo committed
1596
                throw runtime_error("TopUpKeyPool() : writing generated key failed");
1597
            setKeyPool.insert(nEnd);
1598
            LogPrintf("keypool added key %"PRId64", size=%"PRIszu"\n", nEnd, setKeyPool.size());
1599
        }
Matt Corallo's avatar
Matt Corallo committed
1600
1601
1602
1603
    }
    return true;
}

1604
void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
Matt Corallo's avatar
Matt Corallo committed
1605
1606
{
    nIndex = -1;
1607
    keypool.vchPubKey = CPubKey();
Matt Corallo's avatar
Matt Corallo committed
1608
    {
1609
1610
        LOCK(cs_wallet);

Matt Corallo's avatar
Matt Corallo committed
1611
1612
        if (!IsLocked())
            TopUpKeyPool();
1613
1614

        // Get the oldest key
Matt Corallo's avatar
Matt Corallo committed
1615
1616
1617
1618
1619
        if(setKeyPool.empty())
            return;

        CWalletDB walletdb(strWalletFile);

1620
1621
1622
1623
        nIndex = *(setKeyPool.begin());
        setKeyPool.erase(setKeyPool.begin());
        if (!walletdb.ReadPool(nIndex, keypool))
            throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1624
        if (!HaveKey(keypool.vchPubKey.GetID()))
1625
            throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1626
        assert(keypool.vchPubKey.IsValid());
1627
        LogPrintf("keypool reserve %"PRId64"\n", nIndex);
1628
1629
1630
    }
}

1631
int64_t CWallet::AddReserveKey(const CKeyPool& keypool)
1632
1633
{
    {
1634
        LOCK2(cs_main, cs_wallet);
1635
1636
        CWalletDB walletdb(strWalletFile);

1637
        int64_t nIndex = 1 + *(--setKeyPool.end());
1638
1639
1640
1641
1642
1643
1644
1645
        if (!walletdb.WritePool(nIndex, keypool))
            throw runtime_error("AddReserveKey() : writing added key failed");
        setKeyPool.insert(nIndex);
        return nIndex;
    }
    return -1;
}

1646
void CWallet::KeepKey(int64_t nIndex)
1647
1648
1649
1650
1651
{
    // Remove from key pool
    if (fFileBacked)
    {
        CWalletDB walletdb(strWalletFile);
Gavin Andresen's avatar
Gavin Andresen committed
1652
        walletdb.ErasePool(nIndex);
1653
    }
1654
    LogPrintf("keypool keep %"PRId64"\n", nIndex);
1655
1656
}

1657
void CWallet::ReturnKey(int64_t nIndex)
1658
1659
{
    // Return to key pool
1660
1661
    {
        LOCK(cs_wallet);
1662
        setKeyPool.insert(nIndex);
1663
    }
1664
    LogPrintf("keypool return %"PRId64"\n", nIndex);
1665
1666
}

1667
bool CWallet::GetKeyFromPool(CPubKey& result)
1668
{
1669
    int64_t nIndex = 0;
1670
    CKeyPool keypool;
1671
    {
1672
        LOCK(cs_wallet);
1673
1674
        ReserveKeyFromKeyPool(nIndex, keypool);
        if (nIndex == -1)
1675
        {
1676
1677
            if (IsLocked()) return false;
            result = GenerateNewKey();
1678
1679
            return true;
        }
1680
1681
        KeepKey(nIndex);
        result = keypool.vchPubKey;
1682
1683
    }
    return true;
1684
1685
}

1686
int64_t CWallet::GetOldestKeyPoolTime()
1687
{
1688
    int64_t nIndex = 0;
1689
1690
    CKeyPool keypool;
    ReserveKeyFromKeyPool(nIndex, keypool);
Matt Corallo's avatar
Matt Corallo committed
1691
1692
    if (nIndex == -1)
        return GetTime();
1693
1694
1695
1696
    ReturnKey(nIndex);
    return keypool.nTime;
}

1697
std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
1698
{
1699
    map<CTxDestination, int64_t> balances;
1700
1701
1702
1703
1704
1705
1706

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

1707
            if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
1708
1709
1710
1711
1712
1713
1714
1715
1716
                continue;

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

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

1717
            for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1718
            {
1719
                CTxDestination addr;
1720
1721
                if (!IsMine(pcoin->vout[i]))
                    continue;
1722
1723
                if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
                    continue;
1724

1725
                int64_t n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736

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

    return balances;
}

1737
set< set<CTxDestination> > CWallet::GetAddressGroupings()
1738
{
1739
1740
    set< set<CTxDestination> > groupings;
    set<CTxDestination> grouping;
1741
1742
1743
1744
1745

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

1746
        if (pcoin->vin.size() > 0)
1747
        {
1748
            bool any_mine = false;
1749
1750
            // group all input addresses with each other
            BOOST_FOREACH(CTxIn txin, pcoin->vin)
1751
1752
            {
                CTxDestination address;
1753
1754
                if(!IsMine(txin)) /* If this input isn't mine, ignore it */
                    continue;
1755
1756
1757
                if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
                    continue;
                grouping.insert(address);
1758
                any_mine = true;
1759
            }
1760
1761

            // group change with input addresses
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
            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();
            }
1778
1779
1780
        }

        // group lone addrs by themselves
1781
        for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1782
1783
            if (IsMine(pcoin->vout[i]))
            {
1784
1785
1786
1787
                CTxDestination address;
                if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
                    continue;
                grouping.insert(address);
1788
1789
1790
1791
1792
                groupings.insert(grouping);
                grouping.clear();
            }
    }

1793
1794
1795
    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)
1796
1797
    {
        // make a set of all the groups hit by this new group
1798
1799
1800
        set< set<CTxDestination>* > hits;
        map< CTxDestination, set<CTxDestination>* >::iterator it;
        BOOST_FOREACH(CTxDestination address, grouping)
1801
1802
1803
1804
            if ((it = setmap.find(address)) != setmap.end())
                hits.insert((*it).second);

        // merge all hit groups into a new single group and delete old groups
1805
1806
        set<CTxDestination>* merged = new set<CTxDestination>(grouping);
        BOOST_FOREACH(set<CTxDestination>* hit, hits)
1807
1808
1809
1810
1811
1812
1813
1814
        {
            merged->insert(hit->begin(), hit->end());
            uniqueGroupings.erase(hit);
            delete hit;
        }
        uniqueGroupings.insert(merged);

        // update setmap
1815
        BOOST_FOREACH(CTxDestination element, *merged)
1816
1817
1818
            setmap[element] = merged;
    }

1819
1820
    set< set<CTxDestination> > ret;
    BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
1821
1822
1823
1824
1825
1826
1827
1828
    {
        ret.insert(*uniqueGrouping);
        delete uniqueGrouping;
    }

    return ret;
}

1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
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;
}

1842
bool CReserveKey::GetReservedKey(CPubKey& pubkey)
1843
1844
1845
1846
1847
{
    if (nIndex == -1)
    {
        CKeyPool keypool;
        pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1848
1849
        if (nIndex != -1)
            vchPubKey = keypool.vchPubKey;
1850
1851
        else {
            if (pwallet->vchDefaultKey.IsValid()) {
1852
                LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
1853
1854
1855
                vchPubKey = pwallet->vchDefaultKey;
            } else
                return false;
1856
        }
1857
    }
1858
    assert(vchPubKey.IsValid());
1859
1860
    pubkey = vchPubKey;
    return true;
1861
1862
1863
1864
1865
1866
1867
}

void CReserveKey::KeepKey()
{
    if (nIndex != -1)
        pwallet->KeepKey(nIndex);
    nIndex = -1;
1868
    vchPubKey = CPubKey();
1869
1870
1871
1872
1873
1874
1875
}

void CReserveKey::ReturnKey()
{
    if (nIndex != -1)
        pwallet->ReturnKey(nIndex);
    nIndex = -1;
1876
    vchPubKey = CPubKey();
1877
}
1878

Pieter Wuille's avatar
Pieter Wuille committed
1879
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
1880
1881
1882
1883
1884
{
    setAddress.clear();

    CWalletDB walletdb(strWalletFile);

1885
    LOCK2(cs_main, cs_wallet);
1886
    BOOST_FOREACH(const int64_t& id, setKeyPool)
1887
1888
1889
1890
    {
        CKeyPool keypool;
        if (!walletdb.ReadPool(id, keypool))
            throw runtime_error("GetAllReserveKeyHashes() : read failed");
1891
        assert(keypool.vchPubKey.IsValid());
1892
1893
        CKeyID keyID = keypool.vchPubKey.GetID();
        if (!HaveKey(keyID))
1894
            throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
1895
        setAddress.insert(keyID);
1896
1897
    }
}
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

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);
    }
}
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940

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

1941
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
Pieter Wuille's avatar
Pieter Wuille committed
1942
1943
1944
1945
1946
1947
1948
1949
    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
1950
    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
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
    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);
1970
        if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
Pieter Wuille's avatar
Pieter Wuille committed
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
            // ... 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
}