raw
genesis                 1 // Copyright (c) 2009-2010 Satoshi Nakamoto
genesis 2 // Copyright (c) 2011 The Bitcoin developers
genesis 3 // Distributed under the MIT/X11 software license, see the accompanying
genesis 4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
genesis 5
genesis 6 #include "headers.h"
genesis 7 #include "db.h"
genesis 8 #include "crypter.h"
genesis 9
genesis 10 using namespace std;
genesis 11
genesis 12
genesis 13 //////////////////////////////////////////////////////////////////////////////
genesis 14 //
genesis 15 // mapWallet
genesis 16 //
genesis 17
genesis 18 bool CWallet::AddKey(const CKey& key)
genesis 19 {
genesis 20 if (!CCryptoKeyStore::AddKey(key))
genesis 21 return false;
genesis 22 if (!fFileBacked)
genesis 23 return true;
genesis 24 if (!IsCrypted())
genesis 25 return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
genesis 26 return true;
genesis 27 }
genesis 28
genesis 29 bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
genesis 30 {
genesis 31 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
genesis 32 return false;
genesis 33 if (!fFileBacked)
genesis 34 return true;
genesis 35 CRITICAL_BLOCK(cs_wallet)
genesis 36 {
genesis 37 if (pwalletdbEncryption)
genesis 38 return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
genesis 39 else
genesis 40 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
genesis 41 }
genesis 42 return false;
genesis 43 }
genesis 44
genesis 45 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
genesis 46 {
genesis 47 if (!IsLocked())
genesis 48 return false;
genesis 49
genesis 50 CCrypter crypter;
genesis 51 CKeyingMaterial vMasterKey;
genesis 52
genesis 53 CRITICAL_BLOCK(cs_wallet)
genesis 54 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
genesis 55 {
genesis 56 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
genesis 57 return false;
genesis 58 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
genesis 59 return false;
genesis 60 if (CCryptoKeyStore::Unlock(vMasterKey))
genesis 61 return true;
genesis 62 }
genesis 63 return false;
genesis 64 }
genesis 65
genesis 66 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
genesis 67 {
genesis 68 bool fWasLocked = IsLocked();
genesis 69
genesis 70 CRITICAL_BLOCK(cs_wallet)
genesis 71 {
genesis 72 Lock();
genesis 73
genesis 74 CCrypter crypter;
genesis 75 CKeyingMaterial vMasterKey;
genesis 76 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
genesis 77 {
genesis 78 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
genesis 79 return false;
genesis 80 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
genesis 81 return false;
genesis 82 if (CCryptoKeyStore::Unlock(vMasterKey))
genesis 83 {
genesis 84 int64 nStartTime = GetTimeMillis();
genesis 85 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
genesis 86 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
genesis 87
genesis 88 nStartTime = GetTimeMillis();
genesis 89 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
genesis 90 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
genesis 91
genesis 92 if (pMasterKey.second.nDeriveIterations < 25000)
genesis 93 pMasterKey.second.nDeriveIterations = 25000;
genesis 94
genesis 95 printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
genesis 96
genesis 97 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
genesis 98 return false;
genesis 99 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
genesis 100 return false;
genesis 101 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
genesis 102 if (fWasLocked)
genesis 103 Lock();
genesis 104 return true;
genesis 105 }
genesis 106 }
genesis 107 }
genesis 108
genesis 109 return false;
genesis 110 }
genesis 111
genesis 112
genesis 113 // This class implements an addrIncoming entry that causes pre-0.4
genesis 114 // clients to crash on startup if reading a private-key-encrypted wallet.
genesis 115 class CCorruptAddress
genesis 116 {
genesis 117 public:
genesis 118 IMPLEMENT_SERIALIZE
genesis 119 (
genesis 120 if (nType & SER_DISK)
genesis 121 READWRITE(nVersion);
genesis 122 )
genesis 123 };
genesis 124
genesis 125 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
genesis 126 {
genesis 127 if (IsCrypted())
genesis 128 return false;
genesis 129
genesis 130 CKeyingMaterial vMasterKey;
genesis 131 RandAddSeedPerfmon();
genesis 132
genesis 133 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
genesis 134 RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
genesis 135
genesis 136 CMasterKey kMasterKey;
genesis 137
genesis 138 RandAddSeedPerfmon();
genesis 139 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
genesis 140 RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
genesis 141
genesis 142 CCrypter crypter;
genesis 143 int64 nStartTime = GetTimeMillis();
genesis 144 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
genesis 145 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
genesis 146
genesis 147 nStartTime = GetTimeMillis();
genesis 148 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
genesis 149 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
genesis 150
genesis 151 if (kMasterKey.nDeriveIterations < 25000)
genesis 152 kMasterKey.nDeriveIterations = 25000;
genesis 153
genesis 154 printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
genesis 155
genesis 156 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
genesis 157 return false;
genesis 158 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
genesis 159 return false;
genesis 160
genesis 161 CRITICAL_BLOCK(cs_wallet)
genesis 162 {
genesis 163 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
genesis 164 if (fFileBacked)
genesis 165 {
genesis 166 pwalletdbEncryption = new CWalletDB(strWalletFile);
genesis 167 pwalletdbEncryption->TxnBegin();
genesis 168 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
genesis 169 }
genesis 170
genesis 171 if (!EncryptKeys(vMasterKey))
genesis 172 {
genesis 173 if (fFileBacked)
genesis 174 pwalletdbEncryption->TxnAbort();
genesis 175 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.
genesis 176 }
genesis 177
genesis 178 if (fFileBacked)
genesis 179 {
genesis 180 CCorruptAddress corruptAddress;
genesis 181 pwalletdbEncryption->WriteSetting("addrIncoming", corruptAddress);
genesis 182 if (!pwalletdbEncryption->TxnCommit())
genesis 183 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.
genesis 184
genesis 185 delete pwalletdbEncryption;
genesis 186 pwalletdbEncryption = NULL;
genesis 187 }
genesis 188
genesis 189 Lock();
genesis 190 Unlock(strWalletPassphrase);
genesis 191 NewKeyPool();
genesis 192 Lock();
genesis 193
genesis 194 // Need to completely rewrite the wallet file; if we don't, bdb might keep
genesis 195 // bits of the unencrypted private key in slack space in the database file.
genesis 196 CDB::Rewrite(strWalletFile);
genesis 197 }
genesis 198
genesis 199 return true;
genesis 200 }
genesis 201
genesis 202 void CWallet::WalletUpdateSpent(const CTransaction &tx)
genesis 203 {
genesis 204 // Anytime a signature is successfully verified, it's proof the outpoint is spent.
genesis 205 // Update the wallet spent flag if it doesn't know due to wallet.dat being
genesis 206 // restored from backup or the user making copies of wallet.dat.
genesis 207 CRITICAL_BLOCK(cs_wallet)
genesis 208 {
genesis 209 BOOST_FOREACH(const CTxIn& txin, tx.vin)
genesis 210 {
genesis 211 map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
genesis 212 if (mi != mapWallet.end())
genesis 213 {
genesis 214 CWalletTx& wtx = (*mi).second;
genesis 215 if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
genesis 216 {
genesis 217 printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
genesis 218 wtx.MarkSpent(txin.prevout.n);
genesis 219 wtx.WriteToDisk();
genesis 220 vWalletUpdated.push_back(txin.prevout.hash);
genesis 221 }
genesis 222 }
genesis 223 }
genesis 224 }
genesis 225 }
genesis 226
mod6_privkey_tools 227 void CWallet::MarkDirty()
mod6_privkey_tools 228 {
mod6_privkey_tools 229 CRITICAL_BLOCK(cs_wallet)
mod6_privkey_tools 230 {
mod6_privkey_tools 231 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
mod6_privkey_tools 232 item.second.MarkDirty();
mod6_privkey_tools 233 }
mod6_privkey_tools 234 }
mod6_privkey_tools 235
genesis 236 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
genesis 237 {
genesis 238 uint256 hash = wtxIn.GetHash();
genesis 239 CRITICAL_BLOCK(cs_wallet)
genesis 240 {
genesis 241 // Inserts only if not already there, returns tx inserted or tx found
genesis 242 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
genesis 243 CWalletTx& wtx = (*ret.first).second;
genesis 244 wtx.pwallet = this;
genesis 245 bool fInsertedNew = ret.second;
genesis 246 if (fInsertedNew)
genesis 247 wtx.nTimeReceived = GetAdjustedTime();
genesis 248
genesis 249 bool fUpdated = false;
genesis 250 if (!fInsertedNew)
genesis 251 {
genesis 252 // Merge
genesis 253 if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
genesis 254 {
genesis 255 wtx.hashBlock = wtxIn.hashBlock;
genesis 256 fUpdated = true;
genesis 257 }
genesis 258 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
genesis 259 {
genesis 260 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
genesis 261 wtx.nIndex = wtxIn.nIndex;
genesis 262 fUpdated = true;
genesis 263 }
genesis 264 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
genesis 265 {
genesis 266 wtx.fFromMe = wtxIn.fFromMe;
genesis 267 fUpdated = true;
genesis 268 }
genesis 269 fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
genesis 270 }
genesis 271
genesis 272 //// debug print
mod6_excise_hash_... 273 printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
genesis 274
genesis 275 // Write to disk
genesis 276 if (fInsertedNew || fUpdated)
genesis 277 if (!wtx.WriteToDisk())
genesis 278 return false;
genesis 279 // If default receiving address gets used, replace it with a new one
genesis 280 CScript scriptDefaultKey;
genesis 281 scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
genesis 282 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
genesis 283 {
genesis 284 if (txout.scriptPubKey == scriptDefaultKey)
genesis 285 {
genesis 286 std::vector<unsigned char> newDefaultKey;
genesis 287 if (GetKeyFromPool(newDefaultKey, false))
genesis 288 {
genesis 289 SetDefaultKey(newDefaultKey);
genesis 290 SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
genesis 291 }
genesis 292 }
genesis 293 }
genesis 294 // Notify UI
genesis 295 vWalletUpdated.push_back(hash);
genesis 296
genesis 297 // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
genesis 298 WalletUpdateSpent(wtx);
genesis 299 }
genesis 300
genesis 301 // Refresh UI
genesis 302 MainFrameRepaint();
genesis 303 return true;
genesis 304 }
genesis 305
genesis 306 // Add a transaction to the wallet, or update it.
genesis 307 // pblock is optional, but should be provided if the transaction is known to be in a block.
genesis 308 // If fUpdate is true, existing transactions will be updated.
genesis 309 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
genesis 310 {
genesis 311 uint256 hash = tx.GetHash();
genesis 312 CRITICAL_BLOCK(cs_wallet)
genesis 313 {
genesis 314 bool fExisted = mapWallet.count(hash);
genesis 315 if (fExisted && !fUpdate) return false;
genesis 316 if (fExisted || IsMine(tx) || IsFromMe(tx))
genesis 317 {
genesis 318 CWalletTx wtx(this,tx);
genesis 319 // Get merkle branch if transaction was found in a block
genesis 320 if (pblock)
genesis 321 wtx.SetMerkleBranch(pblock);
genesis 322 return AddToWallet(wtx);
genesis 323 }
genesis 324 else
genesis 325 WalletUpdateSpent(tx);
genesis 326 }
genesis 327 return false;
genesis 328 }
genesis 329
genesis 330 bool CWallet::EraseFromWallet(uint256 hash)
genesis 331 {
genesis 332 if (!fFileBacked)
genesis 333 return false;
genesis 334 CRITICAL_BLOCK(cs_wallet)
genesis 335 {
genesis 336 if (mapWallet.erase(hash))
genesis 337 CWalletDB(strWalletFile).EraseTx(hash);
genesis 338 }
genesis 339 return true;
genesis 340 }
genesis 341
genesis 342
genesis 343 bool CWallet::IsMine(const CTxIn &txin) const
genesis 344 {
genesis 345 CRITICAL_BLOCK(cs_wallet)
genesis 346 {
genesis 347 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
genesis 348 if (mi != mapWallet.end())
genesis 349 {
genesis 350 const CWalletTx& prev = (*mi).second;
genesis 351 if (txin.prevout.n < prev.vout.size())
genesis 352 if (IsMine(prev.vout[txin.prevout.n]))
genesis 353 return true;
genesis 354 }
genesis 355 }
genesis 356 return false;
genesis 357 }
genesis 358
genesis 359 int64 CWallet::GetDebit(const CTxIn &txin) const
genesis 360 {
genesis 361 CRITICAL_BLOCK(cs_wallet)
genesis 362 {
genesis 363 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
genesis 364 if (mi != mapWallet.end())
genesis 365 {
genesis 366 const CWalletTx& prev = (*mi).second;
genesis 367 if (txin.prevout.n < prev.vout.size())
genesis 368 if (IsMine(prev.vout[txin.prevout.n]))
genesis 369 return prev.vout[txin.prevout.n].nValue;
genesis 370 }
genesis 371 }
genesis 372 return 0;
genesis 373 }
genesis 374
genesis 375 int64 CWalletTx::GetTxTime() const
genesis 376 {
genesis 377 return nTimeReceived;
genesis 378 }
genesis 379
genesis 380 int CWalletTx::GetRequestCount() const
genesis 381 {
genesis 382 // Returns -1 if it wasn't being tracked
genesis 383 int nRequests = -1;
genesis 384 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 385 {
genesis 386 if (IsCoinBase())
genesis 387 {
genesis 388 // Generated block
genesis 389 if (hashBlock != 0)
genesis 390 {
genesis 391 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
genesis 392 if (mi != pwallet->mapRequestCount.end())
genesis 393 nRequests = (*mi).second;
genesis 394 }
genesis 395 }
genesis 396 else
genesis 397 {
genesis 398 // Did anyone request this transaction?
genesis 399 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
genesis 400 if (mi != pwallet->mapRequestCount.end())
genesis 401 {
genesis 402 nRequests = (*mi).second;
genesis 403
genesis 404 // How about the block it's in?
genesis 405 if (nRequests == 0 && hashBlock != 0)
genesis 406 {
genesis 407 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
genesis 408 if (mi != pwallet->mapRequestCount.end())
genesis 409 nRequests = (*mi).second;
genesis 410 else
genesis 411 nRequests = 1; // If it's in someone else's block it must have got out
genesis 412 }
genesis 413 }
genesis 414 }
genesis 415 }
genesis 416 return nRequests;
genesis 417 }
genesis 418
genesis 419 void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CBitcoinAddress, int64> >& listReceived,
genesis 420 list<pair<CBitcoinAddress, int64> >& listSent, int64& nFee, string& strSentAccount) const
genesis 421 {
genesis 422 nGeneratedImmature = nGeneratedMature = nFee = 0;
genesis 423 listReceived.clear();
genesis 424 listSent.clear();
genesis 425 strSentAccount = strFromAccount;
genesis 426
genesis 427 if (IsCoinBase())
genesis 428 {
genesis 429 if (GetBlocksToMaturity() > 0)
genesis 430 nGeneratedImmature = pwallet->GetCredit(*this);
genesis 431 else
genesis 432 nGeneratedMature = GetCredit();
genesis 433 return;
genesis 434 }
genesis 435
genesis 436 // Compute fee:
genesis 437 int64 nDebit = GetDebit();
genesis 438 if (nDebit > 0) // debit>0 means we signed/sent this transaction
genesis 439 {
genesis 440 int64 nValueOut = GetValueOut();
genesis 441 nFee = nDebit - nValueOut;
genesis 442 }
genesis 443
genesis 444 // Sent/received. Standard client will never generate a send-to-multiple-recipients,
genesis 445 // but non-standard clients might (so return a list of address/amount pairs)
genesis 446 BOOST_FOREACH(const CTxOut& txout, vout)
genesis 447 {
genesis 448 CBitcoinAddress address;
genesis 449 vector<unsigned char> vchPubKey;
genesis 450 if (!ExtractAddress(txout.scriptPubKey, NULL, address))
genesis 451 {
genesis 452 printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
genesis 453 this->GetHash().ToString().c_str());
genesis 454 address = " unknown ";
genesis 455 }
genesis 456
genesis 457 // Don't report 'change' txouts
genesis 458 if (nDebit > 0 && pwallet->IsChange(txout))
genesis 459 continue;
genesis 460
genesis 461 if (nDebit > 0)
genesis 462 listSent.push_back(make_pair(address, txout.nValue));
genesis 463
genesis 464 if (pwallet->IsMine(txout))
genesis 465 listReceived.push_back(make_pair(address, txout.nValue));
genesis 466 }
genesis 467
genesis 468 }
genesis 469
mod6_excise_hash_... 470 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived,
genesis 471 int64& nSent, int64& nFee) const
genesis 472 {
genesis 473 nGenerated = nReceived = nSent = nFee = 0;
genesis 474
genesis 475 int64 allGeneratedImmature, allGeneratedMature, allFee;
genesis 476 allGeneratedImmature = allGeneratedMature = allFee = 0;
genesis 477 string strSentAccount;
genesis 478 list<pair<CBitcoinAddress, int64> > listReceived;
genesis 479 list<pair<CBitcoinAddress, int64> > listSent;
genesis 480 GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
genesis 481
genesis 482 if (strAccount == "")
genesis 483 nGenerated = allGeneratedMature;
genesis 484 if (strAccount == strSentAccount)
genesis 485 {
genesis 486 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& s, listSent)
genesis 487 nSent += s.second;
genesis 488 nFee = allFee;
genesis 489 }
genesis 490 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 491 {
genesis 492 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
genesis 493 {
genesis 494 if (pwallet->mapAddressBook.count(r.first))
genesis 495 {
genesis 496 map<CBitcoinAddress, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
genesis 497 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
genesis 498 nReceived += r.second;
genesis 499 }
genesis 500 else if (strAccount.empty())
genesis 501 {
genesis 502 nReceived += r.second;
genesis 503 }
genesis 504 }
genesis 505 }
genesis 506 }
genesis 507
genesis 508 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
genesis 509 {
genesis 510 vtxPrev.clear();
genesis 511
genesis 512 const int COPY_DEPTH = 3;
genesis 513 if (SetMerkleBranch() < COPY_DEPTH)
genesis 514 {
genesis 515 vector<uint256> vWorkQueue;
genesis 516 BOOST_FOREACH(const CTxIn& txin, vin)
genesis 517 vWorkQueue.push_back(txin.prevout.hash);
genesis 518
genesis 519 // This critsect is OK because txdb is already open
genesis 520 CRITICAL_BLOCK(pwallet->cs_wallet)
genesis 521 {
genesis 522 map<uint256, const CMerkleTx*> mapWalletPrev;
genesis 523 set<uint256> setAlreadyDone;
genesis 524 for (int i = 0; i < vWorkQueue.size(); i++)
genesis 525 {
genesis 526 uint256 hash = vWorkQueue[i];
genesis 527 if (setAlreadyDone.count(hash))
genesis 528 continue;
genesis 529 setAlreadyDone.insert(hash);
genesis 530
genesis 531 CMerkleTx tx;
genesis 532 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
genesis 533 if (mi != pwallet->mapWallet.end())
genesis 534 {
genesis 535 tx = (*mi).second;
genesis 536 BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
genesis 537 mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
genesis 538 }
genesis 539 else if (mapWalletPrev.count(hash))
genesis 540 {
genesis 541 tx = *mapWalletPrev[hash];
genesis 542 }
genesis 543 else if (!fClient && txdb.ReadDiskTx(hash, tx))
genesis 544 {
genesis 545 ;
genesis 546 }
genesis 547 else
genesis 548 {
genesis 549 printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
genesis 550 continue;
genesis 551 }
genesis 552
genesis 553 int nDepth = tx.SetMerkleBranch();
genesis 554 vtxPrev.push_back(tx);
genesis 555
genesis 556 if (nDepth < COPY_DEPTH)
genesis 557 BOOST_FOREACH(const CTxIn& txin, tx.vin)
genesis 558 vWorkQueue.push_back(txin.prevout.hash);
genesis 559 }
genesis 560 }
genesis 561 }
genesis 562
genesis 563 reverse(vtxPrev.begin(), vtxPrev.end());
genesis 564 }
genesis 565
genesis 566 bool CWalletTx::WriteToDisk()
genesis 567 {
genesis 568 return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
genesis 569 }
genesis 570
genesis 571 // Scan the block chain (starting in pindexStart) for transactions
genesis 572 // from or to us. If fUpdate is true, found transactions that already
genesis 573 // exist in the wallet will be updated.
genesis 574 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
genesis 575 {
genesis 576 int ret = 0;
genesis 577
genesis 578 CBlockIndex* pindex = pindexStart;
genesis 579 CRITICAL_BLOCK(cs_wallet)
genesis 580 {
genesis 581 while (pindex)
genesis 582 {
genesis 583 CBlock block;
genesis 584 block.ReadFromDisk(pindex, true);
genesis 585 BOOST_FOREACH(CTransaction& tx, block.vtx)
genesis 586 {
genesis 587 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
genesis 588 ret++;
genesis 589 }
genesis 590 pindex = pindex->pnext;
genesis 591 }
genesis 592 }
genesis 593 return ret;
genesis 594 }
genesis 595
genesis 596 void CWallet::ReacceptWalletTransactions()
genesis 597 {
genesis 598 CTxDB txdb("r");
genesis 599 bool fRepeat = true;
genesis 600 while (fRepeat) CRITICAL_BLOCK(cs_wallet)
genesis 601 {
genesis 602 fRepeat = false;
genesis 603 vector<CDiskTxPos> vMissingTx;
genesis 604 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
genesis 605 {
genesis 606 CWalletTx& wtx = item.second;
genesis 607 if (wtx.IsCoinBase() && wtx.IsSpent(0))
genesis 608 continue;
genesis 609
genesis 610 CTxIndex txindex;
genesis 611 bool fUpdated = false;
genesis 612 if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
genesis 613 {
genesis 614 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
genesis 615 if (txindex.vSpent.size() != wtx.vout.size())
genesis 616 {
genesis 617 printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
genesis 618 continue;
genesis 619 }
genesis 620 for (int i = 0; i < txindex.vSpent.size(); i++)
genesis 621 {
genesis 622 if (wtx.IsSpent(i))
genesis 623 continue;
genesis 624 if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
genesis 625 {
genesis 626 wtx.MarkSpent(i);
genesis 627 fUpdated = true;
genesis 628 vMissingTx.push_back(txindex.vSpent[i]);
genesis 629 }
genesis 630 }
genesis 631 if (fUpdated)
genesis 632 {
genesis 633 printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
genesis 634 wtx.MarkDirty();
genesis 635 wtx.WriteToDisk();
genesis 636 }
genesis 637 }
genesis 638 else
genesis 639 {
genesis 640 // Reaccept any txes of ours that aren't already in a block
genesis 641 if (!wtx.IsCoinBase())
genesis 642 wtx.AcceptWalletTransaction(txdb, false);
genesis 643 }
genesis 644 }
genesis 645 if (!vMissingTx.empty())
genesis 646 {
genesis 647 // TODO: optimize this to scan just part of the block chain?
genesis 648 if (ScanForWalletTransactions(pindexGenesisBlock))
genesis 649 fRepeat = true; // Found missing transactions: re-do Reaccept.
genesis 650 }
genesis 651 }
genesis 652 }
genesis 653
genesis 654 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
genesis 655 {
genesis 656 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
genesis 657 {
genesis 658 if (!tx.IsCoinBase())
genesis 659 {
genesis 660 uint256 hash = tx.GetHash();
genesis 661 if (!txdb.ContainsTx(hash))
genesis 662 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
genesis 663 }
genesis 664 }
genesis 665 if (!IsCoinBase())
genesis 666 {
genesis 667 uint256 hash = GetHash();
genesis 668 if (!txdb.ContainsTx(hash))
genesis 669 {
mod6_excise_hash_... 670 printf("Relaying wtx %s\n", hash.ToString().c_str());
genesis 671 RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
genesis 672 }
genesis 673 }
genesis 674 }
genesis 675
genesis 676 void CWalletTx::RelayWalletTransaction()
genesis 677 {
genesis 678 CTxDB txdb("r");
genesis 679 RelayWalletTransaction(txdb);
genesis 680 }
genesis 681
genesis 682 void CWallet::ResendWalletTransactions()
genesis 683 {
genesis 684 // Do this infrequently and randomly to avoid giving away
genesis 685 // that these are our transactions.
genesis 686 static int64 nNextTime;
genesis 687 if (GetTime() < nNextTime)
genesis 688 return;
genesis 689 bool fFirst = (nNextTime == 0);
genesis 690 nNextTime = GetTime() + GetRand(30 * 60);
genesis 691 if (fFirst)
genesis 692 return;
genesis 693
genesis 694 // Only do it if there's been a new block since last time
genesis 695 static int64 nLastTime;
genesis 696 if (nTimeBestReceived < nLastTime)
genesis 697 return;
genesis 698 nLastTime = GetTime();
genesis 699
genesis 700 // Rebroadcast any of our txes that aren't in a block yet
genesis 701 printf("ResendWalletTransactions()\n");
genesis 702 CTxDB txdb("r");
genesis 703 CRITICAL_BLOCK(cs_wallet)
genesis 704 {
genesis 705 // Sort them in chronological order
genesis 706 multimap<unsigned int, CWalletTx*> mapSorted;
genesis 707 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
genesis 708 {
genesis 709 CWalletTx& wtx = item.second;
genesis 710 // Don't rebroadcast until it's had plenty of time that
genesis 711 // it should have gotten in already by now.
genesis 712 if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
genesis 713 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
genesis 714 }
genesis 715 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
genesis 716 {
genesis 717 CWalletTx& wtx = *item.second;
genesis 718 wtx.RelayWalletTransaction(txdb);
genesis 719 }
genesis 720 }
genesis 721 }
genesis 722
genesis 723
genesis 724
genesis 725
genesis 726
genesis 727
genesis 728 //////////////////////////////////////////////////////////////////////////////
genesis 729 //
genesis 730 // Actions
genesis 731 //
genesis 732
genesis 733
genesis 734 int64 CWallet::GetBalance() const
genesis 735 {
genesis 736 int64 nTotal = 0;
genesis 737 CRITICAL_BLOCK(cs_wallet)
genesis 738 {
genesis 739 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 740 {
genesis 741 const CWalletTx* pcoin = &(*it).second;
genesis 742 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 743 continue;
genesis 744 nTotal += pcoin->GetAvailableCredit();
genesis 745 }
genesis 746 }
genesis 747
genesis 748 return nTotal;
genesis 749 }
genesis 750
genesis 751 int64 CWallet::GetUnconfirmedBalance() const
genesis 752 {
genesis 753 int64 nTotal = 0;
genesis 754 CRITICAL_BLOCK(cs_wallet)
genesis 755 {
genesis 756 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 757 {
genesis 758 const CWalletTx* pcoin = &(*it).second;
genesis 759 if (pcoin->IsFinal() && pcoin->IsConfirmed())
genesis 760 continue;
genesis 761 nTotal += pcoin->GetAvailableCredit();
genesis 762 }
genesis 763 }
genesis 764 return nTotal;
genesis 765 }
genesis 766
genesis 767 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 768 {
genesis 769 setCoinsRet.clear();
genesis 770 nValueRet = 0;
genesis 771
genesis 772 // List of values less than target
genesis 773 pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
genesis 774 coinLowestLarger.first = INT64_MAX;
genesis 775 coinLowestLarger.second.first = NULL;
genesis 776 vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
genesis 777 int64 nTotalLower = 0;
genesis 778
genesis 779 CRITICAL_BLOCK(cs_wallet)
genesis 780 {
genesis 781 vector<const CWalletTx*> vCoins;
genesis 782 vCoins.reserve(mapWallet.size());
genesis 783 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
genesis 784 vCoins.push_back(&(*it).second);
genesis 785 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
genesis 786
genesis 787 BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
genesis 788 {
genesis 789 if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
genesis 790 continue;
genesis 791
genesis 792 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
genesis 793 continue;
genesis 794
genesis 795 int nDepth = pcoin->GetDepthInMainChain();
genesis 796 if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
genesis 797 continue;
genesis 798
genesis 799 for (int i = 0; i < pcoin->vout.size(); i++)
genesis 800 {
genesis 801 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
genesis 802 continue;
genesis 803
genesis 804 int64 n = pcoin->vout[i].nValue;
genesis 805
genesis 806 if (n <= 0)
genesis 807 continue;
genesis 808
genesis 809 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
genesis 810
genesis 811 if (n == nTargetValue)
genesis 812 {
genesis 813 setCoinsRet.insert(coin.second);
genesis 814 nValueRet += coin.first;
genesis 815 return true;
genesis 816 }
genesis 817 else if (n < nTargetValue + CENT)
genesis 818 {
genesis 819 vValue.push_back(coin);
genesis 820 nTotalLower += n;
genesis 821 }
genesis 822 else if (n < coinLowestLarger.first)
genesis 823 {
genesis 824 coinLowestLarger = coin;
genesis 825 }
genesis 826 }
genesis 827 }
genesis 828 }
genesis 829
genesis 830 if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
genesis 831 {
genesis 832 for (int i = 0; i < vValue.size(); ++i)
genesis 833 {
genesis 834 setCoinsRet.insert(vValue[i].second);
genesis 835 nValueRet += vValue[i].first;
genesis 836 }
genesis 837 return true;
genesis 838 }
genesis 839
genesis 840 if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
genesis 841 {
genesis 842 if (coinLowestLarger.second.first == NULL)
genesis 843 return false;
genesis 844 setCoinsRet.insert(coinLowestLarger.second);
genesis 845 nValueRet += coinLowestLarger.first;
genesis 846 return true;
genesis 847 }
genesis 848
genesis 849 if (nTotalLower >= nTargetValue + CENT)
genesis 850 nTargetValue += CENT;
genesis 851
genesis 852 // Solve subset sum by stochastic approximation
genesis 853 sort(vValue.rbegin(), vValue.rend());
genesis 854 vector<char> vfIncluded;
genesis 855 vector<char> vfBest(vValue.size(), true);
genesis 856 int64 nBest = nTotalLower;
genesis 857
genesis 858 for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
genesis 859 {
genesis 860 vfIncluded.assign(vValue.size(), false);
genesis 861 int64 nTotal = 0;
genesis 862 bool fReachedTarget = false;
genesis 863 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
genesis 864 {
genesis 865 for (int i = 0; i < vValue.size(); i++)
genesis 866 {
genesis 867 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
genesis 868 {
genesis 869 nTotal += vValue[i].first;
genesis 870 vfIncluded[i] = true;
genesis 871 if (nTotal >= nTargetValue)
genesis 872 {
genesis 873 fReachedTarget = true;
genesis 874 if (nTotal < nBest)
genesis 875 {
genesis 876 nBest = nTotal;
genesis 877 vfBest = vfIncluded;
genesis 878 }
genesis 879 nTotal -= vValue[i].first;
genesis 880 vfIncluded[i] = false;
genesis 881 }
genesis 882 }
genesis 883 }
genesis 884 }
genesis 885 }
genesis 886
genesis 887 // If the next larger is still closer, return it
genesis 888 if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
genesis 889 {
genesis 890 setCoinsRet.insert(coinLowestLarger.second);
genesis 891 nValueRet += coinLowestLarger.first;
genesis 892 }
genesis 893 else {
genesis 894 for (int i = 0; i < vValue.size(); i++)
genesis 895 if (vfBest[i])
genesis 896 {
genesis 897 setCoinsRet.insert(vValue[i].second);
genesis 898 nValueRet += vValue[i].first;
genesis 899 }
genesis 900
genesis 901 //// debug print
genesis 902 printf("SelectCoins() best subset: ");
genesis 903 for (int i = 0; i < vValue.size(); i++)
genesis 904 if (vfBest[i])
genesis 905 printf("%s ", FormatMoney(vValue[i].first).c_str());
genesis 906 printf("total %s\n", FormatMoney(nBest).c_str());
genesis 907 }
genesis 908
genesis 909 return true;
genesis 910 }
genesis 911
genesis 912 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
genesis 913 {
genesis 914 return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
genesis 915 SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
genesis 916 SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
genesis 917 }
genesis 918
genesis 919
genesis 920
genesis 921
genesis 922 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 923 {
genesis 924 int64 nValue = 0;
genesis 925 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 926 {
genesis 927 if (nValue < 0)
genesis 928 return false;
genesis 929 nValue += s.second;
genesis 930 }
genesis 931 if (vecSend.empty() || nValue < 0)
genesis 932 return false;
genesis 933
genesis 934 wtxNew.pwallet = this;
genesis 935
genesis 936 CRITICAL_BLOCK(cs_main)
genesis 937 CRITICAL_BLOCK(cs_wallet)
genesis 938 {
genesis 939 // txdb must be opened before the mapWallet lock
genesis 940 CTxDB txdb("r");
genesis 941 {
genesis 942 nFeeRet = nTransactionFee;
genesis 943 loop
genesis 944 {
genesis 945 wtxNew.vin.clear();
genesis 946 wtxNew.vout.clear();
genesis 947 wtxNew.fFromMe = true;
genesis 948
genesis 949 int64 nTotalValue = nValue + nFeeRet;
genesis 950 double dPriority = 0;
genesis 951 // vouts to the payees
genesis 952 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
genesis 953 wtxNew.vout.push_back(CTxOut(s.second, s.first));
genesis 954
genesis 955 // Choose coins to use
genesis 956 set<pair<const CWalletTx*,unsigned int> > setCoins;
genesis 957 int64 nValueIn = 0;
genesis 958 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
genesis 959 return false;
genesis 960 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
genesis 961 {
genesis 962 int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
genesis 963 dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
genesis 964 }
genesis 965
genesis 966 int64 nChange = nValueIn - nValue - nFeeRet;
genesis 967 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
genesis 968 // or until nChange becomes zero
genesis 969 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
genesis 970 {
genesis 971 int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
genesis 972 nChange -= nMoveToFee;
genesis 973 nFeeRet += nMoveToFee;
genesis 974 }
genesis 975
genesis 976 if (nChange > 0)
genesis 977 {
genesis 978 // Note: We use a new key here to keep it from being obvious which side is the change.
genesis 979 // The drawback is that by not reusing a previous key, the change may be lost if a
genesis 980 // backup is restored, if the backup doesn't have the new private key for the change.
genesis 981 // If we reused the old key, it would be possible to add code to look for and
genesis 982 // rediscover unknown transactions that were written with keys of ours to recover
genesis 983 // post-backup change.
genesis 984
genesis 985 // Reserve a new key pair from key pool
genesis 986 vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
genesis 987 // assert(mapKeys.count(vchPubKey));
genesis 988
genesis 989 // Fill a vout to ourself, using same address type as the payment
genesis 990 CScript scriptChange;
genesis 991 if (vecSend[0].first.GetBitcoinAddress().IsValid())
genesis 992 scriptChange.SetBitcoinAddress(vchPubKey);
genesis 993 else
genesis 994 scriptChange << vchPubKey << OP_CHECKSIG;
genesis 995
genesis 996 // Insert change txn at random position:
genesis 997 vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
genesis 998 wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
genesis 999 }
genesis 1000 else
genesis 1001 reservekey.ReturnKey();
genesis 1002
genesis 1003 // Fill vin
genesis 1004 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 1005 wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
genesis 1006
genesis 1007 // Sign
genesis 1008 int nIn = 0;
genesis 1009 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
genesis 1010 if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
genesis 1011 return false;
genesis 1012
genesis 1013 // Limit size
genesis 1014 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
genesis 1015 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
genesis 1016 return false;
genesis 1017 dPriority /= nBytes;
genesis 1018
genesis 1019 // Check that enough fee is included
genesis 1020 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
genesis 1021 bool fAllowFree = CTransaction::AllowFree(dPriority);
genesis 1022 int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
genesis 1023 if (nFeeRet < max(nPayFee, nMinFee))
genesis 1024 {
genesis 1025 nFeeRet = max(nPayFee, nMinFee);
genesis 1026 continue;
genesis 1027 }
genesis 1028
genesis 1029 // Fill vtxPrev by copying from previous transactions vtxPrev
genesis 1030 wtxNew.AddSupportingTransactions(txdb);
genesis 1031 wtxNew.fTimeReceivedIsTxTime = true;
genesis 1032
genesis 1033 break;
genesis 1034 }
genesis 1035 }
genesis 1036 }
genesis 1037 return true;
genesis 1038 }
genesis 1039
genesis 1040 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
genesis 1041 {
genesis 1042 vector< pair<CScript, int64> > vecSend;
genesis 1043 vecSend.push_back(make_pair(scriptPubKey, nValue));
genesis 1044 return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
genesis 1045 }
genesis 1046
genesis 1047 // Call after CreateTransaction unless you want to abort
genesis 1048 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
genesis 1049 {
genesis 1050 CRITICAL_BLOCK(cs_main)
genesis 1051 CRITICAL_BLOCK(cs_wallet)
genesis 1052 {
genesis 1053 printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
genesis 1054 {
genesis 1055 // This is only to keep the database open to defeat the auto-flush for the
genesis 1056 // duration of this scope. This is the only place where this optimization
genesis 1057 // maybe makes sense; please don't do it anywhere else.
genesis 1058 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
genesis 1059
genesis 1060 // Take key pair from key pool so it won't be used again
genesis 1061 reservekey.KeepKey();
genesis 1062
genesis 1063 // Add tx to wallet, because if it has change it's also ours,
genesis 1064 // otherwise just for transaction history.
genesis 1065 AddToWallet(wtxNew);
genesis 1066
genesis 1067 // Mark old coins as spent
genesis 1068 set<CWalletTx*> setCoins;
genesis 1069 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
genesis 1070 {
genesis 1071 CWalletTx &coin = mapWallet[txin.prevout.hash];
genesis 1072 coin.pwallet = this;
genesis 1073 coin.MarkSpent(txin.prevout.n);
genesis 1074 coin.WriteToDisk();
genesis 1075 vWalletUpdated.push_back(coin.GetHash());
genesis 1076 }
genesis 1077
genesis 1078 if (fFileBacked)
genesis 1079 delete pwalletdb;
genesis 1080 }
genesis 1081
genesis 1082 // Track how many getdata requests our transaction gets
genesis 1083 mapRequestCount[wtxNew.GetHash()] = 0;
genesis 1084
genesis 1085 // Broadcast
genesis 1086 if (!wtxNew.AcceptToMemoryPool())
genesis 1087 {
genesis 1088 // This must not fail. The transaction has already been signed and recorded.
genesis 1089 printf("CommitTransaction() : Error: Transaction not valid");
genesis 1090 return false;
genesis 1091 }
genesis 1092 wtxNew.RelayWalletTransaction();
genesis 1093 }
genesis 1094 MainFrameRepaint();
genesis 1095 return true;
genesis 1096 }
genesis 1097
genesis 1098
genesis 1099
genesis 1100
genesis 1101 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1102 {
genesis 1103 CReserveKey reservekey(this);
genesis 1104 int64 nFeeRequired;
genesis 1105
genesis 1106 if (IsLocked())
genesis 1107 {
genesis 1108 string strError = _("Error: Wallet locked, unable to create transaction ");
genesis 1109 printf("SendMoney() : %s", strError.c_str());
genesis 1110 return strError;
genesis 1111 }
genesis 1112 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
genesis 1113 {
genesis 1114 string strError;
genesis 1115 if (nValue + nFeeRequired > GetBalance())
genesis 1116 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());
genesis 1117 else
genesis 1118 strError = _("Error: Transaction creation failed ");
genesis 1119 printf("SendMoney() : %s", strError.c_str());
genesis 1120 return strError;
genesis 1121 }
genesis 1122
genesis 1123 if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
genesis 1124 return "ABORTED";
genesis 1125
genesis 1126 if (!CommitTransaction(wtxNew, reservekey))
genesis 1127 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.");
genesis 1128
genesis 1129 MainFrameRepaint();
genesis 1130 return "";
genesis 1131 }
genesis 1132
genesis 1133
genesis 1134
genesis 1135 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
genesis 1136 {
genesis 1137 // Check amount
genesis 1138 if (nValue <= 0)
genesis 1139 return _("Invalid amount");
genesis 1140 if (nValue + nTransactionFee > GetBalance())
genesis 1141 return _("Insufficient funds");
genesis 1142
genesis 1143 // Parse bitcoin address
genesis 1144 CScript scriptPubKey;
genesis 1145 scriptPubKey.SetBitcoinAddress(address);
genesis 1146
genesis 1147 return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
genesis 1148 }
genesis 1149
genesis 1150
genesis 1151
genesis 1152
genesis 1153 int CWallet::LoadWallet(bool& fFirstRunRet)
genesis 1154 {
genesis 1155 if (!fFileBacked)
genesis 1156 return false;
genesis 1157 fFirstRunRet = false;
genesis 1158 int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
genesis 1159 if (nLoadWalletRet == DB_NEED_REWRITE)
genesis 1160 {
genesis 1161 if (CDB::Rewrite(strWalletFile, "\x04pool"))
genesis 1162 {
genesis 1163 setKeyPool.clear();
genesis 1164 // Note: can't top-up keypool here, because wallet is locked.
genesis 1165 // User will be prompted to unlock wallet the next operation
genesis 1166 // the requires a new key.
genesis 1167 }
genesis 1168 nLoadWalletRet = DB_NEED_REWRITE;
genesis 1169 }
genesis 1170
genesis 1171 if (nLoadWalletRet != DB_LOAD_OK)
genesis 1172 return nLoadWalletRet;
genesis 1173 fFirstRunRet = vchDefaultKey.empty();
genesis 1174
genesis 1175 if (!HaveKey(Hash160(vchDefaultKey)))
genesis 1176 {
genesis 1177 // Create new keyUser and set as default key
genesis 1178 RandAddSeedPerfmon();
genesis 1179
genesis 1180 std::vector<unsigned char> newDefaultKey;
genesis 1181 if (!GetKeyFromPool(newDefaultKey, false))
genesis 1182 return DB_LOAD_FAIL;
genesis 1183 SetDefaultKey(newDefaultKey);
genesis 1184 if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
genesis 1185 return DB_LOAD_FAIL;
genesis 1186 }
genesis 1187
genesis 1188 CreateThread(ThreadFlushWalletDB, &strWalletFile);
genesis 1189 return DB_LOAD_OK;
genesis 1190 }
genesis 1191
genesis 1192
genesis 1193 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
genesis 1194 {
genesis 1195 mapAddressBook[address] = strName;
genesis 1196 if (!fFileBacked)
genesis 1197 return false;
genesis 1198 return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
genesis 1199 }
genesis 1200
genesis 1201 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
genesis 1202 {
genesis 1203 mapAddressBook.erase(address);
genesis 1204 if (!fFileBacked)
genesis 1205 return false;
genesis 1206 return CWalletDB(strWalletFile).EraseName(address.ToString());
genesis 1207 }
genesis 1208
genesis 1209
genesis 1210 void CWallet::PrintWallet(const CBlock& block)
genesis 1211 {
genesis 1212 CRITICAL_BLOCK(cs_wallet)
genesis 1213 {
genesis 1214 if (mapWallet.count(block.vtx[0].GetHash()))
genesis 1215 {
genesis 1216 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
genesis 1217 printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
genesis 1218 }
genesis 1219 }
genesis 1220 printf("\n");
genesis 1221 }
genesis 1222
genesis 1223 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
genesis 1224 {
genesis 1225 CRITICAL_BLOCK(cs_wallet)
genesis 1226 {
genesis 1227 map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
genesis 1228 if (mi != mapWallet.end())
genesis 1229 {
genesis 1230 wtx = (*mi).second;
genesis 1231 return true;
genesis 1232 }
genesis 1233 }
genesis 1234 return false;
genesis 1235 }
genesis 1236
genesis 1237 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
genesis 1238 {
genesis 1239 if (fFileBacked)
genesis 1240 {
genesis 1241 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
genesis 1242 return false;
genesis 1243 }
genesis 1244 vchDefaultKey = vchPubKey;
genesis 1245 return true;
genesis 1246 }
genesis 1247
genesis 1248 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
genesis 1249 {
genesis 1250 if (!pwallet->fFileBacked)
genesis 1251 return false;
genesis 1252 strWalletFileOut = pwallet->strWalletFile;
genesis 1253 return true;
genesis 1254 }
genesis 1255
genesis 1256 //
genesis 1257 // Mark old keypool keys as used,
genesis 1258 // and generate all new keys
genesis 1259 //
genesis 1260 bool CWallet::NewKeyPool()
genesis 1261 {
genesis 1262 CRITICAL_BLOCK(cs_wallet)
genesis 1263 {
genesis 1264 CWalletDB walletdb(strWalletFile);
genesis 1265 BOOST_FOREACH(int64 nIndex, setKeyPool)
genesis 1266 walletdb.ErasePool(nIndex);
genesis 1267 setKeyPool.clear();
genesis 1268
genesis 1269 if (IsLocked())
genesis 1270 return false;
genesis 1271
genesis 1272 int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
genesis 1273 for (int i = 0; i < nKeys; i++)
genesis 1274 {
genesis 1275 int64 nIndex = i+1;
genesis 1276 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
genesis 1277 setKeyPool.insert(nIndex);
genesis 1278 }
genesis 1279 printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
genesis 1280 }
genesis 1281 return true;
genesis 1282 }
genesis 1283
genesis 1284 bool CWallet::TopUpKeyPool()
genesis 1285 {
genesis 1286 CRITICAL_BLOCK(cs_wallet)
genesis 1287 {
genesis 1288 if (IsLocked())
genesis 1289 return false;
genesis 1290
genesis 1291 CWalletDB walletdb(strWalletFile);
genesis 1292
genesis 1293 // Top up key pool
genesis 1294 int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
genesis 1295 while (setKeyPool.size() < nTargetSize+1)
genesis 1296 {
genesis 1297 int64 nEnd = 1;
genesis 1298 if (!setKeyPool.empty())
genesis 1299 nEnd = *(--setKeyPool.end()) + 1;
genesis 1300 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
genesis 1301 throw runtime_error("TopUpKeyPool() : writing generated key failed");
genesis 1302 setKeyPool.insert(nEnd);
genesis 1303 printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
genesis 1304 }
genesis 1305 }
genesis 1306 return true;
genesis 1307 }
genesis 1308
genesis 1309 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
genesis 1310 {
genesis 1311 nIndex = -1;
genesis 1312 keypool.vchPubKey.clear();
genesis 1313 CRITICAL_BLOCK(cs_wallet)
genesis 1314 {
genesis 1315 if (!IsLocked())
genesis 1316 TopUpKeyPool();
genesis 1317
genesis 1318 // Get the oldest key
genesis 1319 if(setKeyPool.empty())
genesis 1320 return;
genesis 1321
genesis 1322 CWalletDB walletdb(strWalletFile);
genesis 1323
genesis 1324 nIndex = *(setKeyPool.begin());
genesis 1325 setKeyPool.erase(setKeyPool.begin());
genesis 1326 if (!walletdb.ReadPool(nIndex, keypool))
genesis 1327 throw runtime_error("ReserveKeyFromKeyPool() : read failed");
genesis 1328 if (!HaveKey(Hash160(keypool.vchPubKey)))
genesis 1329 throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
genesis 1330 assert(!keypool.vchPubKey.empty());
genesis 1331 printf("keypool reserve %"PRI64d"\n", nIndex);
genesis 1332 }
genesis 1333 }
genesis 1334
genesis 1335 void CWallet::KeepKey(int64 nIndex)
genesis 1336 {
genesis 1337 // Remove from key pool
genesis 1338 if (fFileBacked)
genesis 1339 {
genesis 1340 CWalletDB walletdb(strWalletFile);
genesis 1341 walletdb.ErasePool(nIndex);
genesis 1342 }
genesis 1343 printf("keypool keep %"PRI64d"\n", nIndex);
genesis 1344 }
genesis 1345
genesis 1346 void CWallet::ReturnKey(int64 nIndex)
genesis 1347 {
genesis 1348 // Return to key pool
genesis 1349 CRITICAL_BLOCK(cs_wallet)
genesis 1350 setKeyPool.insert(nIndex);
genesis 1351 printf("keypool return %"PRI64d"\n", nIndex);
genesis 1352 }
genesis 1353
genesis 1354 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
genesis 1355 {
genesis 1356 int64 nIndex = 0;
genesis 1357 CKeyPool keypool;
genesis 1358 CRITICAL_BLOCK(cs_wallet)
genesis 1359 {
genesis 1360 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1361 if (nIndex == -1)
genesis 1362 {
genesis 1363 if (fAllowReuse && !vchDefaultKey.empty())
genesis 1364 {
genesis 1365 result = vchDefaultKey;
genesis 1366 return true;
genesis 1367 }
genesis 1368 if (IsLocked()) return false;
genesis 1369 result = GenerateNewKey();
genesis 1370 return true;
genesis 1371 }
genesis 1372 KeepKey(nIndex);
genesis 1373 result = keypool.vchPubKey;
genesis 1374 }
genesis 1375 return true;
genesis 1376 }
genesis 1377
genesis 1378 int64 CWallet::GetOldestKeyPoolTime()
genesis 1379 {
genesis 1380 int64 nIndex = 0;
genesis 1381 CKeyPool keypool;
genesis 1382 ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1383 if (nIndex == -1)
genesis 1384 return GetTime();
genesis 1385 ReturnKey(nIndex);
genesis 1386 return keypool.nTime;
genesis 1387 }
genesis 1388
genesis 1389 vector<unsigned char> CReserveKey::GetReservedKey()
genesis 1390 {
genesis 1391 if (nIndex == -1)
genesis 1392 {
genesis 1393 CKeyPool keypool;
genesis 1394 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
genesis 1395 if (nIndex != -1)
genesis 1396 vchPubKey = keypool.vchPubKey;
genesis 1397 else
genesis 1398 {
genesis 1399 printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
genesis 1400 vchPubKey = pwallet->vchDefaultKey;
genesis 1401 }
genesis 1402 }
genesis 1403 assert(!vchPubKey.empty());
genesis 1404 return vchPubKey;
genesis 1405 }
genesis 1406
genesis 1407 void CReserveKey::KeepKey()
genesis 1408 {
genesis 1409 if (nIndex != -1)
genesis 1410 pwallet->KeepKey(nIndex);
genesis 1411 nIndex = -1;
genesis 1412 vchPubKey.clear();
genesis 1413 }
genesis 1414
genesis 1415 void CReserveKey::ReturnKey()
genesis 1416 {
genesis 1417 if (nIndex != -1)
genesis 1418 pwallet->ReturnKey(nIndex);
genesis 1419 nIndex = -1;
genesis 1420 vchPubKey.clear();
genesis 1421 }
genesis 1422