File indexing completed on 2020-06-25 15:51:15
0001
0002
0003
0004
0005
0006 #include "headers.h"
0007 #include "db.h"
0008 #include "crypter.h"
0009
0010 using namespace std;
0011
0012
0013
0014
0015
0016
0017
0018 bool CWallet::AddKey(const CKey& key)
0019 {
0020 if (!CCryptoKeyStore::AddKey(key))
0021 return false;
0022 if (!fFileBacked)
0023 return true;
0024 if (!IsCrypted())
0025 return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
0026 return true;
0027 }
0028
0029 bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
0030 {
0031 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
0032 return false;
0033 if (!fFileBacked)
0034 return true;
0035 CRITICAL_BLOCK(cs_wallet)
0036 {
0037 if (pwalletdbEncryption)
0038 return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
0039 else
0040 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
0041 }
0042 return false;
0043 }
0044
0045 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
0046 {
0047 if (!IsLocked())
0048 return false;
0049
0050 CCrypter crypter;
0051 CKeyingMaterial vMasterKey;
0052
0053 CRITICAL_BLOCK(cs_wallet)
0054 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
0055 {
0056 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
0057 return false;
0058 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
0059 return false;
0060 if (CCryptoKeyStore::Unlock(vMasterKey))
0061 return true;
0062 }
0063 return false;
0064 }
0065
0066 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
0067 {
0068 bool fWasLocked = IsLocked();
0069
0070 CRITICAL_BLOCK(cs_wallet)
0071 {
0072 Lock();
0073
0074 CCrypter crypter;
0075 CKeyingMaterial vMasterKey;
0076 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
0077 {
0078 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
0079 return false;
0080 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
0081 return false;
0082 if (CCryptoKeyStore::Unlock(vMasterKey))
0083 {
0084 int64 nStartTime = GetTimeMillis();
0085 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
0086 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
0087
0088 nStartTime = GetTimeMillis();
0089 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
0090 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
0091
0092 if (pMasterKey.second.nDeriveIterations < 25000)
0093 pMasterKey.second.nDeriveIterations = 25000;
0094
0095 printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
0096
0097 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
0098 return false;
0099 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
0100 return false;
0101 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
0102 if (fWasLocked)
0103 Lock();
0104 return true;
0105 }
0106 }
0107 }
0108
0109 return false;
0110 }
0111
0112
0113
0114
0115 class CCorruptAddress
0116 {
0117 public:
0118 IMPLEMENT_SERIALIZE
0119 (
0120 if (nType & SER_DISK)
0121 READWRITE(nVersion);
0122 )
0123 };
0124
0125 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
0126 {
0127 if (IsCrypted())
0128 return false;
0129
0130 CKeyingMaterial vMasterKey;
0131 RandAddSeedPerfmon();
0132
0133 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
0134 RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
0135
0136 CMasterKey kMasterKey;
0137
0138 RandAddSeedPerfmon();
0139 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
0140 RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
0141
0142 CCrypter crypter;
0143 int64 nStartTime = GetTimeMillis();
0144 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
0145 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
0146
0147 nStartTime = GetTimeMillis();
0148 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
0149 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
0150
0151 if (kMasterKey.nDeriveIterations < 25000)
0152 kMasterKey.nDeriveIterations = 25000;
0153
0154 printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
0155
0156 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
0157 return false;
0158 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
0159 return false;
0160
0161 CRITICAL_BLOCK(cs_wallet)
0162 {
0163 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
0164 if (fFileBacked)
0165 {
0166 pwalletdbEncryption = new CWalletDB(strWalletFile);
0167 pwalletdbEncryption->TxnBegin();
0168 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
0169 }
0170
0171 if (!EncryptKeys(vMasterKey))
0172 {
0173 if (fFileBacked)
0174 pwalletdbEncryption->TxnAbort();
0175 exit(1);
0176 }
0177
0178 if (fFileBacked)
0179 {
0180 CCorruptAddress corruptAddress;
0181 pwalletdbEncryption->WriteSetting("addrIncoming", corruptAddress);
0182 if (!pwalletdbEncryption->TxnCommit())
0183 exit(1);
0184
0185 delete pwalletdbEncryption;
0186 pwalletdbEncryption = NULL;
0187 }
0188
0189 Lock();
0190 Unlock(strWalletPassphrase);
0191 NewKeyPool();
0192 Lock();
0193
0194
0195
0196 CDB::Rewrite(strWalletFile);
0197 }
0198
0199 return true;
0200 }
0201
0202 void CWallet::WalletUpdateSpent(const CTransaction &tx)
0203 {
0204
0205
0206
0207 CRITICAL_BLOCK(cs_wallet)
0208 {
0209 BOOST_FOREACH(const CTxIn& txin, tx.vin)
0210 {
0211 map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
0212 if (mi != mapWallet.end())
0213 {
0214 CWalletTx& wtx = (*mi).second;
0215 if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
0216 {
0217 printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
0218 wtx.MarkSpent(txin.prevout.n);
0219 wtx.WriteToDisk();
0220 vWalletUpdated.push_back(txin.prevout.hash);
0221 }
0222 }
0223 }
0224 }
0225 }
0226
0227 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
0228 {
0229 uint256 hash = wtxIn.GetHash();
0230 CRITICAL_BLOCK(cs_wallet)
0231 {
0232
0233 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
0234 CWalletTx& wtx = (*ret.first).second;
0235 wtx.pwallet = this;
0236 bool fInsertedNew = ret.second;
0237 if (fInsertedNew)
0238 wtx.nTimeReceived = GetAdjustedTime();
0239
0240 bool fUpdated = false;
0241 if (!fInsertedNew)
0242 {
0243
0244 if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
0245 {
0246 wtx.hashBlock = wtxIn.hashBlock;
0247 fUpdated = true;
0248 }
0249 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
0250 {
0251 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
0252 wtx.nIndex = wtxIn.nIndex;
0253 fUpdated = true;
0254 }
0255 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
0256 {
0257 wtx.fFromMe = wtxIn.fFromMe;
0258 fUpdated = true;
0259 }
0260 fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
0261 }
0262
0263
0264 printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
0265
0266
0267 if (fInsertedNew || fUpdated)
0268 if (!wtx.WriteToDisk())
0269 return false;
0270
0271 CScript scriptDefaultKey;
0272 scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
0273 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
0274 {
0275 if (txout.scriptPubKey == scriptDefaultKey)
0276 {
0277 std::vector<unsigned char> newDefaultKey;
0278 if (GetKeyFromPool(newDefaultKey, false))
0279 {
0280 SetDefaultKey(newDefaultKey);
0281 SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
0282 }
0283 }
0284 }
0285
0286 vWalletUpdated.push_back(hash);
0287
0288
0289 WalletUpdateSpent(wtx);
0290 }
0291
0292
0293 MainFrameRepaint();
0294 return true;
0295 }
0296
0297
0298
0299
0300 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
0301 {
0302 uint256 hash = tx.GetHash();
0303 CRITICAL_BLOCK(cs_wallet)
0304 {
0305 bool fExisted = mapWallet.count(hash);
0306 if (fExisted && !fUpdate) return false;
0307 if (fExisted || IsMine(tx) || IsFromMe(tx))
0308 {
0309 CWalletTx wtx(this,tx);
0310
0311 if (pblock)
0312 wtx.SetMerkleBranch(pblock);
0313 return AddToWallet(wtx);
0314 }
0315 else
0316 WalletUpdateSpent(tx);
0317 }
0318 return false;
0319 }
0320
0321 bool CWallet::EraseFromWallet(uint256 hash)
0322 {
0323 if (!fFileBacked)
0324 return false;
0325 CRITICAL_BLOCK(cs_wallet)
0326 {
0327 if (mapWallet.erase(hash))
0328 CWalletDB(strWalletFile).EraseTx(hash);
0329 }
0330 return true;
0331 }
0332
0333
0334 bool CWallet::IsMine(const CTxIn &txin) const
0335 {
0336 CRITICAL_BLOCK(cs_wallet)
0337 {
0338 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
0339 if (mi != mapWallet.end())
0340 {
0341 const CWalletTx& prev = (*mi).second;
0342 if (txin.prevout.n < prev.vout.size())
0343 if (IsMine(prev.vout[txin.prevout.n]))
0344 return true;
0345 }
0346 }
0347 return false;
0348 }
0349
0350 int64 CWallet::GetDebit(const CTxIn &txin) const
0351 {
0352 CRITICAL_BLOCK(cs_wallet)
0353 {
0354 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
0355 if (mi != mapWallet.end())
0356 {
0357 const CWalletTx& prev = (*mi).second;
0358 if (txin.prevout.n < prev.vout.size())
0359 if (IsMine(prev.vout[txin.prevout.n]))
0360 return prev.vout[txin.prevout.n].nValue;
0361 }
0362 }
0363 return 0;
0364 }
0365
0366 int64 CWalletTx::GetTxTime() const
0367 {
0368 return nTimeReceived;
0369 }
0370
0371 int CWalletTx::GetRequestCount() const
0372 {
0373
0374 int nRequests = -1;
0375 CRITICAL_BLOCK(pwallet->cs_wallet)
0376 {
0377 if (IsCoinBase())
0378 {
0379
0380 if (hashBlock != 0)
0381 {
0382 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
0383 if (mi != pwallet->mapRequestCount.end())
0384 nRequests = (*mi).second;
0385 }
0386 }
0387 else
0388 {
0389
0390 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
0391 if (mi != pwallet->mapRequestCount.end())
0392 {
0393 nRequests = (*mi).second;
0394
0395
0396 if (nRequests == 0 && hashBlock != 0)
0397 {
0398 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
0399 if (mi != pwallet->mapRequestCount.end())
0400 nRequests = (*mi).second;
0401 else
0402 nRequests = 1;
0403 }
0404 }
0405 }
0406 }
0407 return nRequests;
0408 }
0409
0410 void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CBitcoinAddress, int64> >& listReceived,
0411 list<pair<CBitcoinAddress, int64> >& listSent, int64& nFee, string& strSentAccount) const
0412 {
0413 nGeneratedImmature = nGeneratedMature = nFee = 0;
0414 listReceived.clear();
0415 listSent.clear();
0416 strSentAccount = strFromAccount;
0417
0418 if (IsCoinBase())
0419 {
0420 if (GetBlocksToMaturity() > 0)
0421 nGeneratedImmature = pwallet->GetCredit(*this);
0422 else
0423 nGeneratedMature = GetCredit();
0424 return;
0425 }
0426
0427
0428 int64 nDebit = GetDebit();
0429 if (nDebit > 0)
0430 {
0431 int64 nValueOut = GetValueOut();
0432 nFee = nDebit - nValueOut;
0433 }
0434
0435
0436
0437 BOOST_FOREACH(const CTxOut& txout, vout)
0438 {
0439 CBitcoinAddress address;
0440 vector<unsigned char> vchPubKey;
0441 if (!ExtractAddress(txout.scriptPubKey, NULL, address))
0442 {
0443 printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
0444 this->GetHash().ToString().c_str());
0445 address = " unknown ";
0446 }
0447
0448
0449 if (nDebit > 0 && pwallet->IsChange(txout))
0450 continue;
0451
0452 if (nDebit > 0)
0453 listSent.push_back(make_pair(address, txout.nValue));
0454
0455 if (pwallet->IsMine(txout))
0456 listReceived.push_back(make_pair(address, txout.nValue));
0457 }
0458
0459 }
0460
0461 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived,
0462 int64& nSent, int64& nFee) const
0463 {
0464 nGenerated = nReceived = nSent = nFee = 0;
0465
0466 int64 allGeneratedImmature, allGeneratedMature, allFee;
0467 allGeneratedImmature = allGeneratedMature = allFee = 0;
0468 string strSentAccount;
0469 list<pair<CBitcoinAddress, int64> > listReceived;
0470 list<pair<CBitcoinAddress, int64> > listSent;
0471 GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
0472
0473 if (strAccount == "")
0474 nGenerated = allGeneratedMature;
0475 if (strAccount == strSentAccount)
0476 {
0477 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& s, listSent)
0478 nSent += s.second;
0479 nFee = allFee;
0480 }
0481 CRITICAL_BLOCK(pwallet->cs_wallet)
0482 {
0483 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
0484 {
0485 if (pwallet->mapAddressBook.count(r.first))
0486 {
0487 map<CBitcoinAddress, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
0488 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
0489 nReceived += r.second;
0490 }
0491 else if (strAccount.empty())
0492 {
0493 nReceived += r.second;
0494 }
0495 }
0496 }
0497 }
0498
0499 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
0500 {
0501 vtxPrev.clear();
0502
0503 const int COPY_DEPTH = 3;
0504 if (SetMerkleBranch() < COPY_DEPTH)
0505 {
0506 vector<uint256> vWorkQueue;
0507 BOOST_FOREACH(const CTxIn& txin, vin)
0508 vWorkQueue.push_back(txin.prevout.hash);
0509
0510
0511 CRITICAL_BLOCK(pwallet->cs_wallet)
0512 {
0513 map<uint256, const CMerkleTx*> mapWalletPrev;
0514 set<uint256> setAlreadyDone;
0515 for (int i = 0; i < vWorkQueue.size(); i++)
0516 {
0517 uint256 hash = vWorkQueue[i];
0518 if (setAlreadyDone.count(hash))
0519 continue;
0520 setAlreadyDone.insert(hash);
0521
0522 CMerkleTx tx;
0523 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
0524 if (mi != pwallet->mapWallet.end())
0525 {
0526 tx = (*mi).second;
0527 BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
0528 mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
0529 }
0530 else if (mapWalletPrev.count(hash))
0531 {
0532 tx = *mapWalletPrev[hash];
0533 }
0534 else if (!fClient && txdb.ReadDiskTx(hash, tx))
0535 {
0536 ;
0537 }
0538 else
0539 {
0540 printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
0541 continue;
0542 }
0543
0544 int nDepth = tx.SetMerkleBranch();
0545 vtxPrev.push_back(tx);
0546
0547 if (nDepth < COPY_DEPTH)
0548 BOOST_FOREACH(const CTxIn& txin, tx.vin)
0549 vWorkQueue.push_back(txin.prevout.hash);
0550 }
0551 }
0552 }
0553
0554 reverse(vtxPrev.begin(), vtxPrev.end());
0555 }
0556
0557 bool CWalletTx::WriteToDisk()
0558 {
0559 return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
0560 }
0561
0562
0563
0564
0565 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
0566 {
0567 int ret = 0;
0568
0569 CBlockIndex* pindex = pindexStart;
0570 CRITICAL_BLOCK(cs_wallet)
0571 {
0572 while (pindex)
0573 {
0574 CBlock block;
0575 block.ReadFromDisk(pindex, true);
0576 BOOST_FOREACH(CTransaction& tx, block.vtx)
0577 {
0578 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
0579 ret++;
0580 }
0581 pindex = pindex->pnext;
0582 }
0583 }
0584 return ret;
0585 }
0586
0587 void CWallet::ReacceptWalletTransactions()
0588 {
0589 CTxDB txdb("r");
0590 bool fRepeat = true;
0591 while (fRepeat) CRITICAL_BLOCK(cs_wallet)
0592 {
0593 fRepeat = false;
0594 vector<CDiskTxPos> vMissingTx;
0595 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
0596 {
0597 CWalletTx& wtx = item.second;
0598 if (wtx.IsCoinBase() && wtx.IsSpent(0))
0599 continue;
0600
0601 CTxIndex txindex;
0602 bool fUpdated = false;
0603 if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
0604 {
0605
0606 if (txindex.vSpent.size() != wtx.vout.size())
0607 {
0608 printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
0609 continue;
0610 }
0611 for (int i = 0; i < txindex.vSpent.size(); i++)
0612 {
0613 if (wtx.IsSpent(i))
0614 continue;
0615 if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
0616 {
0617 wtx.MarkSpent(i);
0618 fUpdated = true;
0619 vMissingTx.push_back(txindex.vSpent[i]);
0620 }
0621 }
0622 if (fUpdated)
0623 {
0624 printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
0625 wtx.MarkDirty();
0626 wtx.WriteToDisk();
0627 }
0628 }
0629 else
0630 {
0631
0632 if (!wtx.IsCoinBase())
0633 wtx.AcceptWalletTransaction(txdb, false);
0634 }
0635 }
0636 if (!vMissingTx.empty())
0637 {
0638
0639 if (ScanForWalletTransactions(pindexGenesisBlock))
0640 fRepeat = true;
0641 }
0642 }
0643 }
0644
0645 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
0646 {
0647 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
0648 {
0649 if (!tx.IsCoinBase())
0650 {
0651 uint256 hash = tx.GetHash();
0652 if (!txdb.ContainsTx(hash))
0653 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
0654 }
0655 }
0656 if (!IsCoinBase())
0657 {
0658 uint256 hash = GetHash();
0659 if (!txdb.ContainsTx(hash))
0660 {
0661 printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
0662 RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
0663 }
0664 }
0665 }
0666
0667 void CWalletTx::RelayWalletTransaction()
0668 {
0669 CTxDB txdb("r");
0670 RelayWalletTransaction(txdb);
0671 }
0672
0673 void CWallet::ResendWalletTransactions()
0674 {
0675
0676
0677 static int64 nNextTime;
0678 if (GetTime() < nNextTime)
0679 return;
0680 bool fFirst = (nNextTime == 0);
0681 nNextTime = GetTime() + GetRand(30 * 60);
0682 if (fFirst)
0683 return;
0684
0685
0686 static int64 nLastTime;
0687 if (nTimeBestReceived < nLastTime)
0688 return;
0689 nLastTime = GetTime();
0690
0691
0692 printf("ResendWalletTransactions()\n");
0693 CTxDB txdb("r");
0694 CRITICAL_BLOCK(cs_wallet)
0695 {
0696
0697 multimap<unsigned int, CWalletTx*> mapSorted;
0698 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
0699 {
0700 CWalletTx& wtx = item.second;
0701
0702
0703 if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
0704 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
0705 }
0706 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
0707 {
0708 CWalletTx& wtx = *item.second;
0709 wtx.RelayWalletTransaction(txdb);
0710 }
0711 }
0712 }
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725 int64 CWallet::GetBalance() const
0726 {
0727 int64 nTotal = 0;
0728 CRITICAL_BLOCK(cs_wallet)
0729 {
0730 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
0731 {
0732 const CWalletTx* pcoin = &(*it).second;
0733 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
0734 continue;
0735 nTotal += pcoin->GetAvailableCredit();
0736 }
0737 }
0738
0739 return nTotal;
0740 }
0741
0742 int64 CWallet::GetUnconfirmedBalance() const
0743 {
0744 int64 nTotal = 0;
0745 CRITICAL_BLOCK(cs_wallet)
0746 {
0747 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
0748 {
0749 const CWalletTx* pcoin = &(*it).second;
0750 if (pcoin->IsFinal() && pcoin->IsConfirmed())
0751 continue;
0752 nTotal += pcoin->GetAvailableCredit();
0753 }
0754 }
0755 return nTotal;
0756 }
0757
0758 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
0759 {
0760 setCoinsRet.clear();
0761 nValueRet = 0;
0762
0763
0764 pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
0765 coinLowestLarger.first = INT64_MAX;
0766 coinLowestLarger.second.first = NULL;
0767 vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
0768 int64 nTotalLower = 0;
0769
0770 CRITICAL_BLOCK(cs_wallet)
0771 {
0772 vector<const CWalletTx*> vCoins;
0773 vCoins.reserve(mapWallet.size());
0774 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
0775 vCoins.push_back(&(*it).second);
0776 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
0777
0778 BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
0779 {
0780 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
0781 continue;
0782
0783 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
0784 continue;
0785
0786 int nDepth = pcoin->GetDepthInMainChain();
0787 if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
0788 continue;
0789
0790 for (int i = 0; i < pcoin->vout.size(); i++)
0791 {
0792 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
0793 continue;
0794
0795 int64 n = pcoin->vout[i].nValue;
0796
0797 if (n <= 0)
0798 continue;
0799
0800 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
0801
0802 if (n == nTargetValue)
0803 {
0804 setCoinsRet.insert(coin.second);
0805 nValueRet += coin.first;
0806 return true;
0807 }
0808 else if (n < nTargetValue + CENT)
0809 {
0810 vValue.push_back(coin);
0811 nTotalLower += n;
0812 }
0813 else if (n < coinLowestLarger.first)
0814 {
0815 coinLowestLarger = coin;
0816 }
0817 }
0818 }
0819 }
0820
0821 if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
0822 {
0823 for (int i = 0; i < vValue.size(); ++i)
0824 {
0825 setCoinsRet.insert(vValue[i].second);
0826 nValueRet += vValue[i].first;
0827 }
0828 return true;
0829 }
0830
0831 if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
0832 {
0833 if (coinLowestLarger.second.first == NULL)
0834 return false;
0835 setCoinsRet.insert(coinLowestLarger.second);
0836 nValueRet += coinLowestLarger.first;
0837 return true;
0838 }
0839
0840 if (nTotalLower >= nTargetValue + CENT)
0841 nTargetValue += CENT;
0842
0843
0844 sort(vValue.rbegin(), vValue.rend());
0845 vector<char> vfIncluded;
0846 vector<char> vfBest(vValue.size(), true);
0847 int64 nBest = nTotalLower;
0848
0849 for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
0850 {
0851 vfIncluded.assign(vValue.size(), false);
0852 int64 nTotal = 0;
0853 bool fReachedTarget = false;
0854 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
0855 {
0856 for (int i = 0; i < vValue.size(); i++)
0857 {
0858 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
0859 {
0860 nTotal += vValue[i].first;
0861 vfIncluded[i] = true;
0862 if (nTotal >= nTargetValue)
0863 {
0864 fReachedTarget = true;
0865 if (nTotal < nBest)
0866 {
0867 nBest = nTotal;
0868 vfBest = vfIncluded;
0869 }
0870 nTotal -= vValue[i].first;
0871 vfIncluded[i] = false;
0872 }
0873 }
0874 }
0875 }
0876 }
0877
0878
0879 if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
0880 {
0881 setCoinsRet.insert(coinLowestLarger.second);
0882 nValueRet += coinLowestLarger.first;
0883 }
0884 else {
0885 for (int i = 0; i < vValue.size(); i++)
0886 if (vfBest[i])
0887 {
0888 setCoinsRet.insert(vValue[i].second);
0889 nValueRet += vValue[i].first;
0890 }
0891
0892
0893 printf("SelectCoins() best subset: ");
0894 for (int i = 0; i < vValue.size(); i++)
0895 if (vfBest[i])
0896 printf("%s ", FormatMoney(vValue[i].first).c_str());
0897 printf("total %s\n", FormatMoney(nBest).c_str());
0898 }
0899
0900 return true;
0901 }
0902
0903 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
0904 {
0905 return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
0906 SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
0907 SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
0908 }
0909
0910
0911
0912
0913 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
0914 {
0915 int64 nValue = 0;
0916 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
0917 {
0918 if (nValue < 0)
0919 return false;
0920 nValue += s.second;
0921 }
0922 if (vecSend.empty() || nValue < 0)
0923 return false;
0924
0925 wtxNew.pwallet = this;
0926
0927 CRITICAL_BLOCK(cs_main)
0928 CRITICAL_BLOCK(cs_wallet)
0929 {
0930
0931 CTxDB txdb("r");
0932 {
0933 nFeeRet = nTransactionFee;
0934 loop
0935 {
0936 wtxNew.vin.clear();
0937 wtxNew.vout.clear();
0938 wtxNew.fFromMe = true;
0939
0940 int64 nTotalValue = nValue + nFeeRet;
0941 double dPriority = 0;
0942
0943 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
0944 wtxNew.vout.push_back(CTxOut(s.second, s.first));
0945
0946
0947 set<pair<const CWalletTx*,unsigned int> > setCoins;
0948 int64 nValueIn = 0;
0949 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
0950 return false;
0951 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
0952 {
0953 int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
0954 dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
0955 }
0956
0957 int64 nChange = nValueIn - nValue - nFeeRet;
0958
0959
0960 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
0961 {
0962 int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
0963 nChange -= nMoveToFee;
0964 nFeeRet +=