<oembed><type>rich</type><version>1.0</version><author_name>npub1m230cem2yh3mtdzkg32qhj73uytgkyg5ylxsu083n3tpjnajxx4qqa2np2</author_name><author_url>https://nostr.ae/npub1m230cem2yh3mtdzkg32qhj73uytgkyg5ylxsu083n3tpjnajxx4qqa2np2</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2014-10-01&#xA;📝 Original message:I&#39;ve written a reference implementation and BIP draft for a new opcode,&#xA;CHECKLOCKTIMEVERIFY. The BIP, reproduced below, can be found at:&#xA;&#xA;    https://github.com/petertodd/bips/blob/checklocktimeverify/bip-checklocktimeverify.mediawiki&#xA;&#xA;The reference implementation, including a full-set of unittests for the&#xA;opcode semantics can be found at:&#xA;&#xA;    https://github.com/petertodd/bitcoin/compare/checklocktimeverify&#xA;&#xA;&lt;pre&gt;&#xA;  BIP:&#xA;  Title: OP_CHECKLOCKTIMEVERIFY&#xA;  Author: Peter Todd &lt;pete at petertodd.org&gt;&#xA;  Status: Draft&#xA;  Type: Standards Track&#xA;  Created: 2014-10-01&#xA;&lt;/pre&gt;&#xA;&#xA;==Abstract==&#xA;&#xA;This BIP describes a new opcode (OP_CHECKLOCKTIMEVERIFY) for the Bitcoin&#xA;scripting system that allows a transaction output to be made unspendable until&#xA;some point in the future.&#xA;&#xA;&#xA;==Summary==&#xA;&#xA;CHECKLOCKTIMEVERIFY re-defines the existing NOP2 opcode. When executed it&#xA;compares the top item on the stack to the nLockTime field of the transaction&#xA;containing the scriptSig. If that top stack item is greater than the transation&#xA;nLockTime the script fails immediately, otherwise script evaluation continues&#xA;as though a NOP was executed.&#xA;&#xA;The nLockTime field in a transaction prevents the transaction from being mined&#xA;until either a certain block height, or block time, has been reached. By&#xA;comparing the argument to CHECKLOCKTIMEVERIFY against the nLockTime field, we&#xA;indirectly verify that the desired block height or block time has been reached;&#xA;until that block height or block time has been reached the transaction output&#xA;remains unspendable.&#xA;&#xA;&#xA;==Motivation==&#xA;&#xA;The nLockTime field in transactions makes it possible to prove that a&#xA;transaction output can be spent in the future: a valid signature for a&#xA;transaction with the desired nLockTime can be constructed, proving that it is&#xA;possible to spend the output with that signature when the nLockTime is reached.&#xA;An example where this technique is used is in micro-payment channels, where the&#xA;nLockTime field proves that should the receiver vanish the sender is guaranteed&#xA;to get all their escrowed funds back when the nLockTime is reached.&#xA;&#xA;However the nLockTime field is insufficient if you wish to prove that&#xA;transaction output &#39;&#39;can-not&#39;&#39; be spent until some time in the future, as there&#xA;is no way to prove that the secret keys corresponding to the pubkeys controling&#xA;the funds have not been used to create a valid signature.&#xA;&#xA;&#xA;===Escrow===&#xA;&#xA;If Alice and Bob jointly operate a business they may want to&#xA;ensure that all funds are kept in 2-of-2 multisig transaction outputs that&#xA;require the co-operation of both parties to spend. However, they recognise that&#xA;in exceptional circumstances such as either party getting &#34;hit by a bus&#34; they&#xA;need a backup plan to retrieve the funds. So they appoint their lawyer, Lenny,&#xA;to act as a third-party.&#xA;&#xA;With a standard 2-of-3 CHECKMULTISIG at any time Lenny could conspire with&#xA;either Alice or Bob to steal the funds illegitimately. Equally Lenny may prefer&#xA;not to have immediate access to the funds to discourage bad actors from&#xA;attempting to get the secret keys from him by force.&#xA;&#xA;However with CHECKLOCKTIMEVERIFY the funds can be stored in scriptPubKeys of&#xA;the form:&#xA;&#xA;    IF&#xA;        &lt;now + 3 months&gt; CHECKLOCKTIMEVERIFY DROP&#xA;        &lt;Lenny&#39;s pubkey&gt; CHECKSIGVERIFY&#xA;        1&#xA;    ELSE&#xA;        2&#xA;    ENDIF&#xA;    &lt;Alice&#39;s pubkey&gt; &lt;Bob&#39;s pubkey&gt; 2 CHECKMULTISIG&#xA;&#xA;At any time the funds can be spent with the following scriptSig:&#xA;&#xA;    &lt;Alice&#39;s signature&gt; &lt;Bob&#39;s signature&gt; 0&#xA;&#xA;After 3 months have passed Lenny and one of either Alice or Bob can spend the&#xA;funds with the following scriptSig:&#xA;&#xA;    &lt;Alice/Bob&#39;s signature&gt; &lt;Lenny&#39;s signature&gt; 1&#xA;&#xA;&#xA;===Non-interactive time-locked refunds===&#xA;&#xA;There exist a number of protocols where a transaction output is created that&#xA;the co-operation of both parties to spend the output. To ensure the failure of&#xA;one party does not result in the funds becoming lost refund transactions are&#xA;setup in advance using nLockTime. These refund transactions need to be created&#xA;interactively, and additionaly, are currently vulnerable to transaction&#xA;mutability. CHECKLOCKTIMEVERIFY can be used in these protocols, replacing the&#xA;interactive setup with a non-interactive setup, and additionally, making&#xA;transaction mutability a non-issue.&#xA;&#xA;&#xA;====Two-factor wallets====&#xA;&#xA;Services like GreenAddress store Bitcoins with 2-of-2 multisig scriptPubKey&#39;s&#xA;such that one keypair is controlled by the user, and the other keypair is&#xA;controlled by the service. To spend funds the user uses locally installed&#xA;wallet software that generates one of the required signatures, and then uses a&#xA;2nd-factor authentication method to authorize the service to create the second&#xA;SIGHASH_NONE signature that is locked until some time in the future and sends&#xA;the user that signature for storage. If the user needs to spend their funds and&#xA;the service is not available, they wait until the nLockTime expires.&#xA;&#xA;The problem is there exist numerous occasions the user will not have a valid&#xA;signature for some or all of their transaction outputs. With&#xA;CHECKLOCKTIMEVERIFY rather than creating refund signatures on demand&#xA;scriptPubKeys of the following form are used instead:&#xA;&#xA;    IF&#xA;        &lt;service pubkey&gt; CHECKSIGVERIFY&#xA;    ELSE&#xA;        &lt;expiry time&gt; CHECKLOCKTIMEVERIFY DROP&#xA;    ENDIF&#xA;    &lt;user pubkey&gt; CHECKSIG&#xA;&#xA;Now the user is always able to spend their funds without the co-operation of&#xA;the service by waiting for the expiry time to be reached.&#xA;&#xA;&#xA;====Micropayment Channels====&#xA;&#xA;Jeremy Spilman style micropayment channels first setup a deposit controlled by&#xA;2-of-2 multisig, tx1, and then adjust a second transaction, tx2, that spends&#xA;the output of tx1 to payor and payee. Prior to publishing tx1 a refund&#xA;transaction is created, tx3, to ensure that should the payee vanish the payor&#xA;can get their deposit back. The process by which the refund transaction is&#xA;created is currently vulnerable to transaction mutability attacks, and&#xA;additionally, requires the payor to store the refund. Using the same&#xA;scriptPubKey from as in the Two-factor wallets example solves both these issues.&#xA;&#xA;&#xA;===Trustless Payments for Publishing Data===&#xA;&#xA;The PayPub protocol makes it possible to pay for information in a trustless way&#xA;by first proving that an encrypted file contains the desired data, and secondly&#xA;crafting scriptPubKeys used for payment such that spending them reveals the&#xA;encryption keys to the data. However the existing implementation has a&#xA;significant flaw: the publisher can delay the release of the keys indefinitely.&#xA;&#xA;This problem can be solved interactively with the refund transaction technique;&#xA;with CHECKLOCKTIMEVERIFY the problem can be non-interactively solved using&#xA;scriptPubKeys of the following form:&#xA;&#xA;    IF&#xA;        HASH160 &lt;Hash160(encryption key)&gt; EQUALVERIFY&#xA;        &lt;publisher pubkey&gt; CHECKSIG&#xA;    ELSE&#xA;        &lt;expiry time&gt; CHECKLOCKTIMEVERIFY DROP&#xA;        &lt;buyer pubkey&gt; CHECKSIG&#xA;    ENDIF&#xA;&#xA;The buyer of the data is now making a secure offer with an expiry time. If the&#xA;publisher fails to accept the offer before the expiry time is reached the buyer&#xA;can cancel the offer by spending the output.&#xA;&#xA;&#xA;===Proving sacrifice to miners&#39; fees===&#xA;&#xA;Proving the sacrifice of some limited resource is a common technique in a&#xA;variety of cryptographic protocols. Proving sacrifices of coins to mining fees&#xA;has been proposed as a &#39;&#39;universal public good&#39;&#39; to which the sacrifice could&#xA;be directed, rather than simply destroying the coins. However doing so is&#xA;non-trivial, and even the best existing technqiue - announce-commit sacrifices&#xA;- could encourage mining centralization. CHECKLOCKTIMEVERIFY can be used to&#xA;create outputs that are provably spendable by anyone (thus to mining fees&#xA;assuming miners behave optimally and rationally) but only at a time&#xA;sufficiently far into the future that large miners profitably can&#39;t sell the&#xA;sacrifices at a discount.&#xA;&#xA;&#xA;===Replacing the nLockTime field entirely===&#xA;&#xA;As an aside, note how if the SignatureHash() algorithm could optionally cover&#xA;part of the scriptSig the signature could require that the scriptSig contain&#xA;CHECKLOCKTIMEVERIFY opcodes, and additionally, require that they be executed.&#xA;(the CODESEPARATOR opcode came very close to making this possible in v0.1 of&#xA;Bitcoin) This per-signature capability could replace the per-transaction&#xA;nLockTime field entirely as a valid signature would now be the proof that a&#xA;transaction output &#39;&#39;can&#39;&#39; be spent.&#xA;&#xA;&#xA;==Detailed Specification==&#xA;&#xA;Refer to the reference implementation, reproduced below, for the precise&#xA;semantics and detailed rationale for those semantics.&#xA;&#xA;    case OP_NOP2:&#xA;    {&#xA;        // CHECKLOCKTIMEVERIFY&#xA;        //&#xA;        // (nLockTime -- nLockTime )&#xA;    &#xA;        if (!(flags &amp; SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY))&#xA;            break; // not enabled; treat as a NOP&#xA;    &#xA;        if (stack.size() &lt; 1)&#xA;            return false;&#xA;    &#xA;        // Note that elsewhere numeric opcodes are limited to&#xA;        // operands in the range -2**31+1 to 2**31-1, however it is&#xA;        // legal for opcodes to produce results exceeding that&#xA;        // range. This limitation is implemented by CScriptNum&#39;s&#xA;        // default 4-byte limit.&#xA;        //&#xA;        // If we kept to that limit we&#39;d have a year 2038 problem,&#xA;        // even though the nLockTime field in transactions&#xA;        // themselves is uint32 which only becomes meaningless&#xA;        // after the year 2106.&#xA;        //&#xA;        // Thus as a special case we tell CScriptNum to accept up&#xA;        // to 5-byte bignums, which are good until 2**32-1, the&#xA;        // same limit as the nLockTime field itself.&#xA;        const CScriptNum nLockTime(stacktop(-1), 5);&#xA;    &#xA;        // In the rare event that the argument may be &lt; 0 due to&#xA;        // some arithmetic being done first, you can always use&#xA;        // 0 MAX CHECKLOCKTIMEVERIFY.&#xA;        if (nLockTime &lt; 0)&#xA;            return false;&#xA;    &#xA;        // There are two times of nLockTime: lock-by-blockheight&#xA;        // and lock-by-blocktime, distinguished by whether&#xA;        // nLockTime &lt; LOCKTIME_THRESHOLD.&#xA;        //&#xA;        // We want to compare apples to apples, so fail the script&#xA;        // unless the type of nLockTime being tested is the same as&#xA;        // the nLockTime in the transaction.&#xA;        if (!(&#xA;              (txTo.nLockTime &lt;  LOCKTIME_THRESHOLD &amp;&amp; nLockTime &lt;  LOCKTIME_THRESHOLD) ||&#xA;              (txTo.nLockTime &gt;= LOCKTIME_THRESHOLD &amp;&amp; nLockTime &gt;= LOCKTIME_THRESHOLD)&#xA;             ))&#xA;            return false;&#xA;    &#xA;        // Now that we know we&#39;re comparing apples-to-apples, the&#xA;        // comparison is a simple numeric one.&#xA;        if (nLockTime &gt; (int64_t)txTo.nLockTime)&#xA;            return false;&#xA;    &#xA;        // Finally the nLockTime feature can be disabled and thus&#xA;        // CHECKLOCKTIMEVERIFY bypassed if every txin has been&#xA;        // finalized by setting nSequence to maxint. The&#xA;        // transaction would be allowed into the blockchain, making&#xA;        // the opcode ineffective.&#xA;        //&#xA;        // Testing if this vin is not final is sufficient to&#xA;        // prevent this condition. Alternatively we could test all&#xA;        // inputs, but testing just this input minimizes the data&#xA;        // required to prove correct CHECKLOCKTIMEVERIFY execution.&#xA;        if (txTo.vin[nIn].IsFinal())&#xA;            return false;&#xA;    &#xA;        break;&#xA;    &#xA;    }&#xA;&#xA;https://github.com/petertodd/bitcoin/commit/ab0f54f38e08ee1e50ff72f801680ee84d0f1bf4&#xA;&#xA;&#xA;==Upgrade and Testing Plan==&#xA;&#xA;TBD&#xA;&#xA;&#xA;==Credits==&#xA;&#xA;Thanks goes to Gregory Maxwell for suggesting that the argument be compared&#xA;against the per-transaction nLockTime, rather than the current block height and&#xA;time.&#xA;&#xA;&#xA;==References==&#xA;&#xA;PayPub - https://github.com/unsystem/paypub&#xA;&#xA;Jeremy Spilman Micropayment Channels - http://www.mail-archive.com/bitcoin-development%40lists.sourceforge.net/msg02028.html&#xA;&#xA;&#xA;==Copyright==&#xA;&#xA;This document is placed in the public domain.&#xA;&#xA;-- &#xA;&#39;peter&#39;[:-1]@petertodd.org&#xA;000000000000000009012f16fe9db21abbba5025453a9b7b589a807b21cec318&#xA;-------------- next part --------------&#xA;A non-text attachment was scrubbed...&#xA;Name: signature.asc&#xA;Type: application/pgp-signature&#xA;Size: 650 bytes&#xA;Desc: Digital signature&#xA;URL: &lt;http://lists.linuxfoundation.org/pipermail/bitcoin-dev/attachments/20141001/e8e4213b/attachment.sig&gt;</html></oembed>