aboutsummaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp208
1 files changed, 111 insertions, 97 deletions
diff --git a/main.cpp b/main.cpp
index c45f85837c..17a1b81c5c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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