script: implement bip146 (nullfail).
This commit is contained in:
parent
a508d5a51d
commit
b03a10d790
@ -772,6 +772,7 @@ exports.flags = {
|
|||||||
VERIFY_WITNESS: (1 << 11),
|
VERIFY_WITNESS: (1 << 11),
|
||||||
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 12),
|
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 12),
|
||||||
VERIFY_MAST: (1 << 13),
|
VERIFY_MAST: (1 << 13),
|
||||||
|
VERIFY_NULLFAIL: (1 << 14),
|
||||||
VERIFY_SEQUENCE: (1 << 0),
|
VERIFY_SEQUENCE: (1 << 0),
|
||||||
MEDIAN_TIME_PAST: (1 << 1)
|
MEDIAN_TIME_PAST: (1 << 1)
|
||||||
};
|
};
|
||||||
|
|||||||
@ -300,7 +300,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
|||||||
var op, code, data, val, v1, v2, v3;
|
var op, code, data, val, v1, v2, v3;
|
||||||
var n, n1, n2, n3;
|
var n, n1, n2, n3;
|
||||||
var res, key, sig, type, subscript, hash;
|
var res, key, sig, type, subscript, hash;
|
||||||
var i, j, m, ikey, isig;
|
var i, j, m, ikey, ikey2, isig;
|
||||||
var locktime;
|
var locktime;
|
||||||
|
|
||||||
if (flags == null)
|
if (flags == null)
|
||||||
@ -835,6 +835,12 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
|||||||
hash = tx.signatureHash(index, subscript, type, version);
|
hash = tx.signatureHash(index, subscript, type, version);
|
||||||
|
|
||||||
res = Script.checksig(hash, sig, key, flags);
|
res = Script.checksig(hash, sig, key, flags);
|
||||||
|
|
||||||
|
if (!res && (flags & constants.flags.VERIFY_NULLFAIL)) {
|
||||||
|
if (sig.length !== 0)
|
||||||
|
throw new ScriptError('NULLFAIL', op, ip);
|
||||||
|
}
|
||||||
|
|
||||||
if (op === opcodes.OP_CHECKSIGVERIFY) {
|
if (op === opcodes.OP_CHECKSIGVERIFY) {
|
||||||
if (!res)
|
if (!res)
|
||||||
throw new ScriptError('CHECKSIGVERIFY', op, ip);
|
throw new ScriptError('CHECKSIGVERIFY', op, ip);
|
||||||
@ -854,6 +860,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
|||||||
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
||||||
|
|
||||||
n = Script.num(stack.top(-i), flags).toNumber();
|
n = Script.num(stack.top(-i), flags).toNumber();
|
||||||
|
ikey2 = n + 2;
|
||||||
|
|
||||||
if (!(n >= 0 && n <= constants.script.MAX_MULTISIG_PUBKEYS))
|
if (!(n >= 0 && n <= constants.script.MAX_MULTISIG_PUBKEYS))
|
||||||
throw new ScriptError('PUBKEY_COUNT', op, ip);
|
throw new ScriptError('PUBKEY_COUNT', op, ip);
|
||||||
@ -913,8 +920,15 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
|||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i-- > 1)
|
while (i-- > 1) {
|
||||||
|
if (!res && (flags & constants.flags.VERIFY_NULLFAIL)) {
|
||||||
|
if (ikey2 === 0 && stack.top(-1).length !== 0)
|
||||||
|
throw new ScriptError('NULLFAIL', op, ip);
|
||||||
|
}
|
||||||
|
if (ikey2 > 0)
|
||||||
|
ikey2--;
|
||||||
stack.pop();
|
stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
if (stack.length < 1)
|
if (stack.length < 1)
|
||||||
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
||||||
|
|||||||
@ -232,8 +232,8 @@
|
|||||||
["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"],
|
["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"],
|
||||||
|
|
||||||
|
|
||||||
["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
|
["1","NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
|
||||||
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
|
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
|
||||||
|
|
||||||
["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"],
|
["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"],
|
||||||
|
|
||||||
@ -443,7 +443,7 @@
|
|||||||
|
|
||||||
["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"],
|
["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"],
|
||||||
["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"],
|
["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"],
|
||||||
["NOP", "NOP3 1", "P2SH,STRICTENC", "OK"],
|
["NOP", "CHECKSEQUENCEVERIFY 1", "P2SH,STRICTENC", "OK"],
|
||||||
["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"],
|
["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"],
|
||||||
["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"],
|
["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"],
|
||||||
["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"],
|
["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"],
|
||||||
@ -701,7 +701,7 @@
|
|||||||
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"],
|
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"],
|
||||||
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"],
|
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"],
|
||||||
|
|
||||||
["2147483648", "NOP3", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"],
|
["2147483648", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"],
|
||||||
|
|
||||||
["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"],
|
["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"],
|
||||||
[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."],
|
[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."],
|
||||||
@ -857,13 +857,13 @@
|
|||||||
["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
|
["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
|
||||||
["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
|
["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
|
||||||
|
|
||||||
["1", "NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
||||||
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
||||||
|
|
||||||
["Ensure 100% coverage of discouraged NOPS"],
|
["Ensure 100% coverage of discouraged NOPS"],
|
||||||
["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||||
["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||||
["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
["1", "CHECKSEQUENCEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||||
["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||||
["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||||
["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||||
@ -1491,6 +1491,27 @@
|
|||||||
"OK",
|
"OK",
|
||||||
"BIP66 example 4, with DERSIG"
|
"BIP66 example 4, with DERSIG"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"0x09 0x300602010102010101",
|
||||||
|
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
|
||||||
|
"DERSIG",
|
||||||
|
"OK",
|
||||||
|
"BIP66 example 4, with DERSIG, non-null DER-compliant signature"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"0",
|
||||||
|
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
|
||||||
|
"DERSIG,NULLFAIL",
|
||||||
|
"OK",
|
||||||
|
"BIP66 example 4, with DERSIG and NULLFAIL"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"0x09 0x300602010102010101",
|
||||||
|
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
|
||||||
|
"DERSIG,NULLFAIL",
|
||||||
|
"NULLFAIL",
|
||||||
|
"BIP66 example 4, with DERSIG and NULLFAIL, non-null DER-compliant signature"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"1",
|
"1",
|
||||||
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
|
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
|
||||||
@ -2119,11 +2140,21 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
["CHECKSEQUENCEVERIFY tests"],
|
["CHECKSEQUENCEVERIFY tests"],
|
||||||
["", "NOP3", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
|
["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
|
||||||
["-1", "NOP3", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
|
["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
|
||||||
["0x0100", "NOP3", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
|
["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
|
||||||
["0", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
|
["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
|
||||||
["4294967296", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
|
["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
|
||||||
"CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"],
|
"CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"],
|
||||||
|
|
||||||
|
["NULLFAIL should cover all signatures and signatures only"],
|
||||||
|
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"],
|
||||||
|
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
|
||||||
|
["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
|
||||||
|
["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL,NULLDUMMY", "SIG_NULLDUMMY", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
|
||||||
|
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||||
|
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||||
|
["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||||
|
["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||||
["The End"]
|
["The End"]
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user