<div dir="ltr"><div><div>As per the rules of BIP 1, I hereby request that the BIP editor please assign an official number to this work. The idea has been discussed before on the bitcoin-dev mailing list:<br><br><a href="http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-June/008452.html">http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-June/008452.html</a><br><br></div>And a reference implementation is available here:<br><br><a href="https://github.com/maaku/bitcoin/tree/checksequenceverify">https://github.com/maaku/bitcoin/tree/checksequenceverify</a><br><br></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Aug 13, 2015 at 4:06 AM, Btc Drak via bitcoin-dev <span dir="ltr">&lt;<a href="mailto:bitcoin-dev@lists.linuxfoundation.org" target="_blank">bitcoin-dev@lists.linuxfoundation.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I have written the following draft BIP for a new opcode<br>
CHECKSEQUENCEVERIFY by Mark Friedenbach, which introduces a form of<br>
relative-locktime to Bitcoin&#39;s scripting language.<br>
<br>
<a href="https://github.com/btcdrak/bips/blob/bip-checksequenceverify/bip-csv.mediawiki" rel="noreferrer" target="_blank">https://github.com/btcdrak/bips/blob/bip-checksequenceverify/bip-csv.mediawiki</a><br>
<br>
&lt;pre&gt;<br>
  BIP: XX<br>
  Title: CHECKSEQUENCEVERIFY<br>
  Authors: BtcDrak &lt;<a href="mailto:btcdrak@gmail.com" target="_blank">btcdrak@gmail.com</a>&gt;<br>
           Mark Friedenbach &lt;<a href="mailto:mark@friedenbach.org" target="_blank">mark@friedenbach.org</a>&gt;<br>
  Status: Draft<br>
  Type: Standards Track<br>
  Created: 2015-08-10<br>
&lt;/pre&gt;<br>
<br>
==Abstract==<br>
<br>
This BIP describes a new opcode (CHECKSEQUENCEVERIFY) for the Bitcoin<br>
scripting system that in combination with BIP 68 allows execution<br>
pathways of a script to be restricted based on the age of the output<br>
being spent.<br>
<br>
<br>
==Summary==<br>
<br>
CHECKSEQUENCEVERIFY redefines the existing NOP3 opcode. When executed<br>
it compares the top item on the stack to the inverse of the nSequence<br>
field of the transaction input containing the scriptSig. If the<br>
inverse of nSequence is less than the sequence threshold (1 &lt;&lt; 31),<br>
the transaction version is greater than or equal to 2, and the top<br>
item on the stack is less than or equal to the inverted nSequence,<br>
script evaluation continues as though a NOP was executed. Otherwise<br>
the script fails immediately.<br>
<br>
BIP 68&#39;s redefinition of nSequence prevents a non-final transaction<br>
from being selected for inclusion in a block until the corresponding<br>
input has reached the specified age, as measured in block heiht or<br>
block time. By comparing the argument to CHECKSEQUENCEVERIFY against<br>
the nSequence field, we indirectly verify a desired minimum age of the<br>
the output being spent; until that relative age has been reached any<br>
script execution pathway including the CHECKSEQUENCEVERIFY will fail<br>
to validate, causing the transaction not to be selected for inclusion<br>
in a block.<br>
<br>
<br>
==Motivation==<br>
<br>
BIP 68 repurposes the transaction nSequence field meaning by giving<br>
sequence numbers new consensus-enforced semantics as a relative<br>
lock-time. However, there is no way to build Bitcoin scripts to make<br>
decisions based on this field.<br>
<br>
By making the nSequence field accessible to script, it becomes<br>
possible to construct code pathways that only become accessible some<br>
minimum time after proof-of-publication. This enables a wide variety<br>
of applications in phased protocols such as escrow, payment channels,<br>
or bidirectional pegs.<br>
<br>
<br>
==Specification==<br>
<br>
Refer to the reference implementation, reproduced below, for the precise<br>
semantics and detailed rationale for those semantics.<br>
<br>
<br>
    case OP_NOP3:<br>
    {<br>
        if (!(flags &amp; SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {<br>
            // not enabled; treat as a NOP3<br>
            if (flags &amp; SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {<br>
                return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);<br>
            }<br>
            break;<br>
        }<br>
<br>
        if (stack.size() &lt; 1)<br>
            return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);<br>
<br>
        // Note that unlike CHECKLOCKTIMEVERIFY we do not need to<br>
        // accept 5-byte bignums since any value greater than or<br>
        // equal to SEQUENCE_THRESHOLD (= 1 &lt;&lt; 31) will be rejected<br>
        // anyway. This limitation just happens to coincide with<br>
        // CScriptNum&#39;s default 4-byte limit with an explicit sign<br>
        // bit.<br>
        //<br>
        // This means there is a maximum relative lock time of 52<br>
        // years, even though the nSequence field in transactions<br>
        // themselves is uint32_t and could allow a relative lock<br>
        // time of up to 120 years.<br>
        const CScriptNum nInvSequence(stacktop(-1), fRequireMinimal);<br>
<br>
        // In the rare event that the argument may be &lt; 0 due to<br>
        // some arithmetic being done first, you can always use<br>
        // 0 MAX CHECKSEQUENCEVERIFY.<br>
        if (nInvSequence &lt; 0)<br>
            return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);<br>
<br>
        // Actually compare the specified inverse sequence number<br>
        // with the input.<br>
        if (!CheckSequence(nInvSequence))<br>
            return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);<br>
<br>
        break;<br>
    }<br>
<br>
    bool CheckSequence(const CScriptNum&amp; nInvSequence) const<br>
    {<br>
        int64_t txToInvSequence;<br>
<br>
        // Fail under all circumstances if the transaction&#39;s version<br>
        // number is not set high enough to enable enforced sequence<br>
        // number rules.<br>
        if (txTo-&gt;nVersion &lt; 2)<br>
            return false;<br>
<br>
        // Sequence number must be inverted to convert it into a<br>
        // relative lock-time.<br>
        txToInvSequence = (int64_t)~txTo-&gt;vin[nIn].nSequence;<br>
<br>
        // Sequence numbers under SEQUENCE_THRESHOLD are not consensus<br>
        // constrained.<br>
        if (txToInvSequence &gt;= SEQUENCE_THRESHOLD)<br>
            return false;<br>
<br>
        // There are two types of relative lock-time: lock-by-<br>
        // blockheight and lock-by-blocktime, distinguished by<br>
        // whether txToInvSequence &lt; LOCKTIME_THRESHOLD.<br>
        //<br>
        // We want to compare apples to apples, so fail the script<br>
        // unless the type of lock-time being tested is the same as<br>
        // the lock-time in the transaction input.<br>
        if (!(<br>
            (txToInvSequence &lt;  LOCKTIME_THRESHOLD &amp;&amp; nInvSequence &lt;<br>
LOCKTIME_THRESHOLD) ||<br>
            (txToInvSequence &gt;= LOCKTIME_THRESHOLD &amp;&amp; nInvSequence &gt;=<br>
LOCKTIME_THRESHOLD)<br>
        ))<br>
            return false;<br>
<br>
        // Now that we know we&#39;re comparing apples-to-apples, the<br>
        // comparison is a simple numeric one.<br>
        if (nInvSequence &gt; txInvToSequence)<br>
            return false;<br>
<br>
        return true;<br>
    }<br>
<br>
<a href="https://github.com/maaku/bitcoin/commit/33be476a60fcc2afbe6be0ca7b93a84209173eb2" rel="noreferrer" target="_blank">https://github.com/maaku/bitcoin/commit/33be476a60fcc2afbe6be0ca7b93a84209173eb2</a><br>
<br>
<br>
==Example: Escrow with Timeout==<br>
<br>
An escrow that times out automatically 30 days after being funded can be<br>
established in the following way. Alice, Bob and Escrow create a 2-of-3<br>
address with the following redeemscript.<br>
<br>
    IF<br>
        2 &lt;Alice&#39;s pubkey&gt; &lt;Bob&#39;s pubkey&gt; &lt;Escrow&#39;s pubkey&gt; 3<br>
