diff options
author | Peter Todd <pete@petertodd.org> | 2014-11-10 04:43:09 -0500 |
---|---|---|
committer | Peter Todd <pete@petertodd.org> | 2014-11-10 08:22:48 -0500 |
commit | b05bc1ef5348a4d50bc3012865534b73dbc2164d (patch) | |
tree | e0b984f63bd6a4d1b7653f47a9cb17d63ecadedc /bip-0065.mediawiki | |
parent | 5f6cb04d9c28b76f33f18dbf43923c88860c2592 (diff) |
BIP65 assigned for CHECKLOCKTIMEVERIFY
Diffstat (limited to 'bip-0065.mediawiki')
-rw-r--r-- | bip-0065.mediawiki | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/bip-0065.mediawiki b/bip-0065.mediawiki new file mode 100644 index 0000000..9574374 --- /dev/null +++ b/bip-0065.mediawiki @@ -0,0 +1,284 @@ +<pre> + BIP: 65 + 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 +requires 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. |