@@ -252,10 +252,7 @@ std::optional<LockPoints> CalculateLockPointsAtTip(
252
252
}
253
253
254
254
bool CheckSequenceLocksAtTip (CBlockIndex* tip,
255
- const CCoinsView& coins_view,
256
- const CTransaction& tx,
257
- LockPoints* lp,
258
- bool useExistingLockPoints)
255
+ const LockPoints& lock_points)
259
256
{
260
257
assert (tip != nullptr );
261
258
@@ -269,61 +266,7 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
269
266
// *next* block, we need to use one more than active_chainstate.m_chain.Height()
270
267
index.nHeight = tip->nHeight + 1 ;
271
268
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 });
327
270
}
328
271
329
272
// Returns the script flags which should be checked for a given block
@@ -409,20 +352,23 @@ void Chainstate::MaybeUpdateMempoolForReorg(
409
352
410
353
// The transaction must be final.
411
354
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 ();
415
357
// 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
+ }
426
372
}
427
373
428
374
// If the transaction spends any coinbase outputs, it must be mature.
@@ -824,7 +770,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
824
770
}
825
771
}
826
772
827
- LockPoints lp;
828
773
m_view.SetBackend (m_viewmempool);
829
774
830
775
const CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip ();
@@ -866,7 +811,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
866
811
// be mined yet.
867
812
// Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
868
813
// 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)) {
870
816
return state.Invalid (TxValidationResult::TX_PREMATURE_SPEND, " non-BIP68-final" );
871
817
}
872
818
@@ -902,7 +848,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
902
848
}
903
849
904
850
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 () ));
906
852
ws.m_vsize = entry->GetTxSize ();
907
853
908
854
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
0 commit comments