mirror of
https://github.com/bitcoin/bips.git
synced 2025-01-18 13:26:08 +01:00
401 lines
16 KiB
Plaintext
401 lines
16 KiB
Plaintext
<pre>
|
|
BIP: 112
|
|
Title: CHECKSEQUENCEVERIFY
|
|
Authors: BtcDrak <btcdrak@gmail.com>
|
|
Mark Friedenbach <mark@friedenbach.org>
|
|
Eric Lombrozo <elombrozo@gmail.com>
|
|
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 nSequence field of the transaction
|
|
input containing the scriptSig. If it is greater than or equal to (1 << 31),
|
|
or if the transaction version is greater than or equal to 2, the transaction input
|
|
sequence is less than or equal to (1 << 31) and the top stack item is less than
|
|
the transaction input sequence, script exection continues as if a NOP was executed,
|
|
otherwise the script fails.
|
|
|
|
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.
|
|
|
|
===Examples===
|
|
|
|
|
|
====Contracts With Expiration Deadlines====
|
|
|
|
=====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.
|
|
|
|
|
|
====Retroactive Invalidation====
|
|
|
|
In many instances, we would like to create contracts that can be revoked in case
|
|
of some future event. However, given the immutable nature of the blockchain, it
|
|
is practically impossible to retroactively invalidate a previous commitment that
|
|
has already confirmed. The only mechanism we really have for retroactive
|
|
invalidation is blockchain reorganization which, for fundamental security
|
|
reasons, is designed to be very hard and very expensive to deliberately pull off.
|
|
|
|
Despite this limitation, we do have a way to provide something functionally similar
|
|
using CHECKSEQUENCEVERIFY. By constructing scripts with multiple branches of
|
|
execution where one or more of the branches are delayed we provide
|
|
a time window in which someone can supply an invalidation condition that allows the
|
|
output to be spent, effectively invalidating the would-be delayed branch and potentially discouraging
|
|
another party from broadcasting the transaction in the first place. If the invalidation
|
|
condition does not occur before the timeout, the delayed branch becomes spendable,
|
|
honoring the original contract.
|
|
|
|
Some more specific applications of this idea:
|
|
|
|
|
|
=====Payment Channel Revocation=====
|
|
|
|
Scriptable relative locktime provides a predictable amount of time to respond in
|
|
the event a counterparty broadcasts a revoked transaction: Absolute locktime
|
|
necessitates closing the channel and reopen it when getting close to the timeout,
|
|
whereas with relative locktime, the clock starts ticking the moment the
|
|
transactions confirms in a block. It also provides a means to know exactly how
|
|
long to wait (in number of blocks) before funds can be pulled out of the channel
|
|
in the event of a noncooperative counterparty.
|
|
|
|
|
|
=====Bidirectional Payment Channels=====
|
|
|
|
The lightning network proposes bidirectional two-party payment channels
|
|
(between Alice and Bob) that would benefit from CHECKSEQUENCEVERIFY.
|
|
|
|
These channels are based on an anchor transaction that requires a 2-of-2
|
|
multisig from Alice and Bob, and a series of revocable commitment
|
|
transactions that spend the anchor transaction. The commitment
|
|
transaction splits the funds from the anchor between Alice and Bob and
|
|
the latest commitment transaction may be published by either party at
|
|
any time, finalising the channel.
|
|
|
|
Ideally then, a revoked commitment transaction would never be able to
|
|
be successfully spent; and the latest commitment transaction would be
|
|
able to be spent very quickly.
|
|
|
|
To allow a commitment transaction to be effectively revoked, Alice
|
|
and Bob have slightly different versions of the latest commitment
|
|
transaction. In Alice's version, any outputs in the commitment
|
|
transaction that pay Alice also include a forced delay, and an
|
|
alternative branch that allows Bob to spend the output if he knows that
|
|
transaction's revocation code. In Bob's version, payments to Bob are
|
|
similarly encumbered. When Alice and Bob negotiate new balances and
|
|
new commitment transactions, they also reveal the old revocation code,
|
|
thus committing to not relaying the old transaction.
|
|
|
|
A simple output, paying to Alice might then look like:
|
|
|
|
OP_HASH160 <revokehash> OP_EQUAL
|
|
OP_IF
|
|
OP_DUP OP_HASH160 <Bob key hash> OP_CHECKSIGVERIFY
|
|
OP_ELSE
|
|
24h OP_CHECKSEQUENCEVERIFY
|
|
OP_DUP OP_HASH160 <Alice key hash> OP_CHECKSIGVERIFY
|
|
OP_ENDIF
|
|
|
|
This allows Alice to publish the latest commitment transaction at any
|
|
time and spend the funds after 24 hours, but also ensures that if Alice
|
|
relays a revoked transaction, that Bob has 24 hours to claim the funds.
|
|
|
|
With CHECKLOCKTIMEVERIFY, this would look like:
|
|
|
|
OP_HASH160 <revokehash> OP_EQUAL
|
|
OP_IF
|
|
OP_DUP OP_HASH160 <Bob key hash> OP_CHECKSIGVERIFY
|
|
OP_ELSE
|
|
2015/12/15 OP_CHECKLOCKTIMEVERIFY
|
|
OP_DUP OP_HASH160 <Alice key hash> OP_CHECKSIGVERIFY
|
|
OP_ENDIF
|
|
|
|
This form of transaction would mean that if the anchor is unspent on
|
|
2015/12/16, Alice can use this commitment even if it has been revoked,
|
|
simply by spending it immediately, giving no time for Bob to claim it.
|
|
|
|
Ths means that the channel has a deadline that cannot be pushed
|
|
back without hitting the blockchain; and also that funds may not be
|
|
available until the deadline is hit. CHECKSEQUENCEVERIFY allows you
|
|
to avoid making that tradeoff.
|
|
|
|
Hashed Time-Lock Contracts (HTLCs) make this slightly more complicated,
|
|
since in principle they may pay either Alice or Bob, depending on whether
|
|
Alice discovers a secret R, or a timeout is reached, but the same principle
|
|
applies -- the branch paying Alice in Alice's commitment transaction gets a
|
|
delay, and the entire output can be claimed by the other party if the
|
|
revocation secret is known. With CHECKSEQUENCEVERIFY, a HTLC payable to
|
|
Alice might look like the following in Alice's commitment transaction:
|
|
|
|
OP_HASH160 OP_DUP <revokehash> OP_EQUAL
|
|
OP_IF
|
|
OP_DROP OP_DUP OP_HASH160 <Bob key hash> OP_CHECKSIGVERIFY
|
|
OP_ELSE
|
|
<R hash> OP_EQUAL
|
|
OP_IF
|
|
"24h" OP_CHECKSEQUENCEVERIFY OP_DROP
|
|
OP_DUP OP_HASH160 <Alice key hash> OP_CHECKSIGVERIFY
|
|
OP_ELSE
|
|
"2015/10/20 10:33" OP_CHECKLOCKTIMEVERIFY OP_DROP
|
|
OP_DUP OP_HASH160 <Bob key hash> OP_CHECKSIGVERIFY
|
|
OP_ENDIF
|
|
OP_ENDIF
|
|
|
|
and correspondingly in Bob's commitment transaction:
|
|
|
|
OP_HASH160 OP_DUP <revokehash> OP_EQUAL
|
|
OP_IF
|
|
OP_DROP OP_DUP OP_HASH160 <Alice key hash> OP_CHECKSIGVERIFY
|
|
OP_ELSE
|
|
<R hash> OP_EQUAL
|
|
OP_IF
|
|
OP_DUP OP_HASH160 <Alice key hash> OP_CHECKSIGVERIFY
|
|
OP_ELSE
|
|
"24h" OP_CHECKSEQUENCEVERIFY OP_DROP
|
|
"2015/10/20 10:33" OP_CHECKLOCKTIMEVERIFY OP_DROP
|
|
OP_DUP OP_HASH160 <Bob key hash> OP_CHECKSIGVERIFY
|
|
OP_ENDIF
|
|
OP_ENDIF
|
|
|
|
Note that both CHECKSEQUENCEVERIFY and CHECKLOCKTIMEVERIFY are used in the
|
|
final branch of above to ensure Bob cannot spend the output until after both
|
|
the timeout is complete and Alice has had time to reveal the revocation
|
|
secret.
|
|
|
|
See the [https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf Deployable Lightning] paper.
|
|
|
|
|
|
=====2-Way Pegged Sidechains=====
|
|
|
|
OP_IF
|
|
lockTxHeight <lockTxHash> nlocktxOut [<workAmount>] reorgBounty Hash160(<...>) <genesisHash> OP_REORGPROOFVERIFY
|
|
OP_ELSE
|
|
withdrawLockTime OP_CHECKSEQUENCEVERIFY OP_DROP OP_HASH160 p2shWithdrawDest OP_EQUAL
|
|
OP_ENDIF
|
|
|
|
|
|
==Specification==
|
|
|
|
Refer to the reference implementation, reproduced below, for the precise
|
|
semantics and detailed rationale for those semantics.
|
|
|
|
|
|
/* Threshold for nSequence: below this value it is interpreted
|
|
* as a relative lock-time, otherwise ignored. */
|
|
static const uint32_t SEQUENCE_LOCKTIME_THRESHOLD = (1 << 31);
|
|
|
|
/* Threshold for nSequence when interpreted as a relative
|
|
* lock-time: below this value it has units of blocks, otherwise
|
|
* seconds. */
|
|
static const uint32_t SEQUENCE_UNITS_THRESHOLD = (1 << 30);
|
|
|
|
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 elsewhere numeric opcodes are limited to
|
|
// operands in the range -2**31+1 to 2**31-1, however it is
|
|
// legal for opcodes to produce results exceeding that
|
|
// range. This limitation is implemented by CScriptNum's
|
|
// default 4-byte limit.
|
|
//
|
|
// If we kept to that limit we'd have a year 2038 problem,
|
|
// even though the nLockTime field in transactions
|
|
// themselves is uint32 which only becomes meaningless
|
|
// after the year 2106.
|
|
//
|
|
// 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
|
|
// some arithmetic being done first, you can always use
|
|
// 0 MAX CHECKSEQUENCEVERIFY.
|
|
if (nSequence < 0)
|
|
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
|
|
|
|
// To provide for future soft-fork extensibility, if the
|
|
// operand is too large to be treated as a relative lock-
|
|
// 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);
|
|
|
|
break;
|
|
}
|
|
|
|
bool CheckSequence(const CScriptNum& nSequence) const
|
|
{
|
|
// 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 if the transaction's version number is not set high
|
|
// enough to trigger BIP 68 rules.
|
|
if (static_cast<uint32_t>(txTo->nVersion) < 2)
|
|
return false;
|
|
|
|
// Sequence numbers above SEQUENCE_LOCKTIME_THRESHOLD
|
|
// are not consensus constrained. Testing that the transaction's
|
|
// sequence number is not above this threshold prevents
|
|
// using this property to get around a CHECKSEQUENCEVERIFY
|
|
// check.
|
|
if (txToSequence >= SEQUENCE_LOCKTIME_THRESHOLD)
|
|
return false;
|
|
|
|
// There are two kinds of nSequence: lock-by-blockheight
|
|
// and lock-by-blocktime, distinguished by whether
|
|
// nSequence < SEQUENCE_UNITS_THRESHOLD.
|
|
//
|
|
// We want to compare apples to apples, so fail the script
|
|
// unless the type of nSequence being tested is the same as
|
|
// the nSequence in the transaction.
|
|
if (!(
|
|
(txToSequence < SEQUENCE_UNITS_THRESHOLD && nSequence < SEQUENCE_UNITS_THRESHOLD) ||
|
|
(txToSequence >= SEQUENCE_UNITS_THRESHOLD && nSequence >= SEQUENCE_UNITS_THRESHOLD)
|
|
))
|
|
return false;
|
|
|
|
// Now that we know we're comparing apples-to-apples, the
|
|
// comparison is a simple numeric one.
|
|
if (nSequence > txToSequence)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
==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 = 4. The new rules are
|
|
in effect for every block (at height H) with nVersion = 4 and at least
|
|
750 out of 1000 blocks preceding it (with heights H-1000..H-1) also
|
|
have nVersion = 4. Furthermore, when 950 out of the 1000 blocks
|
|
preceding a block do have nVersion = 4, nVersion = 3 blocks become
|
|
invalid, and all further blocks enforce the new rules.
|
|
|
|
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.
|
|
|
|
Thanks to Eric Lombrozo and Anthony Towns for contributing example usecases.
|
|
|
|
|
|
==References==
|
|
|
|
[https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki BIP 68] Consensus-enforced transaction replacement signalled via sequence numbers
|
|
|
|
[https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP 65] OP_CHECKLOCKTIMEVERIFY
|
|
|
|
[https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki BIP 113] Median past block time for time-lock constraints
|
|
|
|
[http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and revocation hashes]
|
|
|
|
[http://lightning.network/lightning-network-paper.pdf Lightning Network]
|
|
|
|
[https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf Deployable Lightning]
|
|
|
|
[http://diyhpl.us/diyhpluswiki/transcripts/sf-bitcoin-meetup/2015-02-23-scaling-bitcoin-to-billions-of-transactions-per-day/ Scaling Bitcoin to Billions of Transactions Per Day]
|
|
|
|
[http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html Softfork deployment considerations]
|
|
|
|
[https://gist.github.com/sipa/bf69659f43e763540550 Version bits]
|
|
|
|
[https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2013-April/002433.html Jeremy Spilman Micropayment Channels]
|
|
|
|
|
|
==Copyright==
|
|
|
|
This document is placed in the public domain.
|
|
|