public inbox for bitcoindev@googlegroups.com
 help / color / mirror / Atom feed
From: Matt Corallo <bitcoin-list@bluematt.me>
To: bitcoin-development@lists.sourceforge.net
Subject: [Bitcoin-development] Relative CHECKLOCKTIMEVERIFY (was CLTV proposal)
Date: Mon, 16 Mar 2015 22:22:13 +0000	[thread overview]
Message-ID: <55075795.20904@bluematt.me> (raw)
In-Reply-To: <20141001130826.GM28710@savin.petertodd.org>

In building some CLTV-based contracts, it is often also useful to have a
method of requiring, instead of locktime-is-at-least-N,
locktime-is-at-least-N-plus-the-height-of-my-input. ie you could imagine
an OP_RELATIVECHECKLOCKTIMEVERIFY that reads (does not pop) the top
stack element, adds the height of the output being spent and then has
identical semantics to CLTV.
A slightly different API (and different name) was described by maaku at
http://www.reddit.com/r/Bitcoin/comments/2z2l91/time_to_lobby_bitcoins_core_devs_sf_bitcoin_devs/cpgc154
which does a better job of saving softfork-available opcode space.

There are two major drawbacks to adding such an operation, however.

1) More transaction information is exposed inside the script (prior to
CLTV we only had the sigchecking operation exposed, with a CLTV and
RCLTV/OP_CHECK_MATURITY_VERIFY we expose two more functions).

2) Bitcoin Core's mempool invariant of "all transactions in the mempool
could be thrown into one overside block and aside from block size, it
would be valid" becomes harder to enforce. Currently, during reorgs,
coinbase spends need checked (specifically, anything spending THE
coinbase 100 blocks ago needs checked) and locktime transactions need
checked. With such a new operation, any script which used this new
opcode during its execution would need to be re-evaluated during reorgs.

I think both of these requirements are reasonable and not particularly
cumbersome, and the value of such an operation is quite nice for some
protocols (including settings setting up a contest interval in a
sidechain data validation operation).

Thoughts?

Matt

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



  parent reply	other threads:[~2015-03-16 22:37 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-01 13:08 [Bitcoin-development] [BIP draft] CHECKLOCKTIMEVERIFY - Prevent a txout from being spent until an expiration time Peter Todd
2014-10-01 15:01 ` Gavin Andresen
2014-10-02  1:06   ` Peter Todd
2014-10-01 15:29 ` Sergio Lerner
2014-10-01 17:06   ` Peter Todd
2014-10-01 18:23 ` Luke Dashjr
2014-10-01 20:58   ` Gavin Andresen
2014-10-01 21:04     ` Alan Reiner
2014-10-01 21:34       ` Gavin Andresen
2014-10-02  0:12         ` Peter Todd
2014-10-02  0:05   ` Peter Todd
2014-10-02  0:55     ` Luke Dashjr
2014-10-02  1:09       ` Peter Todd
2014-10-02 15:05         ` Flavien Charlon
2014-10-03 14:28           ` Matt Whitlock
2014-10-03 14:30             ` Matt Whitlock
2014-10-03 16:17             ` Gregory Maxwell
2014-10-03 17:50             ` Luke Dashjr
2014-10-03 20:58               ` Mike Hearn
2014-10-03 23:12                 ` Jeff Garzik
2014-10-04  0:38                   ` Peter Todd
2014-10-04 12:58                     ` Mike Hearn
2014-10-07 15:50                       ` Gavin Andresen
2014-10-07 16:08                         ` Mike Hearn
2014-10-08 10:26                           ` Wladimir
2014-10-09  3:13                             ` Alan Reiner
2014-10-09  6:14                               ` Adam Back
2014-10-09  6:28                                 ` Gregory Maxwell
2014-10-09  6:33                                   ` Peter Todd
2014-10-09  6:40                                     ` Gregory Maxwell
2014-10-08  4:07                         ` Tom Harding
2014-10-08 10:15                           ` Mike Hearn
2015-03-16 22:22 ` Matt Corallo [this message]
2015-03-19 17:39   ` [Bitcoin-development] Relative CHECKLOCKTIMEVERIFY (was CLTV proposal) Zooko Wilcox-OHearn
2015-04-21  7:59   ` Peter Todd
2015-04-26 11:35     ` Jorge Timón
2015-04-26 12:20       ` Jorge Timón
2015-04-27 19:35         ` Peter Todd
2015-04-28  7:44           ` Jorge Timón
2015-05-04  2:15     ` Matt Corallo
2015-05-04 11:24       ` Jorge Timón
2015-05-05  0:41         ` Btc Drak
2015-05-05 19:19           ` Jorge Timón
2015-05-05 20:38         ` Tier Nolan
2015-05-06  7:37           ` Jorge Timón
2015-05-06 22:09             ` Tier Nolan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55075795.20904@bluematt.me \
    --to=bitcoin-list@bluematt.me \
    --cc=bitcoin-development@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox