@ -667,9 +667,10 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
@@ -667,9 +667,10 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true ;
if ( ( int64_t ) tx . nLockTime < ( ( int64_t ) tx . nLockTime < LOCKTIME_THRESHOLD ? ( int64_t ) nBlockHeight : nBlockTime ) )
return true ;
BOOST_FOREACH ( const CTxIn & txin , tx . vin )
if ( ! txin . IsFinal ( ) )
BOOST_FOREACH ( const CTxIn & txin , tx . vin ) {
if ( ! ( txin . nSequence = = CTxIn : : SEQUENCE_FINAL ) )
return false ;
}
return true ;
}
@ -705,6 +706,128 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
@@ -705,6 +706,128 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
return IsFinalTx ( tx , nBlockHeight , nBlockTime ) ;
}
/**
* Calculates the block height and previous block ' s median time past at
* which the transaction will be considered final in the context of BIP 68.
* Also removes from the vector of input heights any entries which did not
* correspond to sequence locked inputs as they do not affect the calculation .
*/
static std : : pair < int , int64_t > CalculateSequenceLocks ( const CTransaction & tx , int flags , std : : vector < int > * prevHeights , const CBlockIndex & block )
{
assert ( prevHeights - > size ( ) = = tx . vin . size ( ) ) ;
// Will be set to the equivalent height- and time-based nLockTime
// values that would be necessary to satisfy all relative lock-
// time constraints given our view of block chain history.
// The semantics of nLockTime are the last invalid height/time, so
// use -1 to have the effect of any height or time being valid.
int nMinHeight = - 1 ;
int64_t nMinTime = - 1 ;
// tx.nVersion is signed integer so requires cast to unsigned otherwise
// we would be doing a signed comparison and half the range of nVersion
// wouldn't support BIP 68.
bool fEnforceBIP68 = static_cast < uint32_t > ( tx . nVersion ) > = 2
& & flags & LOCKTIME_VERIFY_SEQUENCE ;
// Do not enforce sequence numbers as a relative lock time
// unless we have been instructed to
if ( ! fEnforceBIP68 ) {
return std : : make_pair ( nMinHeight , nMinTime ) ;
}
for ( size_t txinIndex = 0 ; txinIndex < tx . vin . size ( ) ; txinIndex + + ) {
const CTxIn & txin = tx . vin [ txinIndex ] ;
// Sequence numbers with the most significant bit set are not
// treated as relative lock-times, nor are they given any
// consensus-enforced meaning at this point.
if ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_DISABLE_FLAG ) {
// The height of this input is not relevant for sequence locks
( * prevHeights ) [ txinIndex ] = 0 ;
continue ;
}
int nCoinHeight = ( * prevHeights ) [ txinIndex ] ;
if ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG ) {
int64_t nCoinTime = block . GetAncestor ( std : : max ( nCoinHeight - 1 , 0 ) ) - > GetMedianTimePast ( ) ;
// NOTE: Subtract 1 to maintain nLockTime semantics
// BIP 68 relative lock times have the semantics of calculating
// the first block or time at which the transaction would be
// valid. When calculating the effective block time or height
// for the entire transaction, we switch to using the
// semantics of nLockTime which is the last invalid block
// time or height. Thus we subtract 1 from the calculated
// time or height.
// Time-based relative lock-times are measured from the
// smallest allowed timestamp of the block containing the
// txout being spent, which is the median time past of the
// block prior.
nMinTime = std : : max ( nMinTime , nCoinTime + ( int64_t ) ( ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_MASK ) < < CTxIn : : SEQUENCE_LOCKTIME_GRANULARITY ) - 1 ) ;
} else {
nMinHeight = std : : max ( nMinHeight , nCoinHeight + ( int ) ( txin . nSequence & CTxIn : : SEQUENCE_LOCKTIME_MASK ) - 1 ) ;
}
}
return std : : make_pair ( nMinHeight , nMinTime ) ;
}
static bool EvaluateSequenceLocks ( const CBlockIndex & block , std : : pair < int , int64_t > lockPair )
{
assert ( block . pprev ) ;
int64_t nBlockTime = block . pprev - > GetMedianTimePast ( ) ;
if ( lockPair . first > = block . nHeight | | lockPair . second > = nBlockTime )
return false ;
return true ;
}
bool SequenceLocks ( const CTransaction & tx , int flags , std : : vector < int > * prevHeights , const CBlockIndex & block )
{
return EvaluateSequenceLocks ( block , CalculateSequenceLocks ( tx , flags , prevHeights , block ) ) ;
}
bool CheckSequenceLocks ( const CTransaction & tx , int flags )
{
AssertLockHeld ( cs_main ) ;
AssertLockHeld ( mempool . cs ) ;
CBlockIndex * tip = chainActive . Tip ( ) ;
CBlockIndex index ;
index . pprev = tip ;
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
// height based locks because when SequenceLocks() 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
// SequenceLocks() with one more than chainActive.Height().
index . nHeight = tip - > nHeight + 1 ;
// pcoinsTip contains the UTXO set for chainActive.Tip()
CCoinsViewMemPool viewMemPool ( pcoinsTip , mempool ) ;
std : : vector < int > prevheights ;
prevheights . resize ( tx . vin . size ( ) ) ;
for ( size_t txinIndex = 0 ; txinIndex < tx . vin . size ( ) ; txinIndex + + ) {
const CTxIn & txin = tx . vin [ txinIndex ] ;
CCoins coins ;
if ( ! viewMemPool . GetCoins ( txin . prevout . hash , coins ) ) {
return error ( " %s: Missing input " , __func__ ) ;
}
if ( coins . nHeight = = MEMPOOL_HEIGHT ) {
// Assume all mempool transaction confirm in the next block
prevheights [ txinIndex ] = tip - > nHeight + 1 ;
} else {
prevheights [ txinIndex ] = coins . nHeight ;
}
}
std : : pair < int , int64_t > lockPair = CalculateSequenceLocks ( tx , flags , & prevheights , index ) ;
return EvaluateSequenceLocks ( index , lockPair ) ;
}
unsigned int GetLegacySigOpCount ( const CTransaction & tx )
{
unsigned int nSigOps = 0 ;
@ -949,6 +1072,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -949,6 +1072,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
view . SetBackend ( dummy ) ;
// 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 ( tx , STANDARD_LOCKTIME_VERIFY_FLAGS ) )
return state . DoS ( 0 , false , REJECT_NONSTANDARD , " non-BIP68-final " ) ;
}
// Check for non-standard pay-to-script-hash in inputs
@ -2075,6 +2206,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
@@ -2075,6 +2206,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CCheckQueueControl < CScriptCheck > control ( fScriptChecks & & nScriptCheckThreads ? & scriptcheckqueue : NULL ) ;
std : : vector < int > prevheights ;
int nLockTimeFlags = 0 ;
CAmount nFees = 0 ;
int nInputs = 0 ;
unsigned int nSigOps = 0 ;
@ -2098,6 +2231,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
@@ -2098,6 +2231,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state . DoS ( 100 , error ( " ConnectBlock(): inputs missing/spent " ) ,
REJECT_INVALID , " bad-txns-inputs-missingorspent " ) ;
// Check that transaction is BIP68 final
// BIP68 lock checks (as opposed to nLockTime checks) must
// be in ConnectBlock because they require the UTXO set
prevheights . resize ( tx . vin . size ( ) ) ;
for ( size_t j = 0 ; j < tx . vin . size ( ) ; j + + ) {
prevheights [ j ] = view . AccessCoins ( tx . vin [ j ] . prevout . hash ) - > nHeight ;
}
if ( ! SequenceLocks ( tx , nLockTimeFlags , & prevheights , * pindex ) ) {
return state . DoS ( 100 , error ( " ConnectBlock(): contains a non-BIP68-final transaction " , __func__ ) ,
REJECT_INVALID , " bad-txns-nonfinal " ) ;
}
if ( fStrictPayToScriptHash )
{
// Add in sigops done by pay-to-script-hash inputs;