From b962c479b3276ccb00a6c71d66532c5bdf6bacf8 Mon Sep 17 00:00:00 2001
From: BtcDrak <btcdrak@gmail.com>
Date: Sat, 26 Sep 2015 09:54:13 +0100
Subject: Amend BIP112 to fit BIP68 redefinition

---
 bip-0112.mediawiki | 107 +++++++++++++++++++++++++++--------------------------
 1 file changed, 55 insertions(+), 52 deletions(-)

(limited to 'bip-0112.mediawiki')

diff --git a/bip-0112.mediawiki b/bip-0112.mediawiki
index c06caf5..ef791b2 100644
--- a/bip-0112.mediawiki
+++ b/bip-0112.mediawiki
@@ -18,14 +18,9 @@ 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.
+CHECKSEQUENCEVERIFY redefines the existing NOP3 opcode. When executed it
+compares the top item on the stack to the nSequence field of the transaction
+input containing the scriptSig. **
 
 BIP 68's redefinition of nSequence prevents a non-final transaction
 from being selected for inclusion in a block until the corresponding
@@ -58,13 +53,14 @@ 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 nSequence: below this value it is interpreted
+     * as a relative lock-time, otherwise ignored. */
+    static const uint32_t SEQUENCE_LOCKTIME_THRESHOLD = (1 << 31);
     
-    // 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);
+    /* Threshold for nSequence when interpreted as a relative
+     * lock-time: below this value it has units of blocks, otherwise
+     * seconds. */
+    static const uint32_t SEQUENCE_UNITS_THRESHOLD = (1 << 30);
     
     case OP_NOP3:
     {
@@ -79,75 +75,81 @@ semantics and detailed rationale for those semantics.
         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.
+        // 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.
         //
-        // 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);
+        // 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**39-1, well
+        // beyond the 2**32-1 limit of the nLockTime field itself.
+        const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
         
         // 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)
+        if (nSequence < 0)
             return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
         
-        // Actually compare the specified inverse sequence number
-        // with the input.
-        if (!CheckSequence(nInvSequence))
+        // To provide for future soft-fork extensibility, if the
+        // operand is too large to be treated as a relative lock-
+        // time, CHECKSEQUENCEVERIFY behaves as a NOP.
+        if (nSequence >= SEQUENCE_LOCKTIME_THRESHOLD)
+            break;
+        
+        // Actually compare the specified sequence number with the input.
+        if (!CheckSequence(nSequence))
             return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
         
         break;
     }
     
-    bool CheckSequence(const CScriptNum& nInvSequence) const
+    bool CheckSequence(const CScriptNum& nSequence) const
     {
-        int64_t txToInvSequence;
+        // Relative lock times are supported by comparing the passed
+        // in operand to the sequence number of the input.
+        const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
         
-        // 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)
+        // Fail if the transaction's version number is not set high
+        // enough to trigger BIP 68 rules.
+        if (static_cast<uint32_t>(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)
+        // Sequence numbers above SEQUENCE_LOCKTIME_THRESHOLD
+        // are not consensus constrained. Testing that the transaction's
+        // sequence number is not above this threshold prevents
+        // using this property to get around a CHECKSEQUENCEVERIFY
+        // check.
+        if (txToSequence >= SEQUENCE_LOCKTIME_THRESHOLD)
             return false;
         
-        // There are two types of relative lock-time: lock-by-
-        // blockheight and lock-by-blocktime, distinguished by
-        // whether txToInvSequence < LOCKTIME_THRESHOLD.
+        // There are two kinds of nSequence: lock-by-blockheight
+        // and lock-by-blocktime, distinguished by whether
+        // nSequence < nThreshold (SEQUENCE_UNITS_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.
+        // unless the type of nSequence being tested is the same as
+        // the nSequence in the transaction.
         if (!(
-            (txToInvSequence <  LOCKTIME_THRESHOLD && nInvSequence <  LOCKTIME_THRESHOLD) ||
-            (txToInvSequence >= LOCKTIME_THRESHOLD && nInvSequence >= LOCKTIME_THRESHOLD)
+            (txToSequence <  nThreshold && nSequence <  nThreshold) ||
+            (txToSequence >= nThreshold && nSequence >= nThreshold)
         ))
             return false;
         
         // Now that we know we're comparing apples-to-apples, the
         // comparison is a simple numeric one.
-        if (nInvSequence > txToInvSequence)
+        if (nSequence > txToSequence)
             return false;
         
         return true;
     }
 
-https://github.com/maaku/bitcoin/commit/33be476a60fcc2afbe6be0ca7b93a84209173eb2
-
 
 ==Example: Escrow with Timeout==
 
@@ -244,3 +246,4 @@ http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html
 ==Copyright==
 
 This document is placed in the public domain.
+
-- 
cgit v1.2.3

