@ -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 CheckFinalTx AtTip ( 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 CheckSequenceLocks AtTip ( 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
// CheckSequenceLocks AtTip () 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
// CheckSequenceLocks AtTip 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 ( ! CheckFinalTx AtTip ( 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
// CheckSequenceLocks AtTip 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 ( ! CheckSequenceLocks AtTip ( m_chain . Tip ( ) , view_mempool , tx , & lp , validLP ) ) {
// If CheckSequenceLocks AtTip 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 CheckSequenceLocks AtTip 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 ( ! CheckFinalTx AtTip ( 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 ( ! CheckSequenceLocks AtTip ( 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 ) ) {