mirror of
https://github.com/bitcoin/bips.git
synced 2025-01-18 13:26:08 +01:00
6902f790f1
Formatting Fix typos Update with BIP 112 assignment Update references to BIP113 Update deployment methodology Add references
247 lines
9.1 KiB
Plaintext
247 lines
9.1 KiB
Plaintext
<pre>
|
|
BIP: 112
|
|
Title: CHECKSEQUENCEVERIFY
|
|
Authors: BtcDrak <btcdrak@gmail.com>
|
|
Mark Friedenbach <mark@friedenbach.org>
|
|
Status: Draft
|
|
Type: Standards Track
|
|
Created: 2015-08-10
|
|
</pre>
|
|
|
|
==Abstract==
|
|
|
|
This BIP describes a new opcode (CHECKSEQUENCEVERIFY) for the Bitcoin
|
|
scripting system that in combination with BIP 68 allows execution
|
|
pathways of a script to be restricted based on the age of the output
|
|
being spent.
|
|
|
|
|
|
==Summary==
|
|
|
|
CHECKSEQUENCEVERIFY redefines the existing NOP3 opcode. When executed
|
|
it compares the top item on the stack to the inverse of the nSequence
|
|
field of the transaction input containing the scriptSig. If the
|
|
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
|
|
from being selected for inclusion in a block until the corresponding
|
|
input has reached the specified age, as measured in block height or
|
|
block time. By comparing the argument to CHECKSEQUENCEVERIFY against
|
|
the nSequence field, we indirectly verify a desired minimum age of the
|
|
the output being spent; until that relative age has been reached any
|
|
script execution pathway including the CHECKSEQUENCEVERIFY will fail
|
|
to validate, causing the transaction not to be selected for inclusion
|
|
in a block.
|
|
|
|
|
|
==Motivation==
|
|
|
|
BIP 68 repurposes the transaction nSequence field meaning by giving
|
|
sequence numbers new consensus-enforced semantics as a relative
|
|
lock-time. However, there is no way to build Bitcoin scripts to make
|
|
decisions based on this field.
|
|
|
|
By making the nSequence field accessible to script, it becomes
|
|
possible to construct code pathways that only become accessible some
|
|
minimum time after proof-of-publication. This enables a wide variety
|
|
of applications in phased protocols such as escrow, payment channels,
|
|
or bidirectional pegs.
|
|
|
|
|
|
==Specification==
|
|
|
|
Refer to the reference implementation, reproduced below, for the precise
|
|
semantics and detailed rationale for those semantics.
|
|
|
|
|
|
// Threshold for nLockTime: below this value it is interpreted as block number,
|
|
// otherwise as UNIX timestamp (already defined in Bitcoin Core).
|
|
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
|
|
|
// Threshold for inverted nSequence: below this value it is interpreted
|
|
// as a relative lock-time, otherwise ignored.
|
|
static const uint32_t SEQUENCE_THRESHOLD = (1 << 31);
|
|
|
|
case OP_NOP3:
|
|
{
|
|
if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
|
|
// not enabled; treat as a NOP3
|
|
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (stack.size() < 1)
|
|
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
|
|
|
// Note that unlike CHECKLOCKTIMEVERIFY we do not need to
|
|
// accept 5-byte bignums since any value greater than or
|
|
// equal to SEQUENCE_THRESHOLD (= 1 << 31) will be rejected
|
|
// anyway. This limitation just happens to coincide with
|
|
// CScriptNum's default 4-byte limit with an explicit sign
|
|
// bit.
|
|
//
|
|
// This means there is a maximum relative lock time of 52
|
|
// years, even though the nSequence field in transactions
|
|
// themselves is uint32_t and could allow a relative lock
|
|
// time of up to 120 years.
|
|
const CScriptNum nInvSequence(stacktop(-1), fRequireMinimal);
|
|
|
|
// In the rare event that the argument may be < 0 due to
|
|
// some arithmetic being done first, you can always use
|
|
// 0 MAX CHECKSEQUENCEVERIFY.
|
|
if (nInvSequence < 0)
|
|
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
|
|
|
|
// Actually compare the specified inverse sequence number
|
|
// with the input.
|
|
if (!CheckSequence(nInvSequence))
|
|
return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
|
|
|
|
break;
|
|
}
|
|
|
|
bool CheckSequence(const CScriptNum& nInvSequence) const
|
|
{
|
|
int64_t txToInvSequence;
|
|
|
|
// Fail under all circumstances if the transaction's version
|
|
// number is not set high enough to enable enforced sequence
|
|
// number rules.
|
|
if (txTo->nVersion < 2)
|
|
return false;
|
|
|
|
// Sequence number must be inverted to convert it into a
|
|
// relative lock-time.
|
|
txToInvSequence = (int64_t)~txTo->vin[nIn].nSequence;
|
|
|
|
// Sequence numbers under SEQUENCE_THRESHOLD are not consensus
|
|
// constrained.
|
|
if (txToInvSequence >= SEQUENCE_THRESHOLD)
|
|
return false;
|
|
|
|
// There are two types of relative lock-time: lock-by-
|
|
// blockheight and lock-by-blocktime, distinguished by
|
|
// whether txToInvSequence < LOCKTIME_THRESHOLD.
|
|
//
|
|
// We want to compare apples to apples, so fail the script
|
|
// unless the type of lock-time being tested is the same as
|
|
// the lock-time in the transaction input.
|
|
if (!(
|
|
(txToInvSequence < LOCKTIME_THRESHOLD && nInvSequence < LOCKTIME_THRESHOLD) ||
|
|
(txToInvSequence >= LOCKTIME_THRESHOLD && nInvSequence >= LOCKTIME_THRESHOLD)
|
|
))
|
|
return false;
|
|
|
|
// Now that we know we're comparing apples-to-apples, the
|
|
// comparison is a simple numeric one.
|
|
if (nInvSequence > txToInvSequence)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
https://github.com/maaku/bitcoin/commit/33be476a60fcc2afbe6be0ca7b93a84209173eb2
|
|
|
|
|
|
==Example: Escrow with Timeout==
|
|
|
|
An escrow that times out automatically 30 days after being funded can be
|
|
established in the following way. Alice, Bob and Escrow create a 2-of-3
|
|
address with the following redeemscript.
|
|
|
|
IF
|
|
2 <Alice's pubkey> <Bob's pubkey> <Escrow's pubkey> 3 CHECKMULTISIGVERIFY
|
|
ELSE
|
|
<LOCKTIME_THRESHOLD + 30*24*60*60> CHECKSEQUENCEVERIFY DROP
|
|
<Alice's pubkey> CHECKSIGVERIFY
|
|
ENDIF
|
|
|
|
At any time funds can be spent using signatures from any two of Alice,
|
|
Bob or the Escrow.
|
|
|
|
After 30 days Alice can sign alone.
|
|
|
|
The clock does not start ticking until the payment to the escrow address
|
|
confirms.
|
|
|
|
|
|
==Reference Implementation==
|
|
|
|
A reference implementation is provided in the following git repository:
|
|
|
|
https://github.com/maaku/bitcoin/tree/checksequenceverify
|
|
|
|
|
|
==Deployment==
|
|
|
|
We reuse the double-threshold switchover mechanism from BIPs 34 and
|
|
66, with the same thresholds, but for nVersion = 8. The new rules are
|
|
in effect for every block (at height H) with nVersion = 8 and at least
|
|
750 out of 1000 blocks preceding it (with heights H-1000..H-1) also
|
|
have nVersion = 8. Furthermore, when 950 out of the 1000 blocks
|
|
preceding a block do have nVersion = 8, nVersion = 3 blocks become
|
|
invalid, and all further blocks enforce the new rules.
|
|
|
|
When assessing the block version as mask of ~0x20000007 must be applied
|
|
to work around the complications caused by
|
|
[http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html BIP101's premature use]
|
|
of the [https://gist.github.com/sipa/bf69659f43e763540550 undecided version bits proposal].
|
|
|
|
By applying ~0x20000007 with nVersion = 8, the thresholds should be tested
|
|
comparing block nVersion >= 4 as this will save a bit for future use.
|
|
|
|
It is recommended that this soft-fork deployment trigger include other
|
|
related proposals for improving Bitcoin's lock-time capabilities, including:
|
|
|
|
[https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP 65]:
|
|
OP_CHECKLOCKTIMEVERIFY,
|
|
|
|
[https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki BIP 68]:
|
|
Consensus-enforced transaction replacement signalled via sequence numbers,
|
|
|
|
and [https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki BIP 113]:
|
|
Median-Past-Time-Lock.
|
|
|
|
==Credits==
|
|
|
|
Mark Friedenbach invented the application of sequence numbers to
|
|
achieve relative lock-time, and wrote the reference implementation of
|
|
CHECKSEQUENCEVERIFY.
|
|
|
|
The reference implementation and this BIP was based heavily on work
|
|
done by Peter Todd for the closely related BIP 65.
|
|
|
|
BtcDrak authored this BIP document.
|
|
|
|
|
|
==References==
|
|
|
|
BIP 68: Consensus-enforced transaction replacement signalled via
|
|
sequence numbers
|
|
https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
|
|
|
|
BIP 65: OP_CHECKLOCKTIMEVERIFY
|
|
https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
|
|
|
|
BIP 113: Median past block time for time-lock constraints
|
|
https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki
|
|
|
|
HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and
|
|
revocation hashes
|
|
http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html
|
|
|
|
[http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html Softfork deployment considerations]
|
|
|
|
[https://gist.github.com/sipa/bf69659f43e763540550 Version bits]
|
|
|
|
|
|
==Copyright==
|
|
|
|
This document is placed in the public domain.
|