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";
// 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";
// 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;
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
//
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
{
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)
};
OP_VERIFY = 0x69,
OP_RETURN = 0x6a,
OP_CHECKLOCKTIMEVERIFY = 0xb1,
+ OP_CHECKSEQUENCEVERIFY = 0xb2,
// stack ops
OP_TOALTSTACK = 0x6b,
// expansion
OP_NOP1 = 0xb0,
- OP_NOP3 = 0xb2,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,