merge bitcoin#24080: Remove unused locktime flags

This commit is contained in:
Kittywhiskers Van Gogh 2022-01-11 17:02:23 +01:00
parent 536c4e1b27
commit 1c1fcc60a8
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
4 changed files with 39 additions and 55 deletions

View File

@ -767,7 +767,7 @@ public:
bool checkFinalTx(const CTransaction& tx) override bool checkFinalTx(const CTransaction& tx) override
{ {
LOCK(cs_main); LOCK(cs_main);
return CheckFinalTx(m_node.chainman->ActiveChain().Tip(), tx); return CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), tx);
} }
bool isInstantSendLockedTx(const uint256& hash) override bool isInstantSendLockedTx(const uint256& hash) override
{ {

View File

@ -34,10 +34,10 @@
namespace miner_tests { namespace miner_tests {
struct MinerTestingSetup : public TestingSetup { struct MinerTestingSetup : public TestingSetup {
void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs); void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
bool TestSequenceLocks(const CTransaction& tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs) bool TestSequenceLocks(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs)
{ {
CCoinsViewMemPool view_mempool(&m_node.chainman->ActiveChainstate().CoinsTip(), *m_node.mempool); CCoinsViewMemPool view_mempool(&m_node.chainman->ActiveChainstate().CoinsTip(), *m_node.mempool);
return CheckSequenceLocks(m_node.chainman->ActiveChain().Tip(), view_mempool, tx, flags); return CheckSequenceLocksAtTip(m_node.chainman->ActiveChain().Tip(), view_mempool, tx);
} }
BlockAssembler AssemblerForTest(const CChainParams& params); BlockAssembler AssemblerForTest(const CChainParams& params);
}; };
@ -429,7 +429,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// non-final txs in mempool // non-final txs in mempool
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1); SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1);
int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST; const int flags{LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST};
// height map // height map
std::vector<int> prevheights; std::vector<int> prevheights;
@ -448,8 +448,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = 0; tx.nLockTime = 0;
hash = tx.GetHash(); hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
{ {
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip(); CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
@ -462,8 +462,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = baseheight + 2; prevheights[0] = baseheight + 2;
hash = tx.GetHash(); hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx)); m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
@ -483,8 +483,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1; tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
hash = tx.GetHash(); hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx)); m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
// absolute time locked // absolute time locked
@ -494,8 +494,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = baseheight + 4; prevheights[0] = baseheight + 4;
hash = tx.GetHash(); hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx)); m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
// mempool-dependent transactions (not added) // mempool-dependent transactions (not added)
@ -503,14 +503,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1; prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
tx.nLockTime = 0; tx.nLockTime = 0;
tx.vin[0].nSequence = 0; tx.vin[0].nSequence = 0;
BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
tx.vin[0].nSequence = 1; tx.vin[0].nSequence = 1;
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG; tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1; tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));

View File

