From 73b3c9238e4de79fd06aa2fe0fbdc31fbb005956 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 13 Aug 2017 17:32:23 +0300 Subject: [PATCH] add/use GetUTXO[Coins/Confirmations] helpers instead of GetInputAge[IX] (move IS confirmations to CInstantSend) --- src/activemasternode.cpp | 6 ++--- src/governance-object.cpp | 3 ++- src/instantx.cpp | 13 ++++----- src/instantx.h | 3 +++ src/masternode.cpp | 25 +----------------- src/masternode.h | 2 -- src/masternodeman.cpp | 2 +- src/privatesend-server.cpp | 8 +++--- src/privatesend.cpp | 18 ++++--------- src/validation.cpp | 54 +++++++++----------------------------- src/validation.h | 5 ++-- src/wallet/rpcwallet.cpp | 5 ++-- 12 files changed, 43 insertions(+), 101 deletions(-) diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index b1d5bfd260957..8045cf57d06b7 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -287,10 +287,10 @@ void CActiveMasternode::ManageStateLocal() CKey keyCollateral; if(pwalletMain->GetMasternodeVinAndKeys(vin, pubKeyCollateral, keyCollateral)) { - int nInputAge = GetInputAge(vin); - if(nInputAge < Params().GetConsensus().nMasternodeMinimumConfirmations){ + int nPrevoutAge = GetUTXOConfirmations(vin.prevout); + if(nPrevoutAge < Params().GetConsensus().nMasternodeMinimumConfirmations){ nState = ACTIVE_MASTERNODE_INPUT_TOO_NEW; - strNotCapableReason = strprintf(_("%s - %d confirmations"), GetStatus(), nInputAge); + strNotCapableReason = strprintf(_("%s - %d confirmations"), GetStatus(), nPrevoutAge); LogPrintf("CActiveMasternode::ManageStateLocal -- %s: %s\n", GetStateString(), strNotCapableReason); return; } diff --git a/src/governance-object.cpp b/src/governance-object.cpp index 3665857be561c..1fcf1401adff7 100644 --- a/src/governance-object.cpp +++ b/src/governance-object.cpp @@ -7,6 +7,7 @@ #include "governance-classes.h" #include "governance-object.h" #include "governance-vote.h" +#include "instantx.h" #include "masternodeman.h" #include "messagesigner.h" #include "util.h" @@ -590,7 +591,7 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC // GET CONFIRMATIONS FOR TRANSACTION AssertLockHeld(cs_main); - int nConfirmationsIn = GetIXConfirmations(nCollateralHash); + int nConfirmationsIn = instantsend.GetConfirmations(nCollateralHash); if (nBlockHash != uint256()) { BlockMap::iterator mi = mapBlockIndex.find(nBlockHash); if (mi != mapBlockIndex.end() && (*mi).second) { diff --git a/src/instantx.cpp b/src/instantx.cpp index 3bbdb27c87f46..aa9ef35b909ec 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -562,9 +562,7 @@ bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate, int // Not in block yet, make sure all its inputs are still unspent BOOST_FOREACH(const CTxIn& txin, txLockCandidate.txLockRequest.vin) { CCoins coins; - if(!pcoinsTip->GetCoins(txin.prevout.hash, coins) || - (unsigned int)txin.prevout.n>=coins.vout.size() || - coins.vout[txin.prevout.n].IsNull()) { + if(!GetUTXOCoins(txin.prevout, coins)) { // Not in UTXO anymore? A conflicting tx was mined while we were waiting for votes. // Reprocess tip to make sure tx for this lock is included. LogPrintf("CTxLockRequest::ResolveConflicts -- Failed to find UTXO %s - disconnecting tip...\n", txin.prevout.ToStringShort()); @@ -773,6 +771,11 @@ int CInstantSend::GetTransactionLockSignatures(const uint256& txHash) return -1; } +int CInstantSend::GetConfirmations(const uint256 &nTXHash) +{ + return IsLockedInstantSendTransaction(nTXHash) ? nInstantSendDepth : 0; +} + bool CInstantSend::IsTxLockRequestTimedOut(const uint256& txHash) { if(!fEnableInstantSend) return false; @@ -912,9 +915,7 @@ bool CTxLockRequest::IsValid(bool fRequireUnspent) const int nPrevoutHeight = 0; CAmount nValue = 0; - if(!pcoinsTip->GetCoins(txin.prevout.hash, coins) || - (unsigned int)txin.prevout.n>=coins.vout.size() || - coins.vout[txin.prevout.n].IsNull()) { + if(!GetUTXOCoins(txin.prevout, coins)) { LogPrint("instantsend", "CTxLockRequest::IsValid -- Failed to find UTXO %s\n", txin.prevout.ToStringShort()); // Normally above sould be enough, but in case we are reprocessing this because of // a lot of legit orphan votes we should also check already spent outpoints. diff --git a/src/instantx.h b/src/instantx.h index 40f6973efbf18..987ed258324d5 100644 --- a/src/instantx.h +++ b/src/instantx.h @@ -4,6 +4,7 @@ #ifndef INSTANTX_H #define INSTANTX_H +#include "chain.h" #include "net.h" #include "primitives/transaction.h" @@ -95,6 +96,8 @@ class CInstantSend bool IsLockedInstantSendTransaction(const uint256& txHash); // get the actual uber og accepted lock signatures int GetTransactionLockSignatures(const uint256& txHash); + // get instantsend confirmations (only) + int GetConfirmations(const uint256 &nTXHash); // remove expired entries from maps void CheckAndRemove(); diff --git a/src/masternode.cpp b/src/masternode.cpp index a8bc8dd5c443e..438a76b461bba 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -114,9 +114,7 @@ CMasternode::CollateralStatus CMasternode::CheckCollateral(CTxIn vin, int& nHeig AssertLockHeld(cs_main); CCoins coins; - if(!pcoinsTip->GetCoins(vin.prevout.hash, coins) || - (unsigned int)vin.prevout.n>=coins.vout.size() || - coins.vout[vin.prevout.n].IsNull()) { + if(!GetUTXOCoins(vin.prevout, coins)) { return COLLATERAL_UTXO_NOT_FOUND; } @@ -309,27 +307,6 @@ std::string CMasternode::GetStatus() const return GetStateString(); } -int CMasternode::GetCollateralAge() -{ - int nHeight; - { - TRY_LOCK(cs_main, lockMain); - if(!lockMain || !chainActive.Tip()) return -1; - nHeight = chainActive.Height(); - } - - if (nCacheCollateralBlock == 0) { - int nInputAge = GetInputAge(vin); - if(nInputAge > 0) { - nCacheCollateralBlock = nHeight - nInputAge; - } else { - return nInputAge; - } - } - - return nHeight - nCacheCollateralBlock; -} - void CMasternode::UpdateLastPaid(const CBlockIndex *pindex, int nMaxBlocksToScanBack) { if(!pindex) return; diff --git a/src/masternode.h b/src/masternode.h index 384fe25e1639b..6ad6ae4a454eb 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -265,8 +265,6 @@ class CMasternode : public masternode_info_t std::string GetStateString() const; std::string GetStatus() const; - int GetCollateralAge(); - int GetLastPaidTime() { return nTimeLastPaid; } int GetLastPaidBlock() { return nBlockLastPaid; } void UpdateLastPaid(const CBlockIndex *pindex, int nMaxBlocksToScanBack); diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index c4761e0f6861c..f92ef92f33c90 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -575,7 +575,7 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight if(fFilterSigTime && mn.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue; //make sure it has at least as many confirmations as there are masternodes - if(mn.GetCollateralAge() < nMnCount) continue; + if(GetUTXOConfirmations(mn.vin.prevout) < nMnCount) continue; vecMasternodeLastPaid.push_back(std::make_pair(mn.GetLastPaidBlock(), &mn)); } diff --git a/src/privatesend-server.cpp b/src/privatesend-server.cpp index 8a3b58e119bbd..43ca47d9bf8fa 100644 --- a/src/privatesend-server.cpp +++ b/src/privatesend-server.cpp @@ -195,11 +195,9 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, std::string& strCommand, C LogPrint("privatesend", "DSVIN -- txin=%s\n", txin.ToString()); - CTransaction txPrev; - uint256 hash; - if(GetTransaction(txin.prevout.hash, txPrev, Params().GetConsensus(), hash, true)) { - if(txPrev.vout.size() > txin.prevout.n) - nValueIn += txPrev.vout[txin.prevout.n].nValue; + CCoins coins; + if(GetUTXOCoins(txin.prevout, coins)) { + nValueIn += coins.vout[txin.prevout.n].nValue; } else { LogPrintf("DSVIN -- missing input! tx=%s", tx.ToString()); PushStatus(pfrom, STATUS_REJECTED, ERR_MISSING_TX); diff --git a/src/privatesend.cpp b/src/privatesend.cpp index bc2503417da40..30771182eedfb 100644 --- a/src/privatesend.cpp +++ b/src/privatesend.cpp @@ -178,7 +178,6 @@ bool CPrivateSend::IsCollateralValid(const CTransaction& txCollateral) CAmount nValueIn = 0; CAmount nValueOut = 0; - bool fMissingTx = false; BOOST_FOREACH(const CTxOut txout, txCollateral.vout) { nValueOut += txout.nValue; @@ -190,19 +189,12 @@ bool CPrivateSend::IsCollateralValid(const CTransaction& txCollateral) } BOOST_FOREACH(const CTxIn txin, txCollateral.vin) { - CTransaction txPrev; - uint256 hash; - if(GetTransaction(txin.prevout.hash, txPrev, Params().GetConsensus(), hash, true)) { - if(txPrev.vout.size() > txin.prevout.n) - nValueIn += txPrev.vout[txin.prevout.n].nValue; - } else { - fMissingTx = true; + CCoins coins; + if(!GetUTXOCoins(txin.prevout, coins)) { + LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s", txCollateral.ToString()); + return false; } - } - - if(fMissingTx) { - LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s", txCollateral.ToString()); - return false; + nValueIn += coins.vout[txin.prevout.n].nValue; } //collateral transactions are required to pay out a small fee to the miners diff --git a/src/validation.cpp b/src/validation.cpp index 39e954715a69b..b904c7dcbea68 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -437,55 +437,27 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in return nSigOps; } -int GetUTXOHeight(const COutPoint& outpoint) +bool GetUTXOCoins(const COutPoint& outpoint, CCoins& coins) { LOCK(cs_main); - CCoins coins; - if(!pcoinsTip->GetCoins(outpoint.hash, coins) || - (unsigned int)outpoint.n>=coins.vout.size() || - coins.vout[outpoint.n].IsNull()) { - return -1; - } - return coins.nHeight; -} - -int GetInputAge(const CTxIn &txin) -{ - CCoinsView viewDummy; - CCoinsViewCache view(&viewDummy); - { - LOCK(mempool.cs); - CCoinsViewMemPool viewMempool(pcoinsTip, mempool); - view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view - - const CCoins* coins = view.AccessCoins(txin.prevout.hash); - - if (coins) { - if(coins->nHeight < 0) return 0; - return chainActive.Height() - coins->nHeight + 1; - } else { - return -1; - } - } + return !(!pcoinsTip->GetCoins(outpoint.hash, coins) || + (unsigned int)outpoint.n>=coins.vout.size() || + coins.vout[outpoint.n].IsNull()); } -int GetInputAgeIX(const uint256 &nTXHash, const CTxIn &txin) +int GetUTXOHeight(const COutPoint& outpoint) { - int nResult = GetInputAge(txin); - if(nResult < 0) return -1; - - if (nResult < 6 && instantsend.IsLockedInstantSendTransaction(nTXHash)) - return nInstantSendDepth + nResult; - - return nResult; + // -1 means UTXO is yet unknown or already spent + CCoins coins; + return GetUTXOCoins(outpoint, coins) ? coins.nHeight : -1; } -int GetIXConfirmations(const uint256 &nTXHash) +int GetUTXOConfirmations(const COutPoint& outpoint) { - if (instantsend.IsLockedInstantSendTransaction(nTXHash)) - return nInstantSendDepth; - - return 0; + // -1 means UTXO is yet unknown or already spent + LOCK(cs_main); + int nPrevoutHeight = GetUTXOHeight(outpoint); + return (nPrevoutHeight > -1 && chainActive.Tip()) ? chainActive.Height() - nPrevoutHeight + 1 : -1; } diff --git a/src/validation.h b/src/validation.h index be1e4acc58c1b..3f9c01e456542 100644 --- a/src/validation.h +++ b/src/validation.h @@ -291,10 +291,9 @@ void PruneAndFlush(); bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs, bool fOverrideMempoolLimit=false, bool fRejectAbsurdFee=false, bool fDryRun=false); +bool GetUTXOCoins(const COutPoint& outpoint, CCoins& coins); int GetUTXOHeight(const COutPoint& outpoint); -int GetInputAge(const CTxIn &txin); -int GetInputAgeIX(const uint256 &nTXHash, const CTxIn &txin); -int GetIXConfirmations(const uint256 &nTXHash); +int GetUTXOConfirmations(const COutPoint& outpoint); /** Convert CValidationState to a human-readable message for logging */ std::string FormatStateMessage(const CValidationState &state); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c37be19b652b5..becdf0a3753a0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -9,7 +9,7 @@ #include "chain.h" #include "core_io.h" #include "init.h" -#include "validation.h" +#include "instantx.h" #include "net.h" #include "netbase.h" #include "policy/rbf.h" @@ -17,6 +17,7 @@ #include "timedata.h" #include "util.h" #include "utilmoneystr.h" +#include "validation.h" #include "wallet.h" #include "walletdb.h" #include "keepass.h" @@ -60,7 +61,7 @@ void EnsureWalletIsUnlocked() void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) { int confirms = wtx.GetDepthInMainChain(false); - int confirmsTotal = GetIXConfirmations(wtx.GetHash()) + confirms; + int confirmsTotal = instantsend.GetConfirmations(wtx.GetHash()) + confirms; entry.push_back(Pair("confirmations", confirmsTotal)); entry.push_back(Pair("bcconfirmations", confirms)); if (wtx.IsCoinBase())