From 4048f45316faa85f8327d1febe080c83b72fc2e7 Mon Sep 17 00:00:00 2001
From: BtcDrak <btcdrak@gmail.com>
Date: Mon, 23 Nov 2015 20:21:32 +0000
Subject: BIP112: Update document to match implementation

---
 bip-0112.mediawiki | 111 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 63 insertions(+), 48 deletions(-)

(limited to 'bip-0112.mediawiki')

diff --git a/bip-0112.mediawiki b/bip-0112.mediawiki
index e1a186f..8821bf5 100644
--- a/bip-0112.mediawiki
+++ b/bip-0112.mediawiki
@@ -21,23 +21,18 @@ being spent.
 
 CHECKSEQUENCEVERIFY redefines the existing NOP3 opcode.
 When executed, the script interpreter continues as if a NOP was executed
-so long as one of the following conditions is met:
+so long as:
 
-  * the transaction's nVersion field is 0 or 1;
-  * the top item on the stack is a value greater than or equal to (1 << 31); or
-  * the top item on the stack and the transaction input's sequence number are both relative lock-times of the same units, and the relative lock-time represented by the sequence number is greater than or equal to the relative lock-time represented by the top item on the stack.
+* the top item on the stack is greater than or equal to 0; and
+* the top item on the stack does not have disable flag (1 << 31) set; and
+* the transaction version is 2 or above; and
+* the transaction input's sequence number does not have the disable flag (1 << 31) set; and
+* the top item on the stack and the transaction input's sequence number are both relative lock-times of the same type, and sequence number is greater than or equal to the top item on the stack.
 
 Otherwise, script execution terminates with an error.
 
-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.
+BIP 68 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==
@@ -100,7 +95,7 @@ Some more specific applications of this idea:
 
 ====Hash Time-Locked Contracts====
 
-Hash Time-Locked Contracts (HTLCs) provide a general mechanism for offchain contract negotiation. An execution pathway can be made to require knowledge of a secret (a hash preimage) that can be presented within an invalidation time window. By sharing the secret it is possible to guarantee to the counterparty that the transaction will never be broadcast since this would allow the counterparty to claim the output immediately while one would have to wait for the time window to pass. If the secret has not been shared, the counterparty will be unable to use the instant pathway and the delayed pathway must be used instead.
+Hash Time-Locked Contracts (HTLCs) provide a general mechanism for off-chain contract negotiation. An execution pathway can be made to require knowledge of a secret (a hash preimage) that can be presented within an invalidation time window. By sharing the secret it is possible to guarantee to the counterparty that the transaction will never be broadcast since this would allow the counterparty to claim the output immediately while one would have to wait for the time window to pass. If the secret has not been shared, the counterparty will be unable to use the instant pathway and the delayed pathway must be used instead.
 
 ====Bidirectional Payment Channels====
 
@@ -166,7 +161,7 @@ This form of transaction would mean that if the anchor is unspent on
 2015/12/16, Alice can use this commitment even if it has been revoked,
 simply by spending it immediately, giving no time for Bob to claim it.
 
-Ths means that the channel has a deadline that cannot be pushed
+This means that the channel has a deadline that cannot be pushed
 back without hitting the blockchain; and also that funds may not be
 available until the deadline is hit. CHECKSEQUENCEVERIFY allows you
 to avoid making such a tradeoff.
@@ -234,15 +229,19 @@ Refer to the reference implementation, reproduced below, for the precise
 semantics and detailed rationale for those semantics.
 
     
-    /* 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);
+    /* If this flag set, CTxIn::nSequence is NOT interpreted as a
+     * relative lock-time. */
+    static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (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);
+    /* If CTxIn::nSequence encodes a relative lock-time and this flag
+     * is set, the relative lock-time has units of 512 seconds,
+     * otherwise it specifies blocks with a granularity of 1. */
+    static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
     
+    /* If CTxIn::nSequence encodes a relative lock-time, this mask is
+     * applied to extract that lock-time from the sequence field. */
+    static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
+   
     case OP_NOP3:
     {
         if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
@@ -252,10 +251,10 @@ semantics and detailed rationale for those semantics.
             }
             break;
         }
-        
+    
         if (stack.size() < 1)
             return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
-        
+     
         // 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
@@ -266,23 +265,24 @@ semantics and detailed rationale for those semantics.
         // to 5-byte bignums, which are good until 2**39-1, well
         // beyond the 2**32-1 limit of the nSequence 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 (nSequence < 0)
             return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
-        
+    
         // 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)
+        // operand has the disabled lock-time flag set,
+        // CHECKSEQUENCEVERIFY behaves as a NOP.
+        if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
             break;
-        
-        // Actually compare the specified sequence number with the input.
+    
+        // Actually compare the specified inverse sequence number
+        // with the input.
         if (!checker.CheckSequence(nSequence))
             return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
-        
+    
         break;
     }
     
@@ -291,38 +291,52 @@ semantics and detailed rationale for those semantics.
         // 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 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 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)
+    
+        // Sequence numbers with their most significant bit set are not
+        // consensus constrained. Testing that the transaction's sequence
+        // number do not have this bit set prevents using this property
+        // to get around a CHECKSEQUENCEVERIFY check.
+        if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
             return false;
+    
+        // Mask off any bits that do not have consensus-enforced meaning
+        // before doing the integer comparisons of ::VerifySequence.
+        const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG
+                                     | CTxIn::SEQUENCE_LOCKTIME_MASK;
         
-        // There are two kinds of nSequence: lock-by-blockheight
+        if (!::VerifySequence(txToSequence & nLockTimeMask,
+                              CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG,
+                              nSequence & nLockTimeMask))
+            return false;
+    
+        return true;
+    }
+    
+    static bool VerifySequence(int64_t txToSequence, int64_t nThreshold, const CScriptNum& nSequence)
+    {
+        // There are two kinds of nLockTime: lock-by-blockheight
         // and lock-by-blocktime, distinguished by whether
-        // nSequence < SEQUENCE_UNITS_THRESHOLD.
+        // nSequence < nThreshold (CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG).
         //
         // We want to compare apples to apples, so fail the script
         // unless the type of nSequence being tested is the same as
         // the nSequence in the transaction.
         if (!(
-            (txToSequence <  SEQUENCE_UNITS_THRESHOLD && nSequence <  SEQUENCE_UNITS_THRESHOLD) ||
-            (txToSequence >= SEQUENCE_UNITS_THRESHOLD && nSequence >= SEQUENCE_UNITS_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 (txTo->vin[nIn].nSequence > txToSequence)
+        if (nSequence > txToSequence)
             return false;
-        
+    
         return true;
     }
 
@@ -367,7 +381,7 @@ done by Peter Todd for the closely related BIP 65.
 
 BtcDrak authored this BIP document.
 
-Thanks to Eric Lombrozo and Anthony Towns for contributing example usecases.
+Thanks to Eric Lombrozo and Anthony Towns for contributing example use cases.
 
 
 ==References==
@@ -397,3 +411,4 @@ Thanks to Eric Lombrozo and Anthony Towns for contributing example usecases.
 
 This document is placed in the public domain.
 
+
-- 
cgit v1.2.3

