checksequenceverify.
This commit is contained in:
parent
aa101a16e8
commit
3dc0f4d412
@ -164,7 +164,8 @@ exports.opcodes = {
|
|||||||
nop1: 0xb0,
|
nop1: 0xb0,
|
||||||
// nop2: 0xb1,
|
// nop2: 0xb1,
|
||||||
checklocktimeverify: 0xb1,
|
checklocktimeverify: 0xb1,
|
||||||
nop3: 0xb2,
|
// nop3: 0xb2,
|
||||||
|
checksequenceverify: 0xb2,
|
||||||
nop4: 0xb3,
|
nop4: 0xb3,
|
||||||
nop5: 0xb4,
|
nop5: 0xb4,
|
||||||
nop6: 0xb5,
|
nop6: 0xb5,
|
||||||
@ -268,6 +269,10 @@ exports.hd = {
|
|||||||
|
|
||||||
exports.locktimeThreshold = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
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(
|
exports.oneHash = new Buffer(
|
||||||
'0000000000000000000000000000000000000000000000000000000000000001',
|
'0000000000000000000000000000000000000000000000000000000000000001',
|
||||||
'hex'
|
'hex'
|
||||||
@ -298,7 +303,9 @@ exports.flags = {
|
|||||||
VERIFY_CLEANSTACK: (1 << 8),
|
VERIFY_CLEANSTACK: (1 << 8),
|
||||||
VERIFY_CHECKLOCKTIMEVERIFY: (1 << 9),
|
VERIFY_CHECKLOCKTIMEVERIFY: (1 << 9),
|
||||||
VERIFY_WITNESS: (1 << 10),
|
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
|
// Block validation
|
||||||
@ -316,4 +323,5 @@ exports.flags.STANDARD_VERIFY_FLAGS =
|
|||||||
| exports.flags.VERIFY_CHECKLOCKTIMEVERIFY
|
| exports.flags.VERIFY_CHECKLOCKTIMEVERIFY
|
||||||
| exports.flags.VERIFY_LOW_S;
|
| exports.flags.VERIFY_LOW_S;
|
||||||
// | exports.flags.VERIFY_WITNESS
|
// | 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) {
|
switch (o) {
|
||||||
case 'nop':
|
case 'nop':
|
||||||
case 'nop3':
|
|
||||||
case 'nop4':
|
case 'nop4':
|
||||||
case 'nop5':
|
case 'nop5':
|
||||||
case 'nop6':
|
case 'nop6':
|
||||||
@ -1172,6 +1171,46 @@ script.execute = function execute(data, stack, tx, index, flags, version, recurs
|
|||||||
|
|
||||||
break;
|
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': {
|
case 'nop1': {
|
||||||
// OP_EVAL = OP_NOP1
|
// OP_EVAL = OP_NOP1
|
||||||
if (!script.allowEval) {
|
if (!script.allowEval) {
|
||||||
@ -1221,6 +1260,66 @@ script.execute = function execute(data, stack, tx, index, flags, version, recurs
|
|||||||
return true;
|
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) {
|
script.bool = function bool(value) {
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user