aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2022-03-14 16:32:17 +0100
committerMarcoFalke <falke.marco@gmail.com>2022-03-14 16:32:23 +0100
commit28bdaa3f7697eef6c3d97e952228ce92e5d18aae (patch)
tree475eca8b12f55c009f0562e3a7a9549d9a23131d /src
parent25d045a9ecc24a2752685d176c28f8f75bb100f6 (diff)
parentfa8d4d9128c35de0fe715f2e2b99269d23c09cc1 (diff)
downloadbitcoin-28bdaa3f7697eef6c3d97e952228ce92e5d18aae.tar.xz
Merge bitcoin/bitcoin#24080: policy: Remove unused locktime flags
fa8d4d9128c35de0fe715f2e2b99269d23c09cc1 scripted-diff: Clarify CheckFinalTxAtTip name (MarcoFalke) fa4e30b0f36f2e7a09db7d30dca9008ed9dbcb35 policy: Remove unused locktime flags (MarcoFalke) Pull request description: The locktime flags have many issues: * They are passed in by a default argument, which is fragile. It has already lead to bugs like the one fixed in commit e30b6ea194fee3bb95a45e7b732a99566b88f1f5. * They are negative (signed), which doesn't make sense for flags (unsigned in general). According to the review comments when the code was added: "The max on the flags is a fairly weird operation." (https://github.com/bitcoin/bitcoin/pull/6566#issuecomment-150310861) * No call site relies on the default argument and they all pass in a single compile-time constant, rendering most of the code dead and untested. * The dead code calls `GetAdjustedTime` (network adjusted time), which has its own issues. See https://github.com/bitcoin/bitcoin/issues/4521 Fix all issues by removing them ACKs for top commit: ajtowns: ACK fa8d4d9128c35de0fe715f2e2b99269d23c09cc1 theStack: Code-review ACK fa8d4d9128c35de0fe715f2e2b99269d23c09cc1 glozow: ACK fa8d4d9128c35de0fe715f2e2b99269d23c09cc1, agree the default arg `flags` is a massive footgun and just setting max flags is weird. Adding `AtTip` to the names makes sense to me, since they're both testing for *next* block and only ever used for {,re}addition to mempool. Tree-SHA512: 79f4a52f34909eb598d88bbae7afe8abe5f85f45c128483d16aa83dacd0e5579e561b725d01b1e9a931d1821012a51ad2bc6fb2867f8d09ee541f9d234d696f8
Diffstat (limited to 'src')
-rw-r--r--src/test/miner_tests.cpp32
-rw-r--r--src/validation.cpp45
-rw-r--r--src/validation.h15
3 files changed, 38 insertions, 54 deletions
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index c453dae701..f6c1d1efad 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -30,10 +30,10 @@ using node::CBlockTemplate;
namespace miner_tests {
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);
- 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);
- 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);
};
@@ -410,7 +410,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// non-final txs in mempool
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
std::vector<int> prevheights;
@@ -429,8 +429,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = 0;
hash = tx.GetHash();
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(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
{
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
@@ -443,8 +443,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = baseheight + 2;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
- BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
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
@@ -464,8 +464,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails
- BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ 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
// absolute time locked
@@ -475,8 +475,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = baseheight + 4;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails
- BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ 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
// mempool-dependent transactions (not added)
@@ -484,14 +484,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
tx.nLockTime = 0;
tx.vin[0].nSequence = 0;
- BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
- BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
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;
- 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;
- BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
diff --git a/src/validation.cpp b/src/validation.cpp
index a7360e4b64..8406f65401 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -178,20 +178,12 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
std::vector<CScriptCheck>* pvChecks = nullptr)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-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);
assert(active_chain_tip); // TODO: Make active_chain_tip a reference
- // By convention a negative value for flags indicates that the
- // 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
+ // CheckFinalTxAtTip() uses active_chain_tip.Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within
// AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a
@@ -203,18 +195,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.
// 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
- // IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set.
- const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
- ? active_chain_tip->GetMedianTimePast()
- : GetAdjustedTime();
+ // IsFinalTx().
+ const int64_t nBlockTime{active_chain_tip->GetMedianTimePast()};
return IsFinalTx(tx, nBlockHeight, nBlockTime);
}
-bool CheckSequenceLocks(CBlockIndex* tip,
+bool CheckSequenceLocksAtTip(CBlockIndex* tip,
const CCoinsView& coins_view,
const CTransaction& tx,
- int flags,
LockPoints* lp,
bool useExistingLockPoints)
{
@@ -222,7 +211,7 @@ bool CheckSequenceLocks(CBlockIndex* tip,
CBlockIndex index;
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
// ConnectBlock(), the height of the block *being*
// evaluated is what is used.
@@ -252,7 +241,7 @@ bool CheckSequenceLocks(CBlockIndex* tip,
prevheights[txinIndex] = coin.nHeight;
}
}
- lockPair = CalculateSequenceLocks(tx, flags, prevheights, index);
+ lockPair = CalculateSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, prevheights, index);
if (lp) {
lp->height = lockPair.first;
lp->time = lockPair.second;
@@ -268,7 +257,7 @@ bool CheckSequenceLocks(CBlockIndex* tip,
// lockPair from CalculateSequenceLocks against tip+1. We know
// EvaluateSequenceLocks will fail if there was a non-zero sequence
// 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;
for (const int height : prevheights) {
// Can ignore mempool inputs since we'll fail if they had non-zero locks
@@ -358,26 +347,26 @@ void CChainState::MaybeUpdateMempoolForReorg(
// Also updates valid entries' cached LockPoints if needed.
// 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.
- 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) {
AssertLockHeld(m_mempool->cs);
AssertLockHeld(::cs_main);
const CTransaction& tx = it->GetTx();
// 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();
const bool validLP{TestLockPointValidity(m_chain, lp)};
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
// 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.
- if (!CheckSequenceLocks(m_chain.Tip(), view_mempool, tx, flags, &lp, validLP)) {
- // If CheckSequenceLocks fails, remove the tx and don't depend on the LockPoints.
+ if (!CheckSequenceLocksAtTip(m_chain.Tip(), view_mempool, tx, &lp, validLP)) {
+ // If CheckSequenceLocksAtTip fails, remove the tx and don't depend on the LockPoints.
return true;
} 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.
m_mempool->mapTx.modify(it, [&lp](CTxMemPoolEntry& e) { e.UpdateLockPoints(lp); });
}
@@ -722,8 +711,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// 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.
- 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");
+ }
if (m_pool.exists(GenTxid::Wtxid(tx.GetWitnessHash()))) {
// Exact transaction already exists in the mempool.
@@ -803,8 +793,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// be mined yet.
// 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.
- 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");
+ }
// 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)) {
diff --git a/src/validation.h b/src/validation.h
index cc2247239f..965ed4225e 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -273,16 +273,12 @@ PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTx
const Package& txns, bool test_accept)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/** Transaction validation functions */
+/* Transaction policy functions */
/**
* 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.
@@ -299,14 +295,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
* of the block needed for calculation or skips the calculation and uses the LockPoints
* passed in for evaluation.
- * The LockPoints should not be considered valid if CheckSequenceLocks returns false.
- *
- * See consensus/consensus.h for flag definitions.
+ * The LockPoints should not be considered valid if CheckSequenceLocksAtTip returns false.
*/
-bool CheckSequenceLocks(CBlockIndex* tip,
+bool CheckSequenceLocksAtTip(CBlockIndex* tip,
const CCoinsView& coins_view,
const CTransaction& tx,
- int flags,
LockPoints* lp = nullptr,
bool useExistingLockPoints = false);