File indexing completed on 2020-06-25 15:51:20
0001
0002
0003
0004
0005 #ifndef BITCOIN_WALLET_H
0006 #define BITCOIN_WALLET_H
0007
0008 #include "bignum.h"
0009 #include "key.h"
0010 #include "script.h"
0011
0012 class CWalletTx;
0013 class CReserveKey;
0014 class CWalletDB;
0015
0016
0017
0018
0019 class CWallet : public CCryptoKeyStore
0020 {
0021 private:
0022 bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
0023 bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
0024
0025 CWalletDB *pwalletdbEncryption;
0026
0027 public:
0028 mutable CCriticalSection cs_wallet;
0029
0030 bool fFileBacked;
0031 std::string strWalletFile;
0032
0033 std::set<int64> setKeyPool;
0034
0035 typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
0036 MasterKeyMap mapMasterKeys;
0037 unsigned int nMasterKeyMaxID;
0038
0039 CWallet()
0040 {
0041 fFileBacked = false;
0042 nMasterKeyMaxID = 0;
0043 pwalletdbEncryption = NULL;
0044 }
0045 CWallet(std::string strWalletFileIn)
0046 {
0047 strWalletFile = strWalletFileIn;
0048 fFileBacked = true;
0049 nMasterKeyMaxID = 0;
0050 pwalletdbEncryption = NULL;
0051 }
0052
0053 std::map<uint256, CWalletTx> mapWallet;
0054 std::vector<uint256> vWalletUpdated;
0055
0056 std::map<uint256, int> mapRequestCount;
0057
0058 std::map<CBitcoinAddress, std::string> mapAddressBook;
0059
0060 std::vector<unsigned char> vchDefaultKey;
0061
0062
0063
0064 bool AddKey(const CKey& key);
0065
0066 bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
0067
0068
0069 bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
0070
0071 bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
0072
0073 bool Unlock(const SecureString& strWalletPassphrase);
0074 bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
0075 bool EncryptWallet(const SecureString& strWalletPassphrase);
0076
0077 bool AddToWallet(const CWalletTx& wtxIn);
0078 bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
0079 bool EraseFromWallet(uint256 hash);
0080 void WalletUpdateSpent(const CTransaction& prevout);
0081 int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
0082 void ReacceptWalletTransactions();
0083 void ResendWalletTransactions();
0084 int64 GetBalance() const;
0085 int64 GetUnconfirmedBalance() const;
0086 bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
0087 bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
0088 bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
0089 std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
0090 std::string SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
0091
0092 bool NewKeyPool();
0093 bool TopUpKeyPool();
0094 void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
0095 void KeepKey(int64 nIndex);
0096 void ReturnKey(int64 nIndex);
0097 bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true);
0098 int64 GetOldestKeyPoolTime();
0099
0100 bool IsMine(const CTxIn& txin) const;
0101 int64 GetDebit(const CTxIn& txin) const;
0102 bool IsMine(const CTxOut& txout) const
0103 {
0104 return ::IsMine(*this, txout.scriptPubKey);
0105 }
0106 int64 GetCredit(const CTxOut& txout) const
0107 {
0108 if (!MoneyRange(txout.nValue))
0109 throw std::runtime_error("CWallet::GetCredit() : value out of range");
0110 return (IsMine(txout) ? txout.nValue : 0);
0111 }
0112 bool IsChange(const CTxOut& txout) const
0113 {
0114 CBitcoinAddress address;
0115 if (ExtractAddress(txout.scriptPubKey, this, address))
0116 CRITICAL_BLOCK(cs_wallet)
0117 if (!mapAddressBook.count(address))
0118 return true;
0119 return false;
0120 }
0121 int64 GetChange(const CTxOut& txout) const
0122 {
0123 if (!MoneyRange(txout.nValue))
0124 throw std::runtime_error("CWallet::GetChange() : value out of range");
0125 return (IsChange(txout) ? txout.nValue : 0);
0126 }
0127 bool IsMine(const CTransaction& tx) const
0128 {
0129 BOOST_FOREACH(const CTxOut& txout, tx.vout)
0130 if (IsMine(txout))
0131 return true;
0132 return false;
0133 }
0134 bool IsFromMe(const CTransaction& tx) const
0135 {
0136 return (GetDebit(tx) > 0);
0137 }
0138 int64 GetDebit(const CTransaction& tx) const
0139 {
0140 int64 nDebit = 0;
0141 BOOST_FOREACH(const CTxIn& txin, tx.vin)
0142 {
0143 nDebit += GetDebit(txin);
0144 if (!MoneyRange(nDebit))
0145 throw std::runtime_error("CWallet::GetDebit() : value out of range");
0146 }
0147 return nDebit;
0148 }
0149 int64 GetCredit(const CTransaction& tx) const
0150 {
0151 int64 nCredit = 0;
0152 BOOST_FOREACH(const CTxOut& txout, tx.vout)
0153 {
0154 nCredit += GetCredit(txout);
0155 if (!MoneyRange(nCredit))
0156 throw std::runtime_error("CWallet::GetCredit() : value out of range");
0157 }
0158 return nCredit;
0159 }
0160 int64 GetChange(const CTransaction& tx) const
0161 {
0162 int64 nChange = 0;
0163 BOOST_FOREACH(const CTxOut& txout, tx.vout)
0164 {
0165 nChange += GetChange(txout);
0166 if (!MoneyRange(nChange))
0167 throw std::runtime_error("CWallet::GetChange() : value out of range");
0168 }
0169 return nChange;
0170 }
0171 void SetBestChain(const CBlockLocator& loc)
0172 {
0173 CWalletDB walletdb(strWalletFile);
0174 walletdb.WriteBestBlock(loc);
0175 }
0176
0177 int LoadWallet(bool& fFirstRunRet);
0178
0179
0180 bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName);
0181
0182 bool DelAddressBookName(const CBitcoinAddress& address);
0183
0184 void UpdatedTransaction(const uint256 &hashTx)
0185 {
0186 CRITICAL_BLOCK(cs_wallet)
0187 vWalletUpdated.push_back(hashTx);
0188 }
0189
0190 void PrintWallet(const CBlock& block);
0191
0192 void Inventory(const uint256 &hash)
0193 {
0194 CRITICAL_BLOCK(cs_wallet)
0195 {
0196 std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
0197 if (mi != mapRequestCount.end())
0198 (*mi).second++;
0199 }
0200 }
0201
0202 int GetKeyPoolSize()
0203 {
0204 return setKeyPool.size();
0205 }
0206
0207 bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
0208
0209 bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
0210 };
0211
0212
0213 class CReserveKey
0214 {
0215 protected:
0216 CWallet* pwallet;
0217 int64 nIndex;
0218 std::vector<unsigned char> vchPubKey;
0219 public:
0220 CReserveKey(CWallet* pwalletIn)
0221 {
0222 nIndex = -1;
0223 pwallet = pwalletIn;
0224 }
0225
0226 ~CReserveKey()
0227 {
0228 if (!fShutdown)
0229 ReturnKey();
0230 }
0231
0232 void ReturnKey();
0233 std::vector<unsigned char> GetReservedKey();
0234 void KeepKey();
0235 };
0236
0237
0238
0239
0240
0241
0242
0243 class CWalletTx : public CMerkleTx
0244 {
0245 public:
0246 const CWallet* pwallet;
0247
0248 std::vector<CMerkleTx> vtxPrev;
0249 std::map<std::string, std::string> mapValue;
0250 std::vector<std::pair<std::string, std::string> > vOrderForm;
0251 unsigned int fTimeReceivedIsTxTime;
0252 unsigned int nTimeReceived;
0253 char fFromMe;
0254 std::string strFromAccount;
0255 std::vector<char> vfSpent;
0256
0257
0258 mutable char fDebitCached;
0259 mutable char fCreditCached;
0260 mutable char fAvailableCreditCached;
0261 mutable char fChangeCached;
0262 mutable int64 nDebitCached;
0263 mutable int64 nCreditCached;
0264 mutable int64 nAvailableCreditCached;
0265 mutable int64 nChangeCached;
0266
0267
0268 mutable unsigned int nTimeDisplayed;
0269 mutable int nLinesDisplayed;
0270 mutable char fConfirmedDisplayed;
0271
0272 CWalletTx()
0273 {
0274 Init(NULL);
0275 }
0276
0277 CWalletTx(const CWallet* pwalletIn)
0278 {
0279 Init(pwalletIn);
0280 }
0281
0282 CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
0283 {
0284 Init(pwalletIn);
0285 }
0286
0287 CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
0288 {
0289 Init(pwalletIn);
0290 }
0291
0292 void Init(const CWallet* pwalletIn)
0293 {
0294 pwallet = pwalletIn;
0295 vtxPrev.clear();
0296 mapValue.clear();
0297 vOrderForm.clear();
0298 fTimeReceivedIsTxTime = false;
0299 nTimeReceived = 0;
0300 fFromMe = false;
0301 strFromAccount.clear();
0302 vfSpent.clear();
0303 fDebitCached = false;
0304 fCreditCached = false;
0305 fAvailableCreditCached = false;
0306 fChangeCached = false;
0307 nDebitCached = 0;
0308 nCreditCached = 0;
0309 nAvailableCreditCached = 0;
0310 nChangeCached = 0;
0311 nTimeDisplayed = 0;
0312 nLinesDisplayed = 0;
0313 fConfirmedDisplayed = false;
0314 }
0315
0316 IMPLEMENT_SERIALIZE
0317 (
0318 CWalletTx* pthis = const_cast<CWalletTx*>(this);
0319 if (fRead)
0320 pthis->Init(NULL);
0321 char fSpent = false;
0322
0323 if (!fRead)
0324 {
0325 pthis->mapValue["fromaccount"] = pthis->strFromAccount;
0326
0327 std::string str;
0328 BOOST_FOREACH(char f, vfSpent)
0329 {
0330 str += (f ? '1' : '0');
0331 if (f)
0332 fSpent = true;
0333 }
0334 pthis->mapValue["spent"] = str;
0335 }
0336
0337 nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
0338 READWRITE(vtxPrev);
0339 READWRITE(mapValue);
0340 READWRITE(vOrderForm);
0341 READWRITE(fTimeReceivedIsTxTime);
0342 READWRITE(nTimeReceived);
0343 READWRITE(fFromMe);
0344 READWRITE(fSpent);
0345
0346 if (fRead)
0347 {
0348 pthis->strFromAccount = pthis->mapValue["fromaccount"];
0349
0350 if (mapValue.count("spent"))
0351 BOOST_FOREACH(char c, pthis->mapValue["spent"])
0352 pthis->vfSpent.push_back(c != '0');
0353 else
0354 pthis->vfSpent.assign(vout.size(), fSpent);
0355 }
0356
0357 pthis->mapValue.erase("fromaccount");
0358 pthis->mapValue.erase("version");
0359 pthis->mapValue.erase("spent");
0360 )
0361
0362
0363
0364 bool UpdateSpent(const std::vector<char>& vfNewSpent)
0365 {
0366 bool fReturn = false;
0367 for (int i=0; i < vfNewSpent.size(); i++)
0368 {
0369 if (i == vfSpent.size())
0370 break;
0371
0372 if (vfNewSpent[i] && !vfSpent[i])
0373 {
0374 vfSpent[i] = true;
0375 fReturn = true;
0376 fAvailableCreditCached = false;
0377 }
0378 }
0379 return fReturn;
0380 }
0381
0382
0383 void MarkDirty()
0384 {
0385 fCreditCached = false;
0386 fAvailableCreditCached = false;
0387 fDebitCached = false;
0388 fChangeCached = false;
0389 }
0390
0391 void MarkSpent(unsigned int nOut)
0392 {
0393 if (nOut >= vout.size())
0394 throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
0395 vfSpent.resize(vout.size());
0396 if (!vfSpent[nOut])
0397 {
0398 vfSpent[nOut] = true;
0399 fAvailableCreditCached = false;
0400 }
0401 }
0402
0403 bool IsSpent(unsigned int nOut) const
0404 {
0405 if (nOut >= vout.size())
0406 throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
0407 if (nOut >= vfSpent.size())
0408 return false;
0409 return (!!vfSpent[nOut]);
0410 }
0411
0412 int64 GetDebit() const
0413 {
0414 if (vin.empty())
0415 return 0;
0416 if (fDebitCached)
0417 return nDebitCached;
0418 nDebitCached = pwallet->GetDebit(*this);
0419 fDebitCached = true;
0420 return nDebitCached;
0421 }
0422
0423 int64 GetCredit(bool fUseCache=true) const
0424 {
0425
0426 if (IsCoinBase() && GetBlocksToMaturity() > 0)
0427 return 0;
0428
0429
0430 if (fUseCache && fCreditCached)
0431 return nCreditCached;
0432 nCreditCached = pwallet->GetCredit(*this);
0433 fCreditCached = true;
0434 return nCreditCached;
0435 }
0436
0437 int64 GetAvailableCredit(bool fUseCache=true) const
0438 {
0439
0440 if (IsCoinBase() && GetBlocksToMaturity() > 0)
0441 return 0;
0442
0443 if (fUseCache && fAvailableCreditCached)
0444 return nAvailableCreditCached;
0445
0446 int64 nCredit = 0;
0447 for (int i = 0; i < vout.size(); i++)
0448 {
0449 if (!IsSpent(i))
0450 {
0451 const CTxOut &txout = vout[i];
0452 nCredit += pwallet->GetCredit(txout);
0453 if (!MoneyRange(nCredit))
0454 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
0455 }
0456 }
0457
0458 nAvailableCreditCached = nCredit;
0459 fAvailableCreditCached = true;
0460 return nCredit;
0461 }
0462
0463
0464 int64 GetChange() const
0465 {
0466 if (fChangeCached)
0467 return nChangeCached;
0468 nChangeCached = pwallet->GetChange(*this);
0469 fChangeCached = true;
0470 return nChangeCached;
0471 }
0472
0473 void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<CBitcoinAddress, int64> >& listReceived,
0474 std::list<std::pair<CBitcoinAddress, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
0475
0476 void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived,
0477 int64& nSent, int64& nFee) const;
0478
0479 bool IsFromMe() const
0480 {
0481 return (GetDebit() > 0);
0482 }
0483
0484 bool IsConfirmed() const
0485 {
0486
0487 if (!IsFinal())
0488 return false;
0489 if (GetDepthInMainChain() >= 1)
0490 return true;
0491 if (!IsFromMe())
0492 return false;
0493
0494
0495
0496 std::map<uint256, const CMerkleTx*> mapPrev;
0497 std::vector<const CMerkleTx*> vWorkQueue;
0498 vWorkQueue.reserve(vtxPrev.size()+1);
0499 vWorkQueue.push_back(this);
0500 for (int i = 0; i < vWorkQueue.size(); i++)
0501 {
0502 const CMerkleTx* ptx = vWorkQueue[i];
0503
0504 if (!ptx->IsFinal())
0505 return false;
0506 if (ptx->GetDepthInMainChain() >= 1)
0507 continue;
0508 if (!pwallet->IsFromMe(*ptx))
0509 return false;
0510
0511 if (mapPrev.empty())
0512 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
0513 mapPrev[tx.GetHash()] = &tx;
0514
0515 BOOST_FOREACH(const CTxIn& txin, ptx->vin)
0516 {
0517 if (!mapPrev.count(txin.prevout.hash))
0518 return false;
0519 vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
0520 }
0521 }
0522 return true;
0523 }
0524
0525 bool WriteToDisk();
0526
0527 int64 GetTxTime() const;
0528 int GetRequestCount() const;
0529
0530 void AddSupportingTransactions(CTxDB& txdb);
0531
0532 bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
0533 bool AcceptWalletTransaction();
0534
0535 void RelayWalletTransaction(CTxDB& txdb);
0536 void RelayWalletTransaction();
0537 };
0538
0539
0540
0541
0542
0543 class CWalletKey
0544 {
0545 public:
0546 CPrivKey vchPrivKey;
0547 int64 nTimeCreated;
0548 int64 nTimeExpires;
0549 std::string strComment;
0550
0551
0552
0553 CWalletKey(int64 nExpires=0)
0554 {
0555 nTimeCreated = (nExpires ? GetTime() : 0);
0556 nTimeExpires = nExpires;
0557 }
0558
0559 IMPLEMENT_SERIALIZE
0560 (
0561 if (!(nType & SER_GETHASH))
0562 READWRITE(nVersion);
0563 READWRITE(vchPrivKey);
0564 READWRITE(nTimeCreated);
0565 READWRITE(nTimeExpires);
0566 READWRITE(strComment);
0567 )
0568 };
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579 class CAccount
0580 {
0581 public:
0582 std::vector<unsigned char> vchPubKey;
0583
0584 CAccount()
0585 {
0586 SetNull();
0587 }
0588
0589 void SetNull()
0590 {
0591 vchPubKey.clear();
0592 }
0593
0594 IMPLEMENT_SERIALIZE
0595 (
0596 if (!(nType & SER_GETHASH))
0597 READWRITE(nVersion);
0598 READWRITE(vchPubKey);
0599 )
0600 };
0601
0602
0603
0604
0605
0606
0607
0608 class CAccountingEntry
0609 {
0610 public:
0611 std::string strAccount;
0612 int64 nCreditDebit;
0613 int64 nTime;
0614 std::string strOtherAccount;
0615 std::string strComment;
0616
0617 CAccountingEntry()
0618 {
0619 SetNull();
0620 }
0621
0622 void SetNull()
0623 {
0624 nCreditDebit = 0;
0625 nTime = 0;
0626 strAccount.clear();
0627 strOtherAccount.clear();
0628 strComment.clear();
0629 }
0630
0631 IMPLEMENT_SERIALIZE
0632 (
0633 if (!(nType & SER_GETHASH))
0634 READWRITE(nVersion);
0635
0636 READWRITE(nCreditDebit);
0637 READWRITE(nTime);
0638 READWRITE(strOtherAccount);
0639 READWRITE(strComment);
0640 )
0641 };
0642
0643 bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
0644
0645 #endif