mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-18 13:17:55 +02:00
Add rules--presently disabled--for using GetMedianTimePast as endpoint for lock-time calculations
The lock-time code currently uses CBlock::nTime as the cutoff point for time based locked transactions. This has the unfortunate outcome of creating a perverse incentive for miners to lie about the time of a block in order to collect more fees by including transactions that by wall clock determination have not yet matured. By using CBlockIndex::GetMedianTimePast from the prior block instead, the self-interested miner no longer gains from generating blocks with fraudulent timestamps. Users can compensate for this change by simply adding an hour (3600 seconds) to their time-based lock times. If enforced, this would be a soft-fork change. This commit only adds the functionality on an unexecuted code path, without changing the behaviour of Bitcoin Core.
This commit is contained in:
parent
0d96b81945
commit
68ea815ad6
3 changed files with 24 additions and 4 deletions
16
src/main.cpp
16
src/main.cpp
|
|
@ -775,7 +775,9 @@ int64_t CheckLockTime(const CTransaction &tx, int flags)
|
|||
// 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.
|
||||
const int64_t nBlockTime = GetAdjustedTime();
|
||||
int64_t nBlockTime = GetAdjustedTime();
|
||||
if (flags & LOCKTIME_MEDIAN_TIME_PAST)
|
||||
nBlockTime -= ((CBlockIndex::nMedianTimeSpan + 1) >> 1) * Params().GetConsensus().nPowTargetSpacing;
|
||||
|
||||
return LockTime(tx, flags, pCoinsView, nBlockHeight, nBlockTime);
|
||||
}
|
||||
|
|
@ -1051,10 +1053,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||
view.SetBackend(dummy);
|
||||
}
|
||||
|
||||
int nLockTimeFlags = 0;
|
||||
int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
|
||||
? chainActive.Tip()->GetMedianTimePast()
|
||||
: GetAdjustedTime();
|
||||
|
||||
// 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 (LockTime(tx, 0, &view, chainActive.Height() + 1, GetAdjustedTime()))
|
||||
if (LockTime(tx, nLockTimeFlags, &view, chainActive.Height() + 1, nLockTimeCutoff))
|
||||
return state.DoS(0, error("AcceptToMemoryPool: non-final"),
|
||||
REJECT_NONSTANDARD, "non-final");
|
||||
|
||||
|
|
@ -2862,7 +2869,10 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
|
|||
// Check that all transactions are finalized
|
||||
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
|
||||
int nLockTimeFlags = 0;
|
||||
if (LockTime(tx, nLockTimeFlags, pcoinsTip, nHeight, block.GetBlockTime()))
|
||||
int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
|
||||
? pindexPrev->GetMedianTimePast()
|
||||
: block.GetBlockTime();
|
||||
if (LockTime(tx, nLockTimeFlags, pcoinsTip, nHeight, nLockTimeCutoff))
|
||||
return state.DoS(10, error("%s: contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -331,6 +331,9 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
|
|||
enum {
|
||||
/* Interpret sequence numbers as relative lock-time constraints. */
|
||||
LOCKTIME_VERIFY_SEQUENCE = (1 << 0),
|
||||
|
||||
/* Use GetMedianTimePast() instead of nTime for end point timestamp. */
|
||||
LOCKTIME_MEDIAN_TIME_PAST = (1 << 1),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
const int nHeight = pindexPrev->nHeight + 1;
|
||||
pblock->nTime = GetAdjustedTime();
|
||||
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
|
||||
CCoinsViewCache view(pcoinsTip);
|
||||
|
||||
// Priority order to process transactions
|
||||
|
|
@ -159,7 +160,13 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||
mi != mempool.mapTx.end(); ++mi)
|
||||
{
|
||||
const CTransaction& tx = mi->second.GetTx();
|
||||
if (tx.IsCoinBase() || LockTime(tx, 0, &view, nHeight, pblock->nTime))
|
||||
|
||||
int nLockTimeFlags = 0;
|
||||
int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
|
||||
? nMedianTimePast
|
||||
: pblock->GetBlockTime();
|
||||
|
||||
if (tx.IsCoinBase() || LockTime(tx, nLockTimeFlags, &view, nHeight, nLockTimeCutoff))
|
||||
continue;
|
||||
|
||||
COrphan* porphan = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue