diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 43383681f9..5d8f856ddc 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -540,9 +540,9 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu CTransactionRef tx; uint256 hashBlock; // this relies on enabled txindex and won't work if we ever try to remove the requirement for txindex for masternodes - if (!GetTransaction(outpoint.hash, tx, params, hashBlock, false)) { + if (!GetTransaction(outpoint.hash, tx, params, hashBlock, false) || hashBlock.IsNull()) { if (printDebug) { - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: failed to find parent TX %s\n", __func__, + LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: failed to find mined parent TX %s\n", __func__, txHash.ToString(), outpoint.hash.ToString()); } return false; diff --git a/src/llmq/quorums_instantsend.h b/src/llmq/quorums_instantsend.h index 2cc0722c7b..2fb579ac8e 100644 --- a/src/llmq/quorums_instantsend.h +++ b/src/llmq/quorums_instantsend.h @@ -74,6 +74,8 @@ class CInstantSendDb class CInstantSendManager : public CRecoveredSigsListener { + friend struct CInstantSendManagerTestAccess; + private: CCriticalSection cs; CInstantSendDb db; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 6408280c81..9898fd7d08 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -50,6 +50,7 @@ add_executable(test_firo ${CMAKE_CURRENT_SOURCE_DIR}/limitedmap_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/logging_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/llmq_signing_shares_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/quorums_instantsend_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mbstring_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mempool_tests.cpp diff --git a/src/test/quorums_instantsend_tests.cpp b/src/test/quorums_instantsend_tests.cpp new file mode 100644 index 0000000000..5f603fca50 --- /dev/null +++ b/src/test/quorums_instantsend_tests.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2026 The Firo developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "chainparams.h" +#include "llmq/quorums_instantsend.h" +#include "test/test_bitcoin.h" +#include "validation.h" + +#include + +namespace llmq +{ +struct CInstantSendManagerTestAccess +{ + static bool CheckCanLock(CInstantSendManager& manager, const COutPoint& outpoint) + { + return manager.CheckCanLock(outpoint, false, uint256(), nullptr, Params().GetConsensus()); + } +}; + +BOOST_FIXTURE_TEST_SUITE(quorums_instantsend_tests, TestingSetup) + +BOOST_AUTO_TEST_CASE(stem_parent_is_not_treated_as_mined) +{ + CMutableTransaction parent; + parent.vin.resize(1); + parent.vin[0].scriptSig = CScript() << OP_11; + parent.vout.resize(1); + parent.vout[0].nValue = 1; + parent.vout[0].scriptPubKey = CScript() << OP_TRUE; + + txpools.clear(); + TestMemPoolEntryHelper entry; + txpools.getStemTxPool().addUnchecked(parent.GetHash(), entry.FromTx(parent)); + + BOOST_REQUIRE(!mempool.exists(parent.GetHash())); + BOOST_REQUIRE(txpools.getStemTxPool().exists(parent.GetHash())); + BOOST_CHECK(!CInstantSendManagerTestAccess::CheckCanLock( + *quorumInstantSendManager, COutPoint(parent.GetHash(), 0))); + + txpools.clear(); +} + +BOOST_AUTO_TEST_SUITE_END() +}