Skip to content

Commit e4e5334

Browse files
committed
Restore MedianTimePast for locktime.
Revert "Revert "Add rules--presently disabled--for using GetMedianTimePast as endpoint for lock-time calculations"" This reverts commit 40cd32e. After careful analysis it was determined that the change was, in fact, safe and several people were suffering momentary confusion about locktime semantics.
1 parent 42f339e commit e4e5334

File tree

5 files changed

+54
-7
lines changed

5 files changed

+54
-7
lines changed

src/consensus/consensus.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,10 @@ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
1313
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
1414
static const int COINBASE_MATURITY = 100;
1515

16+
/** Flags for LockTime() */
17+
enum {
18+
/* Use GetMedianTimePast() instead of nTime for end point timestamp. */
19+
LOCKTIME_MEDIAN_TIME_PAST = (1 << 1),
20+
};
21+
1622
#endif // BITCOIN_CONSENSUS_CONSENSUS_H

src/main.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -650,10 +650,35 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
650650
return true;
651651
}
652652

653-
bool CheckFinalTx(const CTransaction &tx)
653+
bool CheckFinalTx(const CTransaction &tx, int flags)
654654
{
655655
AssertLockHeld(cs_main);
656-
return IsFinalTx(tx, chainActive.Height() + 1, GetAdjustedTime());
656+
657+
// By convention a negative value for flags indicates that the
658+
// current network-enforced consensus rules should be used. In
659+
// a future soft-fork scenario that would mean checking which
660+
// rules would be enforced for the next block and setting the
661+
// appropriate flags. At the present time no soft-forks are
662+
// scheduled, so no flags are set.
663+
flags = std::max(flags, 0);
664+
665+
// CheckFinalTx() uses chainActive.Height()+1 to evaluate
666+
// nLockTime because when IsFinalTx() is called within
667+
// CBlock::AcceptBlock(), the height of the block *being*
668+
// evaluated is what is used. Thus if we want to know if a
669+
// transaction can be part of the *next* block, we need to call
670+
// IsFinalTx() with one more than chainActive.Height().
671+
const int nBlockHeight = chainActive.Height() + 1;
672+
673+
// Timestamps on the other hand don't get any special treatment,
674+
// because we can't know what timestamp the next block will have,
675+
// and there aren't timestamp applications where it matters.
676+
// However this changes once median past time-locks are enforced:
677+
const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
678+
? chainActive.Tip()->GetMedianTimePast()
679+
: GetAdjustedTime();
680+
681+
return IsFinalTx(tx, nBlockHeight, nBlockTime);
657682
}
658683

659684
unsigned int GetLegacySigOpCount(const CTransaction& tx)
@@ -797,7 +822,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
797822
// Only accept nLockTime-using transactions that can be mined in the next
798823
// block; we don't want our mempool filled up with transactions that can't
799824
// be mined yet.
800-
if (!CheckFinalTx(tx))
825+
if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
801826
return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
802827

803828
// is it already in the memory pool?
@@ -2723,10 +2748,15 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
27232748
const Consensus::Params& consensusParams = Params().GetConsensus();
27242749

27252750
// Check that all transactions are finalized
2726-
BOOST_FOREACH(const CTransaction& tx, block.vtx)
2727-
if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) {
2751+
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
2752+
int nLockTimeFlags = 0;
2753+
int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
2754+
? pindexPrev->GetMedianTimePast()
2755+
: block.GetBlockTime();
2756+
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
27282757
return state.DoS(10, error("%s: contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal");
27292758
}
2759+
}
27302760

27312761
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
27322762
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):

src/main.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,10 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
308308
* Check if transaction will be final in the next block to be created.
309309
*
310310
* Calls IsFinalTx() with current block height and appropriate block time.
311+
*
312+
* See consensus/consensus.h for flag definitions.
311313
*/
312-
bool CheckFinalTx(const CTransaction &tx);
314+
bool CheckFinalTx(const CTransaction &tx, int flags = -1);
313315

314316
/**
315317
* Closure representing one script verification

src/miner.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
148148
CBlockIndex* pindexPrev = chainActive.Tip();
149149
const int nHeight = pindexPrev->nHeight + 1;
150150
pblock->nTime = GetAdjustedTime();
151+
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
151152
CCoinsViewCache view(pcoinsTip);
152153

153154
// Priority order to process transactions
@@ -162,7 +163,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
162163
mi != mempool.mapTx.end(); ++mi)
163164
{
164165
const CTransaction& tx = mi->GetTx();
165-
if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime))
166+
167+
int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
168+
? nMedianTimePast
169+
: pblock->GetBlockTime();
170+
171+
if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff))
166172
continue;
167173

168174
COrphan* porphan = NULL;

src/policy/policy.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
4343
/** For convenience, standard but not mandatory verify flags. */
4444
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
4545

46+
/** Used as the flags parameter to CheckFinalTx() in non-consensus code */
47+
static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = 0;
48+
4649
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
4750
/**
4851
* Check for standard transaction types

0 commit comments

Comments
 (0)