diff options
author | Luke-Jr <luke_github1@dashjr.org> | 2015-09-19 18:13:48 +0000 |
---|---|---|
committer | Luke-Jr <luke_github1@dashjr.org> | 2015-09-19 18:13:48 +0000 |
commit | 063a8ad82acacb6babc8dc238258f78b7996b810 (patch) | |
tree | b45d618165bc131102c4c739aa5e7351ec14c021 /bip-0112.mediawiki | |
parent | 4884b4377a323bcb667ee9fa58d7baaa122c36fe (diff) | |
parent | 6902f790f174c8af934869dcc5f10f94f816f65d (diff) | |
download | bips-063a8ad82acacb6babc8dc238258f78b7996b810.tar.xz |
Merge pull request #179 from btcdrak/bip-checksequenceverify
BIP112: CHECKSEQUENCEVERIFY
Diffstat (limited to 'bip-0112.mediawiki')
-rw-r--r-- | bip-0112.mediawiki | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/bip-0112.mediawiki b/bip-0112.mediawiki new file mode 100644 index 0000000..c06caf5 --- /dev/null +++ b/bip-0112.mediawiki @@ -0,0 +1,246 @@ +<pre> + BIP: 112 + Title: CHECKSEQUENCEVERIFY + Authors: BtcDrak <btcdrak@gmail.com> + Mark Friedenbach <mark@friedenbach.org> + 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 inverse of the nSequence +field of the transaction input containing the scriptSig. If the +inverse of nSequence is less than the sequence threshold (1 << 31), +the transaction version is greater than or equal to 2, and the top +item on the stack is less than or equal to the inverted nSequence, +script evaluation continues as though a NOP was executed. Otherwise +the script fails immediately. + +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. + + +==Specification== + +Refer to the reference implementation, reproduced below, for the precise +semantics and detailed rationale for those semantics. + + + // Threshold for nLockTime: below this value it is interpreted as block number, + // otherwise as UNIX timestamp (already defined in Bitcoin Core). + static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC + + // Threshold for inverted nSequence: below this value it is interpreted + // as a relative lock-time, otherwise ignored. + static const uint32_t SEQUENCE_THRESHOLD = (1 << 31); + + 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 unlike CHECKLOCKTIMEVERIFY we do not need to + // accept 5-byte bignums since any value greater than or + // equal to SEQUENCE_THRESHOLD (= 1 << 31) will be rejected + // anyway. This limitation just happens to coincide with + // CScriptNum's default 4-byte limit with an explicit sign + // bit. + // + // This means there is a maximum relative lock time of 52 + // years, even though the nSequence field in transactions + // themselves is uint32_t and could allow a relative lock + // time of up to 120 years. + const CScriptNum nInvSequence(stacktop(-1), fRequireMinimal); + + // 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 (nInvSequence < 0) + return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME); + + // Actually compare the specified inverse sequence number + // with the input. + if (!CheckSequence(nInvSequence)) + return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME); + + break; + } + + bool CheckSequence(const CScriptNum& nInvSequence) const + { + int64_t txToInvSequence; + + // Fail under all circumstances if the transaction's version + // number is not set high enough to enable enforced sequence + // number rules. + if (txTo->nVersion < 2) + return false; + + // Sequence number must be inverted to convert it into a + // relative lock-time. + txToInvSequence = (int64_t)~txTo->vin[nIn].nSequence; + + // Sequence numbers under SEQUENCE_THRESHOLD are not consensus + // constrained. + if (txToInvSequence >= SEQUENCE_THRESHOLD) + return false; + + // There are two types of relative lock-time: lock-by- + // blockheight and lock-by-blocktime, distinguished by + // whether txToInvSequence < LOCKTIME_THRESHOLD. + // + // We want to compare apples to apples, so fail the script + // unless the type of lock-time being tested is the same as + // the lock-time in the transaction input. + if (!( + (txToInvSequence < LOCKTIME_THRESHOLD && nInvSequence < LOCKTIME_THRESHOLD) || + (txToInvSequence >= LOCKTIME_THRESHOLD && nInvSequence >= LOCKTIME_THRESHOLD) + )) + return false; + + // Now that we know we're comparing apples-to-apples, the + // comparison is a simple numeric one. + if (nInvSequence > txToInvSequence) + return false; + + return true; + } + +https://github.com/maaku/bitcoin/commit/33be476a60fcc2afbe6be0ca7b93a84209173eb2 + + +==Example: 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. + + +==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 = 8. The new rules are +in effect for every block (at height H) with nVersion = 8 and at least +750 out of 1000 blocks preceding it (with heights H-1000..H-1) also +have nVersion = 8. Furthermore, when 950 out of the 1000 blocks +preceding a block do have nVersion = 8, nVersion = 3 blocks become +invalid, and all further blocks enforce the new rules. + +When assessing the block version as mask of ~0x20000007 must be applied +to work around the complications caused by +[http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html BIP101's premature use] +of the [https://gist.github.com/sipa/bf69659f43e763540550 undecided version bits proposal]. + +By applying ~0x20000007 with nVersion = 8, the thresholds should be tested +comparing block nVersion >= 4 as this will save a bit for future use. + +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. + + +==References== + +BIP 68: Consensus-enforced transaction replacement signalled via +sequence numbers +https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki + +BIP 65: OP_CHECKLOCKTIMEVERIFY +https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki + +BIP 113: Median past block time for time-lock constraints +https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki + +HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and +revocation hashes +http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html + +[http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html Softfork deployment considerations] + +[https://gist.github.com/sipa/bf69659f43e763540550 Version bits] + + +==Copyright== + +This document is placed in the public domain. |