checksequenceverify.

This commit is contained in:
Christopher Jeffrey 2016-03-07 19:48:48 -08:00
parent aa101a16e8
commit 3dc0f4d412
2 changed files with 111 additions and 4 deletions

View File

@ -164,7 +164,8 @@ exports.opcodes = {
nop1: 0xb0,
// nop2: 0xb1,
checklocktimeverify: 0xb1,
nop3: 0xb2,
// nop3: 0xb2,
checksequenceverify: 0xb2,
nop4: 0xb3,
nop5: 0xb4,
nop6: 0xb5,
@ -268,6 +269,10 @@ exports.hd = {
exports.locktimeThreshold = 500000000; // Tue Nov 5 00:53:20 1985 UTC
exports.sequenceLocktimeDisableFlag = 0x80000000; // (1 << 31)
exports.sequenceLocktimeTypeFlag = 1 << 22;
exports.sequenceLocktimeMask = 0x0000ffff;
exports.oneHash = new Buffer(
'0000000000000000000000000000000000000000000000000000000000000001',
'hex'
@ -298,7 +303,9 @@ exports.flags = {
VERIFY_CLEANSTACK: (1 << 8),
VERIFY_CHECKLOCKTIMEVERIFY: (1 << 9),
VERIFY_WITNESS: (1 << 10),
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 11)
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 11),
// NOTE: Should be (1 << 10) - but that conflicts with segwit
VERIFY_CHECKSEQUENCEVERIFY: (1 << 12)
};
// Block validation
@ -316,4 +323,5 @@ exports.flags.STANDARD_VERIFY_FLAGS =
| exports.flags.VERIFY_CHECKLOCKTIMEVERIFY
| exports.flags.VERIFY_LOW_S;
// | exports.flags.VERIFY_WITNESS
// | exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
// | exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM
// | exports.flags.VERIFY_CHECKSEQUENCEVERIFY;

View File

@ -613,7 +613,6 @@ script.execute = function execute(data, stack, tx, index, flags, version, recurs
switch (o) {
case 'nop':
case 'nop3':
case 'nop4':
case 'nop5':
case 'nop6':
@ -1172,6 +1171,46 @@ script.execute = function execute(data, stack, tx, index, flags, version, recurs
break;
}
case 'checksequenceverify': {
// OP_CHECKSEQUENCEVERIFY = OP_NOP3
if (!(flags & constants.flags.VERIFY_CHECKSEQUENCEVERIFY)) {
if (flags & constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
return false;
break;
}
if (!tx || stack.length === 0)
return false;
locktime = stack[stack.length - 1];
if (!Buffer.isBuffer(locktime))
return false;
if (locktime.length > 5) {
utils.debug('Warning: sequence is over 40 bits.');
return false;
}
locktime = script.num(locktime);
// if (locktime < 0)
// return false;
// if ((locktime & constants.sequenceLocktimeDisableFlag) !== 0)
// break;
if (locktime.cmpn(0) < 0)
return false;
if (locktime.uandn(constants.sequenceLocktimeDisableFlag).cmpn(0) !== 0)
break;
if (!script.checkSequenceBN(locktime, tx, i))
return false;
break;
}
case 'nop1': {
// OP_EVAL = OP_NOP1
if (!script.allowEval) {
@ -1221,6 +1260,66 @@ script.execute = function execute(data, stack, tx, index, flags, version, recurs
return true;
};
script.checkSequence = function checkSequence(sequence, tx, i) {
var txSequence = tx.inputs[i].sequence;
var locktimeMask, txSequenceMasked, sequenceMasked;
if (tx.version < 2)
return false;
// if (txSequence & constants.sequenceLocktimeDisableFlag)
return false;
locktimeMask = constants.sequenceLocktimeTypeFlag
| constants.sequenceLocktimeMask;
txSequenceMasked = txSequence & locktimeMask;
sequenceMasked = sequence & locktimeMask;
if (!(
(txSequenceMasked < constants.sequenceLocktimeTypeFlag
&& sequenceMasked < constants.sequenceLocktimeTypeFlag
|| (txSequenceMasked >= constants.sequenceLocktimeTypeFlag
&& sequenceMasked >= constants.sequenceLocktimeTypeFlag
)) {
return false;
}
if (sequenceMasked > txSequenceMasked)
return false;
return true;
};
script.checkSequenceBN = function checkSequence(sequence, tx, i) {
var txSequence = new bn(tx.inputs[i].sequence);
var locktimeMask, txSequenceMasked, sequenceMasked;
if (tx.version < 2)
return false;
if (txSequence.uandn(constants.sequenceLocktimeDisableFlag).cmpn(0) !== 0)
return false;
locktimeMask = new bn(constants.sequenceLocktimeTypeFlag)
.uorn(constants.sequenceLocktimeMask);
txSequenceMasked = txSequence.uand(locktimeMask);
sequenceMasked = sequence.uand(locktimeMask);
if (!(
(txSequenceMasked.cmpn(constants.sequenceLocktimeTypeFlag) < 0
&& sequenceMasked.cmpn(constants.sequenceLocktimeTypeFlag) < 0
|| (txSequenceMasked.cmpn(constants.sequenceLocktimeTypeFlag) >= 0
&& sequenceMasked.cmpn(constants.sequenceLocktimeTypeFlag) >= 0
)) {
return false;
}
if (sequenceMasked.cmpn(txSequenceMasked) > 0)
return false;
return true;
};
script.bool = function bool(value) {
var i;