aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.cpp29
-rw-r--r--src/main.h13
-rw-r--r--src/miner.cpp3
-rw-r--r--src/qt/transactiondesc.cpp2
-rw-r--r--src/qt/transactionrecord.cpp2
-rw-r--r--src/test/miner_tests.cpp10
-rw-r--r--src/wallet/rpcwallet.cpp8
-rw-r--r--src/wallet/wallet.cpp10
8 files changed, 39 insertions, 38 deletions
diff --git a/src/main.cpp b/src/main.cpp
index d3956fafda..9eec21edd9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -658,14 +658,8 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
- AssertLockHeld(cs_main);
- // Time based nLockTime implemented in 0.1.6
if (tx.nLockTime == 0)
return true;
- if (nBlockHeight == 0)
- nBlockHeight = chainActive.Height();
- if (nBlockTime == 0)
- nBlockTime = GetAdjustedTime();
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
return true;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
@@ -674,6 +668,12 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
}
+bool CheckFinalTx(const CTransaction &tx)
+{
+ AssertLockHeld(cs_main);
+ return IsFinalTx(tx, chainActive.Height() + 1, GetAdjustedTime());
+}
+
/**
* Check transaction inputs to mitigate two
* potential denial-of-service attacks:
@@ -890,21 +890,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
- //
- // However, IsFinalTx() is confusing... Without arguments, it uses
- // chainActive.Height() to evaluate nLockTime; when a block is accepted,
- // chainActive.Height() is set to the value of nHeight in the block.
- // However, when IsFinalTx() is called within CBlock::AcceptBlock(), the
- // height of the block *being* evaluated is what is used. Thus if we want
- // to know if a transaction can be part of the *next* block, we need to
- // call IsFinalTx() with one more than chainActive.Height().
- //
- // Timestamps on the other hand don't get any special treatment, because we
- // can't know what timestamp the next block will have, and there aren't
- // timestamp applications where it matters.
- if (!IsFinalTx(tx, chainActive.Height() + 1))
- return state.DoS(0,
- error("AcceptToMemoryPool: non-final"),
+ if (!CheckFinalTx(tx))
+ return state.DoS(0, error("AcceptToMemoryPool: non-final"),
REJECT_NONSTANDARD, "non-final");
// is it already in the memory pool?
diff --git a/src/main.h b/src/main.h
index 07a709b75c..b789ea95e8 100644
--- a/src/main.h
+++ b/src/main.h
@@ -334,7 +334,18 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state);
*/
bool IsStandardTx(const CTransaction& tx, std::string& reason);
-bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0);
+/**
+ * Check if transaction is final and can be included in a block with the
+ * specified height and time. Consensus critical.
+ */
+bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
+
+/**
+ * Check if transaction will be final in the next block to be created.
+ *
+ * Calls IsFinalTx() with current block height and appropriate block time.
+ */
+bool CheckFinalTx(const CTransaction &tx);
/**
* Closure representing one script verification
diff --git a/src/miner.cpp b/src/miner.cpp
index 804a688523..fb417ac628 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -137,6 +137,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1;
+ pblock->nTime = GetAdjustedTime();
CCoinsViewCache view(pcoinsTip);
// Priority order to process transactions
@@ -151,7 +152,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
mi != mempool.mapTx.end(); ++mi)
{
const CTransaction& tx = mi->second.GetTx();
- if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight))
+ if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime))
continue;
COrphan* porphan = NULL;
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 4fffd03adf..5662b16657 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -26,7 +26,7 @@ using namespace std;
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
AssertLockHeld(cs_main);
- if (!IsFinalTx(wtx, chainActive.Height() + 1))
+ if (!CheckFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height());
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 7f1db58e5d..15d13e9fc9 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -188,7 +188,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.depth = wtx.GetDepthInMainChain();
status.cur_num_blocks = chainActive.Height();
- if (!IsFinalTx(wtx, chainActive.Height() + 1))
+ if (!CheckFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
{
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index d7ea91607c..4ceda04622 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = chainActive.Tip()->nHeight+1;
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(!IsFinalTx(tx, chainActive.Tip()->nHeight + 1));
+ BOOST_CHECK(!CheckFinalTx(tx));
// time locked
tx2.vin.resize(1);
@@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx2.nLockTime = chainActive.Tip()->GetMedianTimePast()+1;
hash = tx2.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx2, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(!IsFinalTx(tx2));
+ BOOST_CHECK(!CheckFinalTx(tx2));
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
@@ -248,8 +248,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
chainActive.Tip()->nHeight++;
SetMockTime(chainActive.Tip()->GetMedianTimePast()+2);
- BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 1));
- BOOST_CHECK(IsFinalTx(tx2));
+ // FIXME: we should *actually* create a new block so the following test
+ // works; CheckFinalTx() isn't fooled by monkey-patching nHeight.
+ //BOOST_CHECK(CheckFinalTx(tx));
+ //BOOST_CHECK(CheckFinalTx(tx2));
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3);
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index dd5240e3c0..3f55b04273 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -588,7 +588,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -642,7 +642,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -666,7 +666,7 @@ CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
+ if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
continue;
CAmount nReceived, nSent, nFee;
@@ -1109,7 +1109,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
int nDepth = wtx.GetDepthInMainChain();
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 3396a3a188..94687d289f 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1317,7 +1317,7 @@ CAmount CWalletTx::GetChange() const
bool CWalletTx::IsTrusted() const
{
// Quick answer in most cases
- if (!IsFinalTx(*this))
+ if (!CheckFinalTx(*this))
return false;
int nDepth = GetDepthInMainChain();
if (nDepth >= 1)
@@ -1423,7 +1423,7 @@ CAmount CWallet::GetUnconfirmedBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
+ if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
nTotal += pcoin->GetAvailableCredit();
}
}
@@ -1468,7 +1468,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
+ if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
}
@@ -1503,7 +1503,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
const uint256& wtxid = it->first;
const CWalletTx* pcoin = &(*it).second;
- if (!IsFinalTx(*pcoin))
+ if (!CheckFinalTx(*pcoin))
continue;
if (fOnlyConfirmed && !pcoin->IsTrusted())
@@ -2290,7 +2290,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
{
CWalletTx *pcoin = &walletEntry.second;
- if (!IsFinalTx(*pcoin) || !pcoin->IsTrusted())
+ if (!CheckFinalTx(*pcoin) || !pcoin->IsTrusted())
continue;
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)