@ -650,10 +650,35 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true ;
return true ;
}
}
bool CheckFinalTx ( const CTransaction & tx )
bool CheckFinalTx ( const CTransaction & tx , int flags )
{
{
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( cs_main ) ;
return IsFinalTx ( tx , chainActive . Height ( ) + 1 , GetAdjustedTime ( ) ) ;
// 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 chainActive.Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within
// CBlock::AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a
// transaction can be part of the *next* block, we need to call
// IsFinalTx() with one more than chainActive.Height().
const int nBlockHeight = chainActive . Height ( ) + 1 ;
// Timestamps on the other hand don't get any special treatment,
// because we can't know what timestamp the next block will have,
// and there aren't timestamp applications where it matters.
// However this changes once median past time-locks are enforced:
const int64_t nBlockTime = ( flags & LOCKTIME_MEDIAN_TIME_PAST )
? chainActive . Tip ( ) - > GetMedianTimePast ( )
: GetAdjustedTime ( ) ;
return IsFinalTx ( tx , nBlockHeight , nBlockTime ) ;
}
}
unsigned int GetLegacySigOpCount ( const CTransaction & tx )
unsigned int GetLegacySigOpCount ( const CTransaction & tx )
@ -797,7 +822,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Only accept nLockTime-using transactions that can be mined in the next
// 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
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
// be mined yet.
if ( ! CheckFinalTx ( tx ) )
if ( ! CheckFinalTx ( tx , STANDARD_LOCKTIME_VERIFY_FLAGS ) )
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " non-final " ) ;
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " non-final " ) ;
// is it already in the memory pool?
// is it already in the memory pool?
@ -2723,10 +2748,15 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
const Consensus : : Params & consensusParams = Params ( ) . GetConsensus ( ) ;
const Consensus : : Params & consensusParams = Params ( ) . GetConsensus ( ) ;
// Check that all transactions are finalized
// Check that all transactions are finalized
BOOST_FOREACH ( const CTransaction & tx , block . vtx )
BOOST_FOREACH ( const CTransaction & tx , block . vtx ) {
if ( ! IsFinalTx ( tx , nHeight , block . GetBlockTime ( ) ) ) {
int nLockTimeFlags = 0 ;
int64_t nLockTimeCutoff = ( nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST )
? pindexPrev - > GetMedianTimePast ( )
: block . GetBlockTime ( ) ;
if ( ! IsFinalTx ( tx , nHeight , nLockTimeCutoff ) ) {
return state . DoS ( 10 , error ( " %s: contains a non-final transaction " , __func__ ) , REJECT_INVALID , " bad-txns-nonfinal " ) ;
return state . DoS ( 10 , error ( " %s: contains a non-final transaction " , __func__ ) , REJECT_INVALID , " bad-txns-nonfinal " ) ;
}
}
}
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):