@ -145,20 +145,12 @@ const CBlockIndex* CChainState::FindForkInGlobalIndex(const CBlockLocator& locat
bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = nullptr); bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = nullptr);
bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, int flags) bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction& tx)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
assert(active_chain_tip); // TODO: Make active_chain_tip a reference assert(active_chain_tip); // TODO: Make active_chain_tip a reference
// By convention a negative value for flags indicates that the // CheckFinalTxAtTip() uses active_chain_tip.Height()+1 to evaluate
// current network-enforced consensus rules should be used. In
// a future soft-fork scenario that would mean checking which
// rules would be enforced for the next block and setting the
// appropriate flags. At the present time no soft-forks are
// scheduled, so no flags are set.
flags = std::max(flags, 0);
// CheckFinalTx() uses active_chain_tip.Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within // nLockTime because when IsFinalTx() is called within
// AcceptBlock(), the height of the block *being* // AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a // evaluated is what is used. Thus if we want to know if a
@ -170,18 +162,15 @@ bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, i
// less than the median time of the previous block they're contained in. // less than the median time of the previous block they're contained in.
// When the next block is created its previous block will be the current // When the next block is created its previous block will be the current
// chain tip, so we use that to calculate the median time passed to // chain tip, so we use that to calculate the median time passed to
// IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set. // IsFinalTx().
const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST) const int64_t nBlockTime{active_chain_tip->GetMedianTimePast()};
? active_chain_tip->GetMedianTimePast()
: GetAdjustedTime();
return IsFinalTx(tx, nBlockHeight, nBlockTime); return IsFinalTx(tx, nBlockHeight, nBlockTime);
} }
bool CheckSequenceLocks(CBlockIndex* tip, bool CheckSequenceLocksAtTip(CBlockIndex* tip,
const CCoinsView& coins_view, const CCoinsView& coins_view,
const CTransaction& tx, const CTransaction& tx,
int flags,
LockPoints* lp, LockPoints* lp,
bool useExistingLockPoints) bool useExistingLockPoints)
{ {
@ -189,7 +178,7 @@ bool CheckSequenceLocks(CBlockIndex* tip,
CBlockIndex index; CBlockIndex index;
index.pprev = tip; index.pprev = tip;
// CheckSequenceLocks() uses active_chainstate.m_chain.Height()+1 to evaluate // CheckSequenceLocksAtTip() uses active_chainstate.m_chain.Height()+1 to evaluate
// height based locks because when SequenceLocks() is called within // height based locks because when SequenceLocks() is called within
// ConnectBlock(), the height of the block *being* // ConnectBlock(), the height of the block *being*
// evaluated is what is used. // evaluated is what is used.
@ -219,7 +208,7 @@ bool CheckSequenceLocks(CBlockIndex* tip,
prevheights[txinIndex] = coin.nHeight; prevheights[txinIndex] = coin.nHeight;
} }
} }
lockPair = CalculateSequenceLocks(tx, flags, prevheights, index); lockPair = CalculateSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, prevheights, index);
if (lp) { if (lp) {
lp->height = lockPair.first; lp->height = lockPair.first;
lp->time = lockPair.second; lp->time = lockPair.second;
@ -235,7 +224,7 @@ bool CheckSequenceLocks(CBlockIndex* tip,
// lockPair from CalculateSequenceLocks against tip+1. We know // lockPair from CalculateSequenceLocks against tip+1. We know
// EvaluateSequenceLocks will fail if there was a non-zero sequence // EvaluateSequenceLocks will fail if there was a non-zero sequence
// lock on a mempool input, so we can use the return value of // lock on a mempool input, so we can use the return value of
// CheckSequenceLocks to indicate the LockPoints validity // CheckSequenceLocksAtTip to indicate the LockPoints validity
int maxInputHeight = 0; int maxInputHeight = 0;
for (const int height : prevheights) { for (const int height : prevheights) {
// Can ignore mempool inputs since we'll fail if they had non-zero locks // Can ignore mempool inputs since we'll fail if they had non-zero locks
@ -384,26 +373,26 @@ void CChainState::MaybeUpdateMempoolForReorg(
// Also updates valid entries' cached LockPoints if needed. // Also updates valid entries' cached LockPoints if needed.
// If false, the tx is still valid and its lockpoints are updated. // If false, the tx is still valid and its lockpoints are updated.
// If true, the tx would be invalid in the next block; remove this entry and all of its descendants. // If true, the tx would be invalid in the next block; remove this entry and all of its descendants.
const auto filter_final_and_mature = [this, flags=STANDARD_LOCKTIME_VERIFY_FLAGS](CTxMemPool::txiter it) const auto filter_final_and_mature = [this](CTxMemPool::txiter it)
EXCLUSIVE_LOCKS_REQUIRED(m_mempool->cs, ::cs_main) { EXCLUSIVE_LOCKS_REQUIRED(m_mempool->cs, ::cs_main) {
AssertLockHeld(m_mempool->cs); AssertLockHeld(m_mempool->cs);
AssertLockHeld(::cs_main); AssertLockHeld(::cs_main);
const CTransaction& tx = it->GetTx(); const CTransaction& tx = it->GetTx();
// The transaction must be final. // The transaction must be final.
if (!CheckFinalTx(m_chain.Tip(), tx, flags)) return true; if (!CheckFinalTxAtTip(m_chain.Tip(), tx)) return true;
LockPoints lp = it->GetLockPoints(); LockPoints lp = it->GetLockPoints();
const bool validLP{TestLockPointValidity(m_chain, lp)}; const bool validLP{TestLockPointValidity(m_chain, lp)};
CCoinsViewMemPool view_mempool(&CoinsTip(), *m_mempool); CCoinsViewMemPool view_mempool(&CoinsTip(), *m_mempool);
// CheckSequenceLocks checks if the transaction will be final in the next block to be // CheckSequenceLocksAtTip checks if the transaction will be final in the next block to be
// created on top of the new chain. We use useExistingLockPoints=false so that, instead of // created on top of the new chain. We use useExistingLockPoints=false so that, instead of
// using the information in lp (which might now refer to a block that no longer exists in // using the information in lp (which might now refer to a block that no longer exists in
// the chain), it will update lp to contain LockPoints relevant to the new chain. // the chain), it will update lp to contain LockPoints relevant to the new chain.
if (!CheckSequenceLocks(m_chain.Tip(), view_mempool, tx, flags, &lp, validLP)) { if (!CheckSequenceLocksAtTip(m_chain.Tip(), view_mempool, tx, &lp, validLP)) {
// If CheckSequenceLocks fails, remove the tx and don't depend on the LockPoints. // If CheckSequenceLocksAtTip fails, remove the tx and don't depend on the LockPoints.
return true; return true;
} else if (!validLP) { } else if (!validLP) {
// If CheckSequenceLocks succeeded, it also updated the LockPoints. // If CheckSequenceLocksAtTip succeeded, it also updated the LockPoints.
// Now update the mempool entry lockpoints as well. // Now update the mempool entry lockpoints as well.
m_mempool->mapTx.modify(it, [&lp](CTxMemPoolEntry& e) { e.UpdateLockPoints(lp); }); m_mempool->mapTx.modify(it, [&lp](CTxMemPoolEntry& e) { e.UpdateLockPoints(lp); });
} }
@ -643,8 +632,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Only accept nLockTime-using transactions that can be mined in the next // 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 // block; we don't want our mempool filled up with transactions that can't
// be mined yet. // be mined yet.
if (!CheckFinalTx(m_active_chainstate.m_chain.Tip(), tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) if (!CheckFinalTxAtTip(m_active_chainstate.m_chain.Tip(), tx)) {
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final"); return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
}
// is it already in the memory pool? // is it already in the memory pool?
if (m_pool.exists(hash)) { if (m_pool.exists(hash)) {
@ -720,8 +710,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// be mined yet. // be mined yet.
// Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's // Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
// backend was removed, it no longer pulls coins from the mempool. // backend was removed, it no longer pulls coins from the mempool.
if (!CheckSequenceLocks(m_active_chainstate.m_chain.Tip(), m_view, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) if (!CheckSequenceLocksAtTip(m_active_chainstate.m_chain.Tip(), m_view, tx, &lp)) {
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final"); return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
}
// The mempool holds txs for the next block, so pass height+1 to CheckTxInputs // The mempool holds txs for the next block, so pass height+1 to CheckTxInputs
if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_chain.Height() + 1, ws.m_base_fees)) { if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_chain.Height() + 1, ws.m_base_fees)) {

View File

@ -275,16 +275,12 @@ bool GetUTXOCoin(CChainState& active_chainstate, const COutPoint& outpoint, Coin
int GetUTXOHeight(CChainState& active_chainstate, const COutPoint& outpoint); int GetUTXOHeight(CChainState& active_chainstate, const COutPoint& outpoint);
int GetUTXOConfirmations(CChainState& active_chainstate, const COutPoint& outpoint); int GetUTXOConfirmations(CChainState& active_chainstate, const COutPoint& outpoint);
/** Transaction validation functions */ /* Transaction policy functions */
/** /**
* Check if transaction will be final in the next block to be created. * Check if transaction will be final in the next block to be created.
*
* Calls IsFinalTx() with current block height and appropriate block time.
*
* See consensus/consensus.h for flag definitions.
*/ */
bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, int flags = -1) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** /**
* Check if transaction will be BIP68 final in the next block to be created on top of tip. * Check if transaction will be BIP68 final in the next block to be created on top of tip.
@ -301,14 +297,11 @@ bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, i
* Optionally stores in LockPoints the resulting height and time calculated and the hash * Optionally stores in LockPoints the resulting height and time calculated and the hash
* of the block needed for calculation or skips the calculation and uses the LockPoints * of the block needed for calculation or skips the calculation and uses the LockPoints
* passed in for evaluation. * passed in for evaluation.
* The LockPoints should not be considered valid if CheckSequenceLocks returns false. * The LockPoints should not be considered valid if CheckSequenceLocksAtTip returns false.
*
* See consensus/consensus.h for flag definitions.
*/ */
bool CheckSequenceLocks(CBlockIndex* tip, bool CheckSequenceLocksAtTip(CBlockIndex* tip,
const CCoinsView& coins_view, const CCoinsView& coins_view,
const CTransaction& tx, const CTransaction& tx,
int flags,
LockPoints* lp = nullptr, LockPoints* lp = nullptr,
bool useExistingLockPoints = false); bool useExistingLockPoints = false);