Skip to content

Commit 0ea28ba

Browse files
committed
Reject non-final txs even in testnet/regtest
Previous behavior with IsFinalTx() being an IsStandard() rule was rather confusing and interferred with testing of protocols that depended on nLockTime.
1 parent f914f1a commit 0ea28ba

File tree

1 file changed

+20
-23
lines changed

1 file changed

+20
-23
lines changed

src/main.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -620,34 +620,11 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
620620

621621
bool IsStandardTx(const CTransaction& tx, string& reason)
622622
{
623-
AssertLockHeld(cs_main);
624623
if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
625624
reason = "version";
626625
return false;
627626
}
628627

629-
// Treat non-final transactions as non-standard to prevent a specific type
630-
// of double-spend attack, as well as DoS attacks. (if the transaction
631-
// can't be mined, the attacker isn't expending resources broadcasting it)
632-
// Basically we don't want to propagate transactions that can't be included in
633-
// the next block.
634-
//
635-
// However, IsFinalTx() is confusing... Without arguments, it uses
636-
// chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height()
637-
// is set to the value of nHeight in the block. However, when IsFinalTx()
638-
// is called within CBlock::AcceptBlock(), the height of the block *being*
639-
// evaluated is what is used. Thus if we want to know if a transaction can
640-
// be part of the *next* block, we need to call IsFinalTx() with one more
641-
// than chainActive.Height().
642-
//
643-
// Timestamps on the other hand don't get any special treatment, because we
644-
// can't know what timestamp the next block will have, and there aren't
645-
// timestamp applications where it matters.
646-
if (!IsFinalTx(tx, chainActive.Height() + 1)) {
647-
reason = "non-final";
648-
return false;
649-
}
650-
651628
// Extremely large transactions with lots of inputs can cost the network
652629
// almost as much to process as they cost the sender in fees, because
653630
// computing signature hashes is O(ninputs*txsize). Limiting transactions
@@ -936,6 +913,26 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
936913
error("AcceptToMemoryPool : nonstandard transaction: %s", reason),
937914
REJECT_NONSTANDARD, reason);
938915

916+
// Only accept nLockTime-using transactions that can be mined in the next
917+
// block; we don't want our mempool filled up with transactions that can't
918+
// be mined yet.
919+
//
920+
// However, IsFinalTx() is confusing... Without arguments, it uses
921+
// chainActive.Height() to evaluate nLockTime; when a block is accepted,
922+
// chainActive.Height() is set to the value of nHeight in the block.
923+
// However, when IsFinalTx() is called within CBlock::AcceptBlock(), the
924+
// height of the block *being* evaluated is what is used. Thus if we want
925+
// to know if a transaction can be part of the *next* block, we need to
926+
// call IsFinalTx() with one more than chainActive.Height().
927+
//
928+
// Timestamps on the other hand don't get any special treatment, because we
929+
// can't know what timestamp the next block will have, and there aren't
930+
// timestamp applications where it matters.
931+
if (!IsFinalTx(tx, chainActive.Height() + 1))
932+
return state.DoS(0,
933+
error("AcceptToMemoryPool : non-final"),
934+
REJECT_NONSTANDARD, "non-final");
935+
939936
// is it already in the memory pool?
940937
uint256 hash = tx.GetHash();
941938
if (pool.exists(hash))

0 commit comments

Comments
 (0)