@@ -252,10 +252,7 @@ std::optional<LockPoints> CalculateLockPointsAtTip(
252252}
253253
254254bool CheckSequenceLocksAtTip (CBlockIndex* tip,
255- const CCoinsView& coins_view,
256- const CTransaction& tx,
257- LockPoints* lp,
258- bool useExistingLockPoints)
255+ const LockPoints& lock_points)
259256{
260257 assert (tip != nullptr );
261258
@@ -269,61 +266,7 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
269266 // *next* block, we need to use one more than active_chainstate.m_chain.Height()
270267 index.nHeight = tip->nHeight + 1 ;
271268
272- std::pair<int , int64_t > lockPair;
273- if (useExistingLockPoints) {
274- assert (lp);
275- lockPair.first = lp->height ;
276- lockPair.second = lp->time ;
277- }
278- else {
279- std::vector<int > prevheights;
280- prevheights.resize (tx.vin .size ());
281- for (size_t txinIndex = 0 ; txinIndex < tx.vin .size (); txinIndex++) {
282- const CTxIn& txin = tx.vin [txinIndex];
283- Coin coin;
284- if (!coins_view.GetCoin (txin.prevout , coin)) {
285- return error (" %s: Missing input" , __func__);
286- }
287- if (coin.nHeight == MEMPOOL_HEIGHT) {
288- // Assume all mempool transaction confirm in the next block
289- prevheights[txinIndex] = tip->nHeight + 1 ;
290- } else {
291- prevheights[txinIndex] = coin.nHeight ;
292- }
293- }
294- lockPair = CalculateSequenceLocks (tx, STANDARD_LOCKTIME_VERIFY_FLAGS, prevheights, index);
295- if (lp) {
296- lp->height = lockPair.first ;
297- lp->time = lockPair.second ;
298- // Also store the hash of the block with the highest height of
299- // all the blocks which have sequence locked prevouts.
300- // This hash needs to still be on the chain
301- // for these LockPoint calculations to be valid
302- // Note: It is impossible to correctly calculate a maxInputBlock
303- // if any of the sequence locked inputs depend on unconfirmed txs,
304- // except in the special case where the relative lock time/height
305- // is 0, which is equivalent to no sequence lock. Since we assume
306- // input height of tip+1 for mempool txs and test the resulting
307- // lockPair from CalculateSequenceLocks against tip+1. We know
308- // EvaluateSequenceLocks will fail if there was a non-zero sequence
309- // lock on a mempool input, so we can use the return value of
310- // CheckSequenceLocksAtTip to indicate the LockPoints validity
311- int maxInputHeight = 0 ;
312- for (const int height : prevheights) {
313- // Can ignore mempool inputs since we'll fail if they had non-zero locks
314- if (height != tip->nHeight +1 ) {
315- maxInputHeight = std::max (maxInputHeight, height);
316- }
317- }
318- // tip->GetAncestor(maxInputHeight) should never return a nullptr
319- // because maxInputHeight is always less than the tip height.
320- // It would, however, be a bad bug to continue execution, since a
321- // LockPoints object with the maxInputBlock member set to nullptr
322- // signifies no relative lock time.
323- lp->maxInputBlock = Assert (tip->GetAncestor (maxInputHeight));
324- }
325- }
326- return EvaluateSequenceLocks (index, lockPair);
269+ return EvaluateSequenceLocks (index, {lock_points.height , lock_points.time });
327270}
328271
329272// Returns the script flags which should be checked for a given block
@@ -409,20 +352,23 @@ void Chainstate::MaybeUpdateMempoolForReorg(
409352
410353 // The transaction must be final.
411354 if (!CheckFinalTxAtTip (*Assert (m_chain.Tip ()), tx)) return true ;
412- LockPoints lp = it->GetLockPoints ();
413- const bool validLP{TestLockPointValidity (m_chain, lp)};
414- CCoinsViewMemPool view_mempool (&CoinsTip (), *m_mempool);
355+
356+ const LockPoints& lp = it->GetLockPoints ();
415357 // CheckSequenceLocksAtTip checks if the transaction will be final in the next block to be
416- // created on top of the new chain. We use useExistingLockPoints=false so that, instead of
417- // using the information in lp (which might now refer to a block that no longer exists in
418- // the chain), it will update lp to contain LockPoints relevant to the new chain.
419- if (!CheckSequenceLocksAtTip (m_chain.Tip (), view_mempool, tx, &lp, validLP)) {
420- // If CheckSequenceLocksAtTip fails, remove the tx and don't depend on the LockPoints.
421- return true ;
422- } else if (!validLP) {
423- // If CheckSequenceLocksAtTip succeeded, it also updated the LockPoints.
424- // Now update the mempool entry lockpoints as well.
425- m_mempool->mapTx .modify (it, [&lp](CTxMemPoolEntry& e) { e.UpdateLockPoints (lp); });
358+ // created on top of the new chain.
359+ if (TestLockPointValidity (m_chain, lp)) {
360+ if (!CheckSequenceLocksAtTip (m_chain.Tip (), lp)) {
361+ return true ;
362+ }
363+ } else {
364+ const CCoinsViewMemPool view_mempool{&CoinsTip (), *m_mempool};
365+ const std::optional<LockPoints> new_lock_points{CalculateLockPointsAtTip (m_chain.Tip (), view_mempool, tx)};
366+ if (new_lock_points.has_value () && CheckSequenceLocksAtTip (m_chain.Tip (), *new_lock_points)) {
367+ // Now update the mempool entry lockpoints as well.
368+ m_mempool->mapTx .modify (it, [&new_lock_points](CTxMemPoolEntry& e) { e.UpdateLockPoints (*new_lock_points); });
369+ } else {
370+ return true ;
371+ }
426372 }
427373
428374 // If the transaction spends any coinbase outputs, it must be mature.
@@ -824,7 +770,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
824770 }
825771 }
826772
827- LockPoints lp;
828773 m_view.SetBackend (m_viewmempool);
829774
830775 const CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip ();
@@ -866,7 +811,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
866811 // be mined yet.
867812 // Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
868813 // backend was removed, it no longer pulls coins from the mempool.
869- if (!CheckSequenceLocksAtTip (m_active_chainstate.m_chain .Tip (), m_view, tx, &lp)) {
814+ const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip (m_active_chainstate.m_chain .Tip (), m_view, tx)};
815+ if (!lock_points.has_value () || !CheckSequenceLocksAtTip (m_active_chainstate.m_chain .Tip (), *lock_points)) {
870816 return state.Invalid (TxValidationResult::TX_PREMATURE_SPEND, " non-BIP68-final" );
871817 }
872818
@@ -902,7 +848,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
902848 }
903849
904850 entry.reset (new CTxMemPoolEntry (ptx, ws.m_base_fees , nAcceptTime, m_active_chainstate.m_chain .Height (),
905- fSpendsCoinbase , nSigOpsCost, lp ));
851+ fSpendsCoinbase , nSigOpsCost, lock_points. value () ));
906852 ws.m_vsize = entry->GetTxSize ();
907853
908854 if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
0 commit comments