OP_CHECKSEQUENCEVERIFY
authorCryptoManiac <balthazar@yandex.ru>
Sun, 21 Feb 2016 22:41:13 +0000 (01:41 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sun, 21 Feb 2016 22:41:13 +0000 (01:41 +0300)
src/main.cpp
src/script.cpp
src/script.h

index 95927c8..404e135 100644 (file)
@@ -1762,6 +1762,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
 
             if (tx.nTime >= CHECKLOCKTIMEVERIFY_SWITCH_TIME) {
                 nFlags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
+                nFlags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
             }
 
             std::vector<CScriptCheck> vChecks;
index 1b504e4..eb1dc9a 100644 (file)
@@ -149,6 +149,7 @@ const char* GetOpName(opcodetype opcode)
     case OP_VERIFY                 : return "OP_VERIFY";
     case OP_RETURN                 : return "OP_RETURN";
     case OP_CHECKLOCKTIMEVERIFY    : return "OP_CHECKLOCKTIMEVERIFY";
+    case OP_CHECKSEQUENCEVERIFY    : return "OP_CHECKSEQUENCEVERIFY";
 
     // stack ops
     case OP_TOALTSTACK             : return "OP_TOALTSTACK";
@@ -231,7 +232,6 @@ const char* GetOpName(opcodetype opcode)
 
     // expanson
     case OP_NOP1                   : return "OP_NOP1";
-    case OP_NOP3                   : return "OP_NOP3";
     case OP_NOP4                   : return "OP_NOP4";
     case OP_NOP5                   : return "OP_NOP5";
     case OP_NOP6                   : return "OP_NOP6";
@@ -422,7 +422,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
                 // Control
                 //
                 case OP_NOP:
-                case OP_NOP1: case OP_NOP3: case OP_NOP4: case OP_NOP5:
+                case OP_NOP1: case OP_NOP4: case OP_NOP5:
                 case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
                 break;
 
@@ -519,6 +519,43 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
                     break;
                 }
 
+                case OP_CHECKSEQUENCEVERIFY:
+                {
+                    if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY))
+                        // treat as a NOP if not enabled
+                        break;
+                    if (stack.size() < 1)
+                        return false;
+                    const CBigNum nInvSequence = CastToBigNum(stacktop(-1));
+
+                    // 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 false; // negative nSequence is senseless
+
+                    // Relative lock times are supported by comparing the passed
+                    // in lock time to the sequence number of the input. All other
+                    // logic is the same, all that differs is what we are comparing
+                    // the lock time to.
+                    int64_t txToLockTime = (int64_t)~txTo.vin[nIn].nSequence;
+                        if (txToLockTime >= SEQUENCE_THRESHOLD)
+                            return false;
+
+                    if (!(
+                        (txToLockTime <  LOCKTIME_THRESHOLD && nInvSequence <  LOCKTIME_THRESHOLD) || 
+                        (txToLockTime >= 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 > txToLockTime)
+                        return false;
+
+                    break;
+                }
+
                 //
                 // Stack ops
                 //
index 7d47989..98d0965 100644 (file)
@@ -19,6 +19,10 @@ class CTransaction;
 
 static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
 
+// 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);
+
 /** IsMine() return codes */
 enum isminetype
 {
@@ -48,7 +52,8 @@ enum
     SCRIPT_VERIFY_LOW_S     = (1U << 2), // enforce low S values in signatures (depends on STRICTENC)
     SCRIPT_VERIFY_NOCACHE   = (1U << 3), // do not store results in signature cache (but do query it)
     SCRIPT_VERIFY_NULLDUMMY = (1U << 4),  // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
-    SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9)
+    SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
+    SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 9)
 
 };
 
@@ -128,6 +133,7 @@ enum opcodetype
     OP_VERIFY = 0x69,
     OP_RETURN = 0x6a,
     OP_CHECKLOCKTIMEVERIFY = 0xb1,
+    OP_CHECKSEQUENCEVERIFY = 0xb2,
 
     // stack ops
     OP_TOALTSTACK = 0x6b,
@@ -213,7 +219,6 @@ enum opcodetype
 
     // expansion
     OP_NOP1 = 0xb0,
-    OP_NOP3 = 0xb2,
     OP_NOP4 = 0xb3,
     OP_NOP5 = 0xb4,
     OP_NOP6 = 0xb5,