CHECKMULTISIGVERIFY<br>
    ELSE<br>
        &lt;LOCKTIME_THRESHOLD + 30*24*60*60&gt; CHECKSEQUENCEVERIFY DROP<br>
        &lt;Alice&#39;s pubkey&gt; CHECKSIGVERIFY<br>
    ENDIF<br>
<br>
At any time funds can be spent using signatures from any two of Alice,<br>
Bob or the Escrow.<br>
<br>
After 30 days Alice can sign alone.<br>
<br>
The clock does not start ticking until the payment to the escrow address<br>
confirms.<br>
<br>
<br>
==Reference Implementation==<br>
<br>
A reference implementation is provided in the following git repository:<br>
<br>
<a href="https://github.com/maaku/bitcoin/tree/checksequenceverify" rel="noreferrer" target="_blank">https://github.com/maaku/bitcoin/tree/checksequenceverify</a><br>
<br>
<br>
==Deployment==<br>
<br>
We reuse the double-threshold switchover mechanism from BIPs 34 and<br>
66, with the same thresholds, but for nVersion = 4. The new rules are<br>
in effect for every block (at height H) with nVersion = 4 and at least<br>
750 out of 1000 blocks preceding it (with heights H-1000..H-1) also<br>
have nVersion = 4. Furthermore, when 950 out of the 1000 blocks<br>
preceding a block do have nVersion = 4, nVersion = 3 blocks become<br>
invalid, and all further blocks enforce the new rules.<br>
<br>
It is recommended that this soft-fork deployment trigger include other<br>
related proposals for improving Bitcoin&#39;s lock-time capabilities, including:<br>
<br>
[<a href="https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki" rel="noreferrer" target="_blank">https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki</a> BIP 65]:<br>
OP_CHECKLOCKTIMEVERIFY,<br>
<br>
[<a href="https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki" rel="noreferrer" target="_blank">https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki</a> BIP 68]:<br>
Consensus-enforced transaction replacement signalled via sequence numbers,<br>
<br>
and [<a href="https://github.com/bitcoin/bips/blob/master/bip-00XX.mediawiki" rel="noreferrer" target="_blank">https://github.com/bitcoin/bips/blob/master/bip-00XX.mediawiki</a> BIP XX]:<br>
Median-Past-Time-Lock.<br>
<br>
<br>
==Credits==<br>
<br>
Mark Friedenbach invented the application of sequence numbers to<br>
achieve relative lock-time, and wrote the reference implementation of<br>
CHECKSEQUENCEVERIFY.<br>
<br>
The reference implementation and this BIP was based heavily on work<br>
done by Peter Todd for the closely related BIP 65.<br>
<br>
BtcDrak authored this BIP document.<br>
<br>
<br>
==References==<br>
<br>
BIP 68: Consensus-enforced transaction replacement signalled via<br>
sequence numbers<br>
<a href="https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki" rel="noreferrer" target="_blank">https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki</a><br>
<br>
BIP 65: OP_CHECKLOCKTIMEVERIFY<br>
<a href="https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki" rel="noreferrer" target="_blank">https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki</a><br>
<br>
BIP XX: Median past block time for time-lock constraints<br>
<a href="https://github.com/bitcoin/bips/blob/master/bip-00XX.mediawiki" rel="noreferrer" target="_blank">https://github.com/bitcoin/bips/blob/master/bip-00XX.mediawiki</a><br>
<br>
HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and<br>
revocation hashes<br>
<a href="http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html" rel="noreferrer" target="_blank">http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html</a><br>
<br>
<br>
==Copyright==<br>
<br>
This document is placed in the public domain.<br>
_______________________________________________<br>
bitcoin-dev mailing list<br>
<a href="mailto:bitcoin-dev@lists.linuxfoundation.org" target="_blank">bitcoin-dev@lists.linuxfoundation.org</a><br>
<a href="https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev" rel="noreferrer" target="_blank">https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev</a><br>
</blockquote></div><br></div></div></div></div>