diff options
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 208 |
1 files changed, 111 insertions, 97 deletions
@@ -144,11 +144,7 @@ bool AddToWallet(const CWalletTx& wtxIn) wtx.fFromMe = wtxIn.fFromMe; fUpdated = true; } - if (wtxIn.fSpent && wtxIn.fSpent != wtx.fSpent) - { - wtx.fSpent = wtxIn.fSpent; - fUpdated = true; - } + fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent); } //// debug print @@ -229,10 +225,10 @@ void WalletUpdateSpent(const COutPoint& prevout) if (mi != mapWallet.end()) { CWalletTx& wtx = (*mi).second; - if (!wtx.fSpent && wtx.vout[prevout.n].IsMine()) + if (!wtx.IsSpent(prevout.n) && wtx.vout[prevout.n].IsMine()) { printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); - wtx.fSpent = true; + wtx.MarkSpent(prevout.n); wtx.WriteToDisk(); vWalletUpdated.push_back(prevout.hash); } @@ -947,34 +943,34 @@ void ReacceptWalletTransactions() foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) { CWalletTx& wtx = item.second; - if (wtx.fSpent && wtx.IsCoinBase()) + if (wtx.IsCoinBase() && wtx.IsSpent(0)) continue; CTxIndex txindex; + bool fUpdated = false; if (txdb.ReadTxIndex(wtx.GetHash(), txindex)) { // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat - if (!wtx.fSpent) + if (txindex.vSpent.size() != wtx.vout.size()) { - if (txindex.vSpent.size() != wtx.vout.size()) - { - printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size()); - continue; - } - for (int i = 0; i < txindex.vSpent.size(); i++) - { - if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine()) - { - wtx.fSpent = true; - vMissingTx.push_back(txindex.vSpent[i]); - } - } - if (wtx.fSpent) + printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size()); + continue; + } + for (int i = 0; i < txindex.vSpent.size(); i++) + { + if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine()) { - printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); - wtx.WriteToDisk(); + wtx.MarkSpent(i); + fUpdated = true; + vMissingTx.push_back(txindex.vSpent[i]); } } + if (fUpdated) + { + printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + wtx.MarkDirty(); + wtx.WriteToDisk(); + } } else { @@ -3740,9 +3736,9 @@ int64 GetBalance() for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { CWalletTx* pcoin = &(*it).second; - if (!pcoin->IsFinal() || pcoin->fSpent || !pcoin->IsConfirmed()) + if (!pcoin->IsFinal() || !pcoin->IsConfirmed()) continue; - nTotal += pcoin->GetCredit(); + nTotal += pcoin->GetAvailableCredit(); } } @@ -3751,14 +3747,16 @@ int64 GetBalance() } -bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<CWalletTx*>& setCoinsRet) +bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) { setCoinsRet.clear(); + nValueRet = 0; // List of values less than target - int64 nLowestLarger = INT64_MAX; - CWalletTx* pcoinLowestLarger = NULL; - vector<pair<int64, CWalletTx*> > vValue; + pair<int64, pair<CWalletTx*,unsigned int> > coinLowestLarger; + coinLowestLarger.first = INT64_MAX; + coinLowestLarger.second.first = NULL; + vector<pair<int64, pair<CWalletTx*,unsigned int> > > vValue; int64 nTotalLower = 0; CRITICAL_BLOCK(cs_mapWallet) @@ -3771,30 +3769,43 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< foreach(CWalletTx* pcoin, vCoins) { - if (!pcoin->IsFinal() || pcoin->fSpent || !pcoin->IsConfirmed()) + if (!pcoin->IsFinal() || !pcoin->IsConfirmed()) + continue; + + if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) continue; int nDepth = pcoin->GetDepthInMainChain(); if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) continue; - int64 n = pcoin->GetCredit(); - if (n <= 0) - continue; - if (n == nTargetValue) - { - setCoinsRet.insert(pcoin); - return true; - } - else if (n < nTargetValue + CENT) + for (int i = 0; i < pcoin->vout.size(); i++) { - vValue.push_back(make_pair(n, pcoin)); - nTotalLower += n; - } - else if (n < nLowestLarger) - { - nLowestLarger = n; - pcoinLowestLarger = pcoin; + if (pcoin->IsSpent(i) || !pcoin->vout[i].IsMine()) + continue; + + int64 n = pcoin->vout[i].nValue; + + if (n <= 0) + continue; + + pair<int64,pair<CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i)); + + if (n == nTargetValue) + { + setCoinsRet.insert(coin.second); + nValueRet += coin.first; + return true; + } + else if (n < nTargetValue + CENT) + { + vValue.push_back(coin); + nTotalLower += n; + } + else if (n < coinLowestLarger.first) + { + coinLowestLarger = coin; + } } } } @@ -3802,15 +3813,19 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT) { for (int i = 0; i < vValue.size(); ++i) + { setCoinsRet.insert(vValue[i].second); + nValueRet += vValue[i].first; + } return true; } - if (nTotalLower < nTargetValue + (pcoinLowestLarger ? CENT : 0)) + if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0)) { - if (pcoinLowestLarger == NULL) + if (coinLowestLarger.second.first == NULL) return false; - setCoinsRet.insert(pcoinLowestLarger); + setCoinsRet.insert(coinLowestLarger.second); + nValueRet += coinLowestLarger.first; return true; } @@ -3853,13 +3868,18 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< } // If the next larger is still closer, return it - if (pcoinLowestLarger && nLowestLarger - nTargetValue <= nBest - nTargetValue) - setCoinsRet.insert(pcoinLowestLarger); - else + if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue) { + setCoinsRet.insert(coinLowestLarger.second); + nValueRet += coinLowestLarger.first; + } + else { for (int i = 0; i < vValue.size(); i++) if (vfBest[i]) + { setCoinsRet.insert(vValue[i].second); + nValueRet += vValue[i].first; + } //// debug print printf("SelectCoins() best subset: "); @@ -3872,11 +3892,11 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< return true; } -bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet) +bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) { - return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet) || - SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet) || - SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet)); + return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) || + SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) || + SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet)); } @@ -3914,15 +3934,14 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew.vout.push_back(CTxOut(s.second, s.first)); // Choose coins to use - set<CWalletTx*> setCoins; - if (!SelectCoins(nTotalValue, setCoins)) - return false; + set<pair<CWalletTx*,unsigned int> > setCoins; int64 nValueIn = 0; - foreach(CWalletTx* pcoin, setCoins) + if (!SelectCoins(nTotalValue, setCoins, nValueIn)) + return false; + foreach(PAIRTYPE(CWalletTx*, unsigned int) pcoin, setCoins) { - int64 nCredit = pcoin->GetCredit(); - nValueIn += nCredit; - dPriority += (double)nCredit * pcoin->GetDepthInMainChain(); + int64 nCredit = pcoin.first->vout[pcoin.second].nValue; + dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain(); } // Fill a vout back to self with any change @@ -3955,18 +3974,14 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& reservekey.ReturnKey(); // Fill vin - foreach(CWalletTx* pcoin, setCoins) - for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) - if (pcoin->vout[nOut].IsMine()) - wtxNew.vin.push_back(CTxIn(pcoin->GetHash(), nOut)); + foreach(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins) + wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); // Sign int nIn = 0; - foreach(CWalletTx* pcoin, setCoins) - for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) - if (pcoin->vout[nOut].IsMine()) - if (!SignSignature(*pcoin, wtxNew, nIn++)) - return false; + foreach(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins) + if (!SignSignature(*coin.first, wtxNew, nIn++)) + return false; // Limit size unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK); @@ -4025,12 +4040,11 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) // Mark old coins as spent set<CWalletTx*> setCoins; foreach(const CTxIn& txin, wtxNew.vin) - setCoins.insert(&mapWallet[txin.prevout.hash]); - foreach(CWalletTx* pcoin, setCoins) { - pcoin->fSpent = true; - pcoin->WriteToDisk(); - vWalletUpdated.push_back(pcoin->GetHash()); + CWalletTx &pcoin = mapWallet[txin.prevout.hash]; + pcoin.MarkSpent(txin.prevout.n); + pcoin.WriteToDisk(); + vWalletUpdated.push_back(pcoin.GetHash()); } } @@ -4054,35 +4068,35 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) +// requires cs_main lock string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee) { - CRITICAL_BLOCK(cs_main) + CReserveKey reservekey; + int64 nFeeRequired; + if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired)) { - CReserveKey reservekey; - int64 nFeeRequired; - if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired)) - { - string strError; - if (nValue + nFeeRequired > GetBalance()) - strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str()); - else - strError = _("Error: Transaction creation failed "); - printf("SendMoney() : %s", strError.c_str()); - return strError; - } + string strError; + if (nValue + nFeeRequired > GetBalance()) + strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str()); + else + strError = _("Error: Transaction creation failed "); + printf("SendMoney() : %s", strError.c_str()); + return strError; + } - if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL)) - return "ABORTED"; + if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL)) + return "ABORTED"; + + if (!CommitTransaction(wtxNew, reservekey)) + 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."); - if (!CommitTransaction(wtxNew, reservekey)) - 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."); - } MainFrameRepaint(); return ""; } +// requires cs_main lock string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee) { // Check amount |