From 64c7ee7e6b9c059d99aaa493c74a6703c6b0fc80 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 1 Jun 2011 18:28:20 +0200 Subject: CWallet class * A new class CKeyStore manages private keys, and script.cpp depends on access to CKeyStore. * A new class CWallet extends CKeyStore, and contains all former wallet-specific globals; CWallet depends on script.cpp, not the other way around. * Wallet-specific functions in CTransaction/CTxIn/CTxOut (GetDebit, GetCredit, GetChange, IsMine, IsFromMe), are moved to CWallet, taking their former 'this' argument as an explicit parameter * CWalletTx objects know which CWallet they belong to, for convenience, so they have their own direct (and caching) GetDebit/... functions. * Some code was moved from CWalletDB to CWallet, such as handling of reserve keys. * Main.cpp keeps a set of all 'registered' wallets, which should be informed about updates to the block chain, and does not have any notion about any 'main' wallet. Function in main.cpp that require a wallet (such as GenerateCoins), take an explicit CWallet* argument. * The actual CWallet instance used by the application is defined in init.cpp as "CWallet* pwalletMain". rpc.cpp and ui.cpp use this variable. * Functions in main.cpp and db.cpp that are not used by other modules are marked static. * The code for handling the 'submitorder' message is removed, as it not really compatible with the idea that a node is independent from the wallet(s) connected to it, and obsolete anyway. --- src/wallet.h | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 211 insertions(+), 37 deletions(-) (limited to 'src/wallet.h') diff --git a/src/wallet.h b/src/wallet.h index f9d2ea0989..b14a2e8264 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -5,40 +5,205 @@ #define BITCOIN_WALLET_H #include "bignum.h" +#include "key.h" #include "script.h" class CWalletTx; class CReserveKey; class CWalletDB; -extern std::map mapWallet; -extern std::vector vWalletUpdated; -extern CCriticalSection cs_mapWallet; +class CWallet : public CKeyStore +{ +private: + bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::set >& setCoinsRet, int64& nValueRet) const; + bool SelectCoins(int64 nTargetValue, std::set >& setCoinsRet, int64& nValueRet) const; -extern std::map mapRequestCount; -extern CCriticalSection cs_mapRequestCount; -extern std::map mapAddressBook; -extern CCriticalSection cs_mapAddressBook; +public: + bool fFileBacked; + std::string strWalletFile; -extern std::vector vchDefaultKey; -extern CKey keyUser; + std::set setKeyPool; + CCriticalSection cs_setKeyPool; -bool AddToWallet(const CWalletTx& wtxIn); -bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false); -bool EraseFromWallet(uint256 hash); -void WalletUpdateSpent(const COutPoint& prevout); -int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); -void ReacceptWalletTransactions(); -void ResendWalletTransactions(); -int64 GetBalance(); -bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); -bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); -bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); -bool BroadcastTransaction(CWalletTx& wtxNew); -std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); -std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); + CWallet() + { + fFileBacked = false; + } + CWallet(std::string strWalletFileIn) + { + strWalletFile = strWalletFileIn; + fFileBacked = true; + } + mutable CCriticalSection cs_mapWallet; + std::map mapWallet; + std::vector vWalletUpdated; + + std::map mapRequestCount; + mutable CCriticalSection cs_mapRequestCount; + + std::map mapAddressBook; + mutable CCriticalSection cs_mapAddressBook; + + std::vector vchDefaultKey; + CKey keyUser; + + bool AddKey(const CKey& key); + bool AddToWallet(const CWalletTx& wtxIn); + bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false); + bool EraseFromWallet(uint256 hash); + void WalletUpdateSpent(const CTransaction& prevout); + int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); + void ReacceptWalletTransactions(); + void ResendWalletTransactions(); + int64 GetBalance() const; + bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); + bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); + bool BroadcastTransaction(CWalletTx& wtxNew); + std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); + std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); + + void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool); + void KeepKey(int64 nIndex); + void ReturnKey(int64 nIndex); + std::vector GetKeyFromKeyPool(); + int64 GetOldestKeyPoolTime(); + + bool IsMine(const CTxIn& txin) const; + int64 GetDebit(const CTxIn& txin) const; + bool IsMine(const CTxOut& txout) const + { + return ::IsMine(*this, txout.scriptPubKey); + } + int64 GetCredit(const CTxOut& txout) const + { + if (!MoneyRange(txout.nValue)) + throw std::runtime_error("CWallet::GetCredit() : value out of range"); + return (IsMine(txout) ? txout.nValue : 0); + } + bool IsChange(const CTxOut& txout) const + { + std::vector vchPubKey; + if (ExtractPubKey(txout.scriptPubKey, this, vchPubKey)) + CRITICAL_BLOCK(cs_mapAddressBook) + if (!mapAddressBook.count(PubKeyToAddress(vchPubKey))) + return true; + return false; + } + int64 GetChange(const CTxOut& txout) const + { + if (!MoneyRange(txout.nValue)) + throw std::runtime_error("CWallet::GetChange() : value out of range"); + if (IsChange(txout) ? txout.nValue : 0); + } + bool IsMine(const CTransaction& tx) const + { + BOOST_FOREACH(const CTxOut& txout, tx.vout) + if (IsMine(txout)) + return true; + return false; + } + bool IsFromMe(const CTransaction& tx) const + { + return (GetDebit(tx) > 0); + } + int64 GetDebit(const CTransaction& tx) const + { + int64 nDebit = 0; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + nDebit += GetDebit(txin); + if (!MoneyRange(nDebit)) + throw std::runtime_error("CWallet::GetDebit() : value out of range"); + } + return nDebit; + } + int64 GetCredit(const CTransaction& tx) const + { + int64 nCredit = 0; + BOOST_FOREACH(const CTxOut& txout, tx.vout) + { + nCredit += GetCredit(txout); + if (!MoneyRange(nCredit)) + throw std::runtime_error("CWallet::GetCredit() : value out of range"); + } + return nCredit; + } + int64 GetChange(const CTransaction& tx) const + { + int64 nChange = 0; + BOOST_FOREACH(const CTxOut& txout, tx.vout) + { + nChange += GetChange(txout); + if (!MoneyRange(nChange)) + throw std::runtime_error("CWallet::GetChange() : value out of range"); + } + return nChange; + } + void SetBestChain(const CBlockLocator& loc) + { + CWalletDB walletdb(strWalletFile); + walletdb.WriteBestBlock(loc); + } + + bool LoadWallet(bool& fFirstRunRet); +// bool BackupWallet(const std::string& strDest); + + bool SetAddressBookName(const std::string& strAddress, const std::string& strName) + { + if (!fFileBacked) + return false; + return CWalletDB(strWalletFile).WriteName(strAddress, strName); + } + + void UpdatedTransaction(const uint256 &hashTx) + { + CRITICAL_BLOCK(cs_mapWallet) + vWalletUpdated.push_back(hashTx); + } + + void PrintWallet(const CBlock& block); + + void Inventory(const uint256 &hash) + { + CRITICAL_BLOCK(cs_mapRequestCount) + { + std::map::iterator mi = mapRequestCount.find(hash); + if (mi != mapRequestCount.end()) + (*mi).second++; + } + } + + bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx); + +}; + + +class CReserveKey +{ +protected: + CWallet* pwallet; + int64 nIndex; + std::vector vchPubKey; +public: + CReserveKey(CWallet* pwalletIn) + { + nIndex = -1; + pwallet = pwalletIn; + } + + ~CReserveKey() + { + if (!fShutdown) + ReturnKey(); + } + + void ReturnKey(); + std::vector GetReservedKey(); + void KeepKey(); +}; // @@ -49,6 +214,8 @@ std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWal class CWalletTx : public CMerkleTx { public: + const CWallet* pwallet; + std::vector vtxPrev; std::map mapValue; std::vector > vOrderForm; @@ -73,24 +240,29 @@ public: mutable int nLinesDisplayed; mutable char fConfirmedDisplayed; - CWalletTx() { - Init(); + Init(NULL); } - CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn) + CWalletTx(const CWallet* pwalletIn) { - Init(); + Init(pwalletIn); } - CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn) + CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn) { - Init(); + Init(pwalletIn); } - void Init() + CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn) { + Init(pwalletIn); + } + + void Init(const CWallet* pwalletIn) + { + pwallet = pwalletIn; vtxPrev.clear(); mapValue.clear(); vOrderForm.clear(); @@ -116,7 +288,7 @@ public: ( CWalletTx* pthis = const_cast(this); if (fRead) - pthis->Init(); + pthis->Init(NULL); char fSpent = false; if (!fRead) @@ -213,7 +385,7 @@ public: return 0; if (fDebitCached) return nDebitCached; - nDebitCached = CTransaction::GetDebit(); + nDebitCached = pwallet->GetDebit(*this); fDebitCached = true; return nDebitCached; } @@ -227,7 +399,7 @@ public: // GetBalance can assume transactions in mapWallet won't change if (fUseCache && fCreditCached) return nCreditCached; - nCreditCached = CTransaction::GetCredit(); + nCreditCached = pwallet->GetCredit(*this); fCreditCached = true; return nCreditCached; } @@ -247,7 +419,7 @@ public: if (!IsSpent(i)) { const CTxOut &txout = vout[i]; - nCredit += txout.GetCredit(); + nCredit += pwallet->GetCredit(txout); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } @@ -263,7 +435,7 @@ public: { if (fChangeCached) return nChangeCached; - nChangeCached = CTransaction::GetChange(); + nChangeCached = pwallet->GetChange(*this); fChangeCached = true; return nChangeCached; } @@ -271,7 +443,7 @@ public: void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list >& listReceived, std::list >& listSent, int64& nFee, std::string& strSentAccount) const; - void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived, + void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived, int64& nSent, int64& nFee) const; bool IsFromMe() const @@ -303,7 +475,7 @@ public: return false; if (ptx->GetDepthInMainChain() >= 1) continue; - if (!ptx->IsFromMe()) + if (!pwallet->IsFromMe(*ptx)) return false; if (mapPrev.empty()) @@ -438,4 +610,6 @@ public: ) }; +bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); + #endif -- cgit v1.2.3