Remove CWalletTx::vfSpent
Use the spent outpoint multimap to figure out which wallet transaction outputs are unspent, instead of a vfSpent array that is saved to disk.
This commit is contained in:
125
src/wallet.h
125
src/wallet.h
@@ -108,11 +108,15 @@ private:
|
||||
int64_t nNextResend;
|
||||
int64_t nLastResend;
|
||||
|
||||
// Used to detect and report conflicted transactions:
|
||||
typedef std::multimap<COutPoint, uint256> TxConflicts;
|
||||
TxConflicts mapTxConflicts;
|
||||
void AddToConflicts(const uint256& wtxhash);
|
||||
void SyncMetaData(std::pair<TxConflicts::iterator, TxConflicts::iterator>);
|
||||
// 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.
|
||||
@@ -169,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);
|
||||
@@ -234,7 +242,6 @@ public:
|
||||
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();
|
||||
@@ -439,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;
|
||||
@@ -447,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
|
||||
@@ -485,7 +490,6 @@ public:
|
||||
void Init(const CWallet* pwalletIn)
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
vtxPrev.clear();
|
||||
mapValue.clear();
|
||||
vOrderForm.clear();
|
||||
fTimeReceivedIsTxTime = false;
|
||||
@@ -493,7 +497,6 @@ public:
|
||||
nTimeSmart = 0;
|
||||
fFromMe = false;
|
||||
strFromAccount.clear();
|
||||
vfSpent.clear();
|
||||
fDebitCached = false;
|
||||
fCreditCached = false;
|
||||
fImmatureCreditCached = false;
|
||||
@@ -518,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)
|
||||
@@ -534,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);
|
||||
@@ -546,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;
|
||||
@@ -564,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()
|
||||
{
|
||||
@@ -599,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())
|
||||
@@ -661,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;
|
||||
@@ -671,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);
|
||||
@@ -719,38 +670,14 @@ public:
|
||||
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);
|
||||
const CTxOut& parentOut = parent->vout[txin.prevout.n];
|
||||
if (parent == NULL || !pwallet->IsMine(parentOut))
|
||||
return false;
|
||||
int nPDepth = ptx->GetDepthInMainChain();
|
||||
if (nPDepth >= 1)
|
||||
continue;
|
||||
if (nPDepth < 0)
|
||||
return false;
|
||||
if (!pwallet->IsFromMe(*ptx))
|
||||
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;
|
||||
}
|
||||
@@ -760,8 +687,6 @@ public:
|
||||
int64_t GetTxTime() const;
|
||||
int GetRequestCount() const;
|
||||
|
||||
void AddSupportingTransactions();
|
||||
bool AcceptWalletTransaction();
|
||||
void RelayWalletTransaction();
|
||||
|
||||
std::set<uint256> GetConflicts() const;
|
||||
|
||||
Reference in New Issue
Block a user