From 1c63052c3e12de166e48281f26a725b60dbb722e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 2 Mar 2017 00:30:43 +0400 Subject: [PATCH] fix recently observed crash on IsValid (#1375) * fix recently observed crash on IsValid +some small cleanup * txin.prevout.n should not exceed txOutpointCreated.vout.size() * fix log output --- src/instantx.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index 8c8bb1a5a..899ab1378 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -848,8 +848,8 @@ bool CTxLockRequest::IsValid(bool fRequireUnspent) const return false; } - int64_t nValueIn = 0; - int64_t nValueOut = 0; + CAmount nValueIn = 0; + CAmount nValueOut = 0; BOOST_FOREACH(const CTxOut& txout, vout) { // InstantSend supports normal scripts and unspendable (i.e. data) scripts. @@ -865,6 +865,8 @@ bool CTxLockRequest::IsValid(bool fRequireUnspent) const CCoins coins; 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()) { @@ -875,20 +877,29 @@ bool CTxLockRequest::IsValid(bool fRequireUnspent) const CTransaction txOutpointCreated; uint256 nHashOutpointConfirmed; if(!GetTransaction(txin.prevout.hash, txOutpointCreated, Params().GetConsensus(), nHashOutpointConfirmed, true) || nHashOutpointConfirmed == uint256()) { - LogPrint("instantsend", "txLockRequest::IsValid -- Failed to find outpoint %s\n", txin.prevout.ToStringShort()); + LogPrint("instantsend", "CTxLockRequest::IsValid -- Failed to find outpoint %s\n", txin.prevout.ToStringShort()); + return false; + } + if(txin.prevout.n >= txOutpointCreated.vout.size()) { + LogPrint("instantsend", "CTxLockRequest::IsValid -- Outpoint %s is out of bounds, size() = %lld\n", + txin.prevout.ToStringShort(), txOutpointCreated.vout.size()); return false; } - LOCK(cs_main); BlockMap::iterator mi = mapBlockIndex.find(nHashOutpointConfirmed); - if(mi == mapBlockIndex.end()) { - // not on this chain? - LogPrint("instantsend", "txLockRequest::IsValid -- Failed to find block %s for outpoint %s\n", nHashOutpointConfirmed.ToString(), txin.prevout.ToStringShort()); + if(mi == mapBlockIndex.end() || !mi->second) { + // shouldn't happen + LogPrint("instantsend", "CTxLockRequest::IsValid -- Failed to find block %s for outpoint %s\n", + nHashOutpointConfirmed.ToString(), txin.prevout.ToStringShort()); return false; } - nPrevoutHeight = mi->second ? mi->second->nHeight : 0; + nPrevoutHeight = mi->second->nHeight; + nValue = txOutpointCreated.vout[txin.prevout.n].nValue; + } else { + nPrevoutHeight = coins.nHeight; + nValue = coins.vout[txin.prevout.n].nValue; } - int nTxAge = chainActive.Height() - (nPrevoutHeight ? nPrevoutHeight : coins.nHeight) + 1; + int nTxAge = chainActive.Height() - nPrevoutHeight + 1; // 1 less than the "send IX" gui requires, in case of a block propagating the network at the time int nConfirmationsRequired = INSTANTSEND_CONFIRMATIONS_REQUIRED - 1; @@ -898,7 +909,7 @@ bool CTxLockRequest::IsValid(bool fRequireUnspent) const return false; } - nValueIn += coins.vout[txin.prevout.n].nValue; + nValueIn += nValue; } if(nValueOut > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) {