diff options
Diffstat (limited to 'src/wallet.h')
-rw-r--r-- | src/wallet.h | 139 |
1 files changed, 43 insertions, 96 deletions
diff --git a/src/wallet.h b/src/wallet.h index dc8c007ac8..e2e89fffe7 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -25,6 +25,7 @@ // Settings extern int64_t nTransactionFee; +extern bool bSpendZeroConfChange; class CAccountingEntry; class CCoinControl; @@ -107,6 +108,16 @@ private: int64_t nNextResend; int64_t nLastResend; + // Used to keep track of spent outpoints, and + // detect and report conflicts (double-spends or + // mutated transactions where the mutant gets mined). + typedef std::multimap<COutPoint, uint256> TxSpends; + TxSpends mapTxSpends; + void AddToSpends(const COutPoint& outpoint, const uint256& wtxid); + void AddToSpends(const uint256& wtxid); + + void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>); + public: /// Main wallet lock. /// This lock protects all the fields added by CWallet @@ -150,6 +161,7 @@ public: } std::map<uint256, CWalletTx> mapWallet; + int64_t nOrderPosNext; std::map<uint256, int> mapRequestCount; @@ -161,12 +173,16 @@ public: int64_t nTimeFirstKey; + const CWalletTx* GetWalletTx(const uint256& hash) const; + // check whether we are allowed to upgrade (or already support) to the named feature bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const; bool SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const; + bool IsSpent(const uint256& hash, unsigned int n) const; + bool IsLockedCoin(uint256 hash, unsigned int n) const; void LockCoin(COutPoint& output); void UnlockCoin(COutPoint& output); @@ -222,11 +238,10 @@ public: TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = ""); void MarkDirty(); - bool AddToWallet(const CWalletTx& wtxIn); + bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false); void SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate); void EraseFromWallet(const uint256 &hash); - void WalletUpdateSpent(const CTransaction& prevout); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(); @@ -322,6 +337,7 @@ public: void SetBestChain(const CBlockLocator& loc); DBErrors LoadWallet(bool& fFirstRunRet); + DBErrors ZapWalletTx(); bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose); @@ -354,7 +370,10 @@ public: bool SetMaxVersion(int nVersion); // get the current wallet format (the oldest client version guaranteed to understand this wallet) - int GetVersion() { AssertLockHeld(cs_wallet); return nWalletVersion; } + int GetVersion() { LOCK(cs_wallet); return nWalletVersion; } + + // Get wallet transactions that conflict with given transaction (spend same outputs) + std::set<uint256> GetConflicts(const uint256& txid) const; /** Address book entry changed. * @note called with lock cs_wallet held. @@ -427,7 +446,6 @@ private: const CWallet* pwallet; public: - std::vector<CMerkleTx> vtxPrev; mapValue_t mapValue; std::vector<std::pair<std::string, std::string> > vOrderForm; unsigned int fTimeReceivedIsTxTime; @@ -435,7 +453,6 @@ public: unsigned int nTimeSmart; char fFromMe; std::string strFromAccount; - std::vector<char> vfSpent; // which outputs are already spent int64_t nOrderPos; // position in ordered transaction list // memory only @@ -473,7 +490,6 @@ public: void Init(const CWallet* pwalletIn) { pwallet = pwalletIn; - vtxPrev.clear(); mapValue.clear(); vOrderForm.clear(); fTimeReceivedIsTxTime = false; @@ -481,7 +497,6 @@ public: nTimeSmart = 0; fFromMe = false; strFromAccount.clear(); - vfSpent.clear(); fDebitCached = false; fCreditCached = false; fImmatureCreditCached = false; @@ -506,15 +521,6 @@ public: { pthis->mapValue["fromaccount"] = pthis->strFromAccount; - std::string str; - BOOST_FOREACH(char f, vfSpent) - { - str += (f ? '1' : '0'); - if (f) - fSpent = true; - } - pthis->mapValue["spent"] = str; - WriteOrderPos(pthis->nOrderPos, pthis->mapValue); if (nTimeSmart) @@ -522,7 +528,8 @@ public: } nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action); - READWRITE(vtxPrev); + std::vector<CMerkleTx> vUnused; // Used to be vtxPrev + READWRITE(vUnused); READWRITE(mapValue); READWRITE(vOrderForm); READWRITE(fTimeReceivedIsTxTime); @@ -534,12 +541,6 @@ public: { pthis->strFromAccount = pthis->mapValue["fromaccount"]; - if (mapValue.count("spent")) - BOOST_FOREACH(char c, pthis->mapValue["spent"]) - pthis->vfSpent.push_back(c != '0'); - else - pthis->vfSpent.assign(vout.size(), fSpent); - ReadOrderPos(pthis->nOrderPos, pthis->mapValue); pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0; @@ -552,26 +553,6 @@ public: pthis->mapValue.erase("timesmart"); ) - // marks certain txout's as spent - // returns true if any update took place - bool UpdateSpent(const std::vector<char>& vfNewSpent) - { - bool fReturn = false; - for (unsigned int i = 0; i < vfNewSpent.size(); i++) - { - if (i == vfSpent.size()) - break; - - if (vfNewSpent[i] && !vfSpent[i]) - { - vfSpent[i] = true; - fReturn = true; - fAvailableCreditCached = false; - } - } - return fReturn; - } - // make sure balances are recalculated void MarkDirty() { @@ -587,27 +568,6 @@ public: MarkDirty(); } - void MarkSpent(unsigned int nOut) - { - if (nOut >= vout.size()) - throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range"); - vfSpent.resize(vout.size()); - if (!vfSpent[nOut]) - { - vfSpent[nOut] = true; - fAvailableCreditCached = false; - } - } - - bool IsSpent(unsigned int nOut) const - { - if (nOut >= vout.size()) - throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range"); - if (nOut >= vfSpent.size()) - return false; - return (!!vfSpent[nOut]); - } - int64_t GetDebit() const { if (vin.empty()) @@ -649,6 +609,9 @@ public: int64_t GetAvailableCredit(bool fUseCache=true) const { + if (pwallet == 0) + return 0; + // Must wait until coinbase is safely deep enough in the chain before valuing it if (IsCoinBase() && GetBlocksToMaturity() > 0) return 0; @@ -659,7 +622,7 @@ public: int64_t nCredit = 0; for (unsigned int i = 0; i < vout.size(); i++) { - if (!IsSpent(i)) + if (!pwallet->IsSpent(GetHash(), i)) { const CTxOut &txout = vout[i]; nCredit += pwallet->GetCredit(txout); @@ -694,45 +657,29 @@ public: return (GetDebit() > 0); } - bool IsConfirmed() const + bool IsTrusted() const { // Quick answer in most cases if (!IsFinalTx(*this)) return false; - if (GetDepthInMainChain() >= 1) + int nDepth = GetDepthInMainChain(); + if (nDepth >= 1) return true; - if (!IsFromMe()) // using wtx's cached debit + if (nDepth < 0) + return false; + if (!bSpendZeroConfChange || !IsFromMe()) // using wtx's cached debit return false; - // If no confirmations but it's from us, we can still - // consider it confirmed if all dependencies are confirmed - std::map<uint256, const CMerkleTx*> mapPrev; - std::vector<const CMerkleTx*> vWorkQueue; - vWorkQueue.reserve(vtxPrev.size()+1); - vWorkQueue.push_back(this); - for (unsigned int i = 0; i < vWorkQueue.size(); i++) + // Trusted if all inputs are from us and are in the mempool: + BOOST_FOREACH(const CTxIn& txin, vin) { - const CMerkleTx* ptx = vWorkQueue[i]; - - if (!IsFinalTx(*ptx)) + // Transactions not sent by us: not trusted + const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash); + if (parent == NULL) return false; - if (ptx->GetDepthInMainChain() >= 1) - continue; - if (!pwallet->IsFromMe(*ptx)) + const CTxOut& parentOut = parent->vout[txin.prevout.n]; + if (!pwallet->IsMine(parentOut)) return false; - - if (mapPrev.empty()) - { - BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) - mapPrev[tx.GetHash()] = &tx; - } - - BOOST_FOREACH(const CTxIn& txin, ptx->vin) - { - if (!mapPrev.count(txin.prevout.hash)) - return false; - vWorkQueue.push_back(mapPrev[txin.prevout.hash]); - } } return true; } @@ -742,9 +689,9 @@ public: int64_t GetTxTime() const; int GetRequestCount() const; - void AddSupportingTransactions(); - bool AcceptWalletTransaction(); void RelayWalletTransaction(); + + std::set<uint256> GetConflicts() const; }; |