Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 32 additions & 34 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,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
Expand Down Expand Up @@ -221,10 +217,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);
}
Expand Down Expand Up @@ -939,34 +935,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;
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
{
Expand Down Expand Up @@ -3732,9 +3728,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();
}
}

Expand Down Expand Up @@ -3763,14 +3759,17 @@ 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();
int64 n = pcoin->GetAvailableCredit();
if (n <= 0)
continue;
if (n == nTargetValue)
Expand Down Expand Up @@ -4017,12 +4016,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());
}
}

Expand Down
122 changes: 113 additions & 9 deletions main.h
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ class CMerkleTx : public CTransaction
fMerkleVerified = false;
}


IMPLEMENT_SERIALIZE
(
nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
Expand Down Expand Up @@ -774,15 +775,17 @@ class CWalletTx : public CMerkleTx
unsigned int fTimeReceivedIsTxTime;
unsigned int nTimeReceived; // time received by this node
char fFromMe;
char fSpent;
string strFromAccount;
vector<char> vfSpent;

// memory only
mutable char fDebitCached;
mutable char fCreditCached;
mutable char fAvailableCreditCached;
mutable char fChangeCached;
mutable int64 nDebitCached;
mutable int64 nCreditCached;
mutable int64 nAvailableCreditCached;
mutable int64 nChangeCached;

// memory only UI hints
Expand Down Expand Up @@ -814,8 +817,8 @@ class CWalletTx : public CMerkleTx
fTimeReceivedIsTxTime = false;
nTimeReceived = 0;
fFromMe = false;
fSpent = false;
strFromAccount.clear();
vfSpent.clear();
fDebitCached = false;
fCreditCached = false;
fChangeCached = false;
Expand All @@ -832,22 +835,96 @@ class CWalletTx : public CMerkleTx
CWalletTx* pthis = const_cast<CWalletTx*>(this);
if (fRead)
pthis->Init();
nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);
READWRITE(vtxPrev);
char fSpent = false;

pthis->mapValue["fromaccount"] = pthis->strFromAccount;
READWRITE(mapValue);
pthis->strFromAccount = pthis->mapValue["fromaccount"];
pthis->mapValue.erase("fromaccount");
pthis->mapValue.erase("version");
if (!fRead)
{
pthis->mapValue["fromaccount"] = pthis->strFromAccount;

string str;
foreach(char f, vfSpent)
{
str += (f ? '1' : '0');
if (f)
fSpent = true;
}
pthis->mapValue["spent"] = str;
}

nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
READWRITE(vtxPrev);
READWRITE(mapValue);
READWRITE(vOrderForm);
READWRITE(fTimeReceivedIsTxTime);
READWRITE(nTimeReceived);
READWRITE(fFromMe);
READWRITE(fSpent);

if (fRead)
{
pthis->strFromAccount = pthis->mapValue["fromaccount"];

if (mapValue.count("spent"))
foreach(char c, pthis->mapValue["spent"])
pthis->vfSpent.push_back(c != '0');
else
pthis->vfSpent.assign(vout.size(), fSpent);
}

pthis->mapValue.erase("fromaccount");
pthis->mapValue.erase("version");
pthis->mapValue.erase("spent");
)

// marks certain txout's as spent
// returns true if any update took place
bool UpdateSpent(const vector<char>& vfNewSpent)
{
bool fReturn;
for (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;
}

void MarkDirty()
{
fCreditCached = false;
fAvailableCreditCached = false;
fDebitCached = false;
fChangeCached = false;
}

void MarkSpent(unsigned int nOut)
{
if (nOut >= vout.size())
throw 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 runtime_error("CWalletTx::IsSpent() : nOut out of range");
if (nOut >= vfSpent.size())
return false;
return (!!vfSpent[nOut]);
}

int64 GetDebit() const
{
if (vin.empty())
Expand All @@ -873,6 +950,33 @@ class CWalletTx : public CMerkleTx
return nCreditCached;
}

int64 GetAvailableCredit(bool fUseCache=true) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;

if (fUseCache && fAvailableCreditCached)
return nAvailableCreditCached;

int64 nCredit = 0;
for (int i = 0; i < vout.size(); i++)
{
if (!IsSpent(i))
{
const CTxOut &txout = vout[i];
nCredit += txout.GetCredit();
if (!MoneyRange(nCredit))
throw runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
}
}

nAvailableCreditCached = nCredit;
fAvailableCreditCached = true;
return nCredit;
}


int64 GetChange() const
{
if (fChangeCached)
Expand Down