checksequenceverify.
This commit is contained in:
parent
aa101a16e8
commit
3dc0f4d412
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user