1
0
Fork 0
mirror of https://github.com/bitcoin/bips.git synced 2025-03-04 03:03:53 +01:00

Amend BIP112 to fit BIP68 redefinition

This commit is contained in:
BtcDrak 2015-09-26 09:54:13 +01:00
parent e413cd49de
commit b962c479b3

View file

@ -18,14 +18,9 @@ being spent.
==Summary== ==Summary==
CHECKSEQUENCEVERIFY redefines the existing NOP3 opcode. When executed CHECKSEQUENCEVERIFY redefines the existing NOP3 opcode. When executed it
it compares the top item on the stack to the inverse of the nSequence compares the top item on the stack to the nSequence field of the transaction
field of the transaction input containing the scriptSig. If the input containing the scriptSig. **
inverse of nSequence is less than the sequence threshold (1 << 31),
the transaction version is greater than or equal to 2, and the top
item on the stack is less than or equal to the inverted nSequence,
script evaluation continues as though a NOP was executed. Otherwise
the script fails immediately.
BIP 68's redefinition of nSequence prevents a non-final transaction BIP 68's redefinition of nSequence prevents a non-final transaction
from being selected for inclusion in a block until the corresponding from being selected for inclusion in a block until the corresponding
@ -58,13 +53,14 @@ Refer to the reference implementation, reproduced below, for the precise
semantics and detailed rationale for those semantics. semantics and detailed rationale for those semantics.
// Threshold for nLockTime: below this value it is interpreted as block number, /* Threshold for nSequence: below this value it is interpreted
// otherwise as UNIX timestamp (already defined in Bitcoin Core). * as a relative lock-time, otherwise ignored. */
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC static const uint32_t SEQUENCE_LOCKTIME_THRESHOLD = (1 << 31);
// Threshold for inverted nSequence: below this value it is interpreted /* Threshold for nSequence when interpreted as a relative
// as a relative lock-time, otherwise ignored. * lock-time: below this value it has units of blocks, otherwise
static const uint32_t SEQUENCE_THRESHOLD = (1 << 31); * seconds. */
static const uint32_t SEQUENCE_UNITS_THRESHOLD = (1 << 30);
case OP_NOP3: case OP_NOP3:
{ {
@ -79,75 +75,81 @@ semantics and detailed rationale for those semantics.
if (stack.size() < 1) if (stack.size() < 1)
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
// Note that unlike CHECKLOCKTIMEVERIFY we do not need to // Note that elsewhere numeric opcodes are limited to
// accept 5-byte bignums since any value greater than or // operands in the range -2**31+1 to 2**31-1, however it is
// equal to SEQUENCE_THRESHOLD (= 1 << 31) will be rejected // legal for opcodes to produce results exceeding that
// anyway. This limitation just happens to coincide with // range. This limitation is implemented by CScriptNum's
// CScriptNum's default 4-byte limit with an explicit sign // default 4-byte limit.
// bit.
// //
// This means there is a maximum relative lock time of 52 // If we kept to that limit we'd have a year 2038 problem,
// years, even though the nSequence field in transactions // even though the nLockTime field in transactions
// themselves is uint32_t and could allow a relative lock // themselves is uint32 which only becomes meaningless
// time of up to 120 years. // after the year 2106.
const CScriptNum nInvSequence(stacktop(-1), fRequireMinimal); //
// Thus as a special case we tell CScriptNum to accept up
// to 5-byte bignums, which are good until 2**39-1, well
// beyond the 2**32-1 limit of the nLockTime field itself.
const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
// In the rare event that the argument may be < 0 due to // In the rare event that the argument may be < 0 due to
// some arithmetic being done first, you can always use // some arithmetic being done first, you can always use
// 0 MAX CHECKSEQUENCEVERIFY. // 0 MAX CHECKSEQUENCEVERIFY.
if (nInvSequence < 0) if (nSequence < 0)
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME); return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
// Actually compare the specified inverse sequence number // To provide for future soft-fork extensibility, if the
// with the input. // operand is too large to be treated as a relative lock-
if (!CheckSequence(nInvSequence)) // time, CHECKSEQUENCEVERIFY behaves as a NOP.
if (nSequence >= SEQUENCE_LOCKTIME_THRESHOLD)
break;
// Actually compare the specified sequence number with the input.
if (!CheckSequence(nSequence))
return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME); return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
break; break;
} }
bool CheckSequence(const CScriptNum& nInvSequence) const bool CheckSequence(const CScriptNum& nSequence) const
{ {
int64_t txToInvSequence; // Relative lock times are supported by comparing the passed
// in operand to the sequence number of the input.
const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
// Fail under all circumstances if the transaction's version // Fail if the transaction's version number is not set high
// number is not set high enough to enable enforced sequence // enough to trigger BIP 68 rules.
// number rules. if (static_cast<uint32_t>(txTo->nVersion) < 2)
if (txTo->nVersion < 2)
return false; return false;
// Sequence number must be inverted to convert it into a // Sequence numbers above SEQUENCE_LOCKTIME_THRESHOLD
// relative lock-time. // are not consensus constrained. Testing that the transaction's
txToInvSequence = (int64_t)~txTo->vin[nIn].nSequence; // sequence number is not above this threshold prevents
// using this property to get around a CHECKSEQUENCEVERIFY
// Sequence numbers under SEQUENCE_THRESHOLD are not consensus // check.
// constrained. if (txToSequence >= SEQUENCE_LOCKTIME_THRESHOLD)
if (txToInvSequence >= SEQUENCE_THRESHOLD)
return false; return false;
// There are two types of relative lock-time: lock-by- // There are two kinds of nSequence: lock-by-blockheight
// blockheight and lock-by-blocktime, distinguished by // and lock-by-blocktime, distinguished by whether
// whether txToInvSequence < LOCKTIME_THRESHOLD. // nSequence < nThreshold (SEQUENCE_UNITS_THRESHOLD).
// //
// We want to compare apples to apples, so fail the script // We want to compare apples to apples, so fail the script
// unless the type of lock-time being tested is the same as // unless the type of nSequence being tested is the same as
// the lock-time in the transaction input. // the nSequence in the transaction.
if (!( if (!(
(txToInvSequence < LOCKTIME_THRESHOLD && nInvSequence < LOCKTIME_THRESHOLD) || (txToSequence < nThreshold && nSequence < nThreshold) ||
(txToInvSequence >= LOCKTIME_THRESHOLD && nInvSequence >= LOCKTIME_THRESHOLD) (txToSequence >= nThreshold && nSequence >= nThreshold)
)) ))
return false; return false;
// Now that we know we're comparing apples-to-apples, the // Now that we know we're comparing apples-to-apples, the
// comparison is a simple numeric one. // comparison is a simple numeric one.
if (nInvSequence > txToInvSequence) if (nSequence > txToSequence)
return false; return false;
return true; return true;
} }
https://github.com/maaku/bitcoin/commit/33be476a60fcc2afbe6be0ca7b93a84209173eb2
==Example: Escrow with Timeout== ==Example: Escrow with Timeout==
@ -244,3 +246,4 @@ http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html
==Copyright== ==Copyright==
This document is placed in the public domain. This document is placed in the public domain.