diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -37,8 +37,10 @@ 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) { - return CheckSequenceLocks(m_node.chainman->ActiveChainstate(), - *m_node.mempool, tx, flags); + CCoinsViewMemPool viewMempool( + &m_node.chainman->ActiveChainstate().CoinsTip(), *m_node.mempool); + return CheckSequenceLocks(m_node.chainman->ActiveChain().Tip(), + viewMempool, tx, flags); } BlockAssembler AssemblerForTest(const CChainParams ¶ms); }; diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -584,13 +584,14 @@ const CTransaction &tx = it->GetTx(); LockPoints lp = it->GetLockPoints(); bool validLP = TestLockPointValidity(active_chainstate.m_chain, &lp); + CCoinsViewMemPool viewMempool(&active_chainstate.CoinsTip(), *this); TxValidationState state; if (!ContextualCheckTransactionForCurrentBlock( active_chainstate.m_chain.Tip(), config.GetChainParams().GetConsensus(), tx, state, flags) || - !CheckSequenceLocks(active_chainstate, *this, tx, flags, &lp, - validLP)) { + !CheckSequenceLocks(active_chainstate.m_chain.Tip(), viewMempool, + tx, flags, &lp, validLP)) { // Note if CheckSequenceLocks fails the LockPoints may still be // invalid. So it's critical that we remove the tx and not depend on // the LockPoints. diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -423,21 +423,25 @@ EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** - * Check if transaction will be BIP 68 final in the next block to be created. - * - * Simulates calling SequenceLocks() with data from the tip of the current - * active chain. Optionally stores in LockPoints the resulting height and time + * Check if transaction will be BIP68 final in the next block to be created on + * top of tip. + * @param[in] tip Chain tip to check tx sequence locks against. + * For example, the tip of the current active chain. + * @param[in] coins_view Any CCoinsView that provides access to the + * relevant coins for checking sequence locks. Any CCoinsView can be passed + * in; it is assumed to be consistent with the tip. + * Simulates calling SequenceLocks() with data from the tip passed in. + * 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. */ -bool CheckSequenceLocks(CChainState &active_chainstate, const CTxMemPool &pool, +bool CheckSequenceLocks(CBlockIndex *tip, const CCoinsView &coins_view, const CTransaction &tx, int flags, LockPoints *lp = nullptr, - bool useExistingLockPoints = false) - EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs); + bool useExistingLockPoints = false); /** * Closure representing one script verification. diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -174,13 +174,9 @@ return true; } -bool CheckSequenceLocks(CChainState &active_chainstate, const CTxMemPool &pool, +bool CheckSequenceLocks(CBlockIndex *tip, const CCoinsView &coins_view, const CTransaction &tx, int flags, LockPoints *lp, bool useExistingLockPoints) { - AssertLockHeld(cs_main); - AssertLockHeld(pool.cs); - - CBlockIndex *tip = active_chainstate.m_chain.Tip(); assert(tip != nullptr); CBlockIndex index; @@ -198,14 +194,12 @@ lockPair.first = lp->height; lockPair.second = lp->time; } else { - // CoinsTip() contains the UTXO set for active_chainstate.m_chain.Tip() - CCoinsViewMemPool viewMemPool(&active_chainstate.CoinsTip(), pool); std::vector prevheights; prevheights.resize(tx.vin.size()); for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { const CTxIn &txin = tx.vin[txinIndex]; Coin coin; - if (!viewMemPool.GetCoin(txin.prevout, coin)) { + if (!coins_view.GetCoin(txin.prevout, coin)) { return error("%s: Missing input", __func__); } if (coin.GetHeight() == MEMPOOL_HEIGHT) { @@ -525,10 +519,11 @@ // Only accept BIP68 sequence locked 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. Must keep pool.cs for this unless we change - // CheckSequenceLocks to take a CoinsViewCache instead of create its - // own. - if (!CheckSequenceLocks(m_active_chainstate, m_pool, tx, + // that can't 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)) { return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");