script: implement bip146 (nullfail).
This commit is contained in:
parent
a508d5a51d
commit
b03a10d790
@ -772,6 +772,7 @@ exports.flags = {
|
||||
VERIFY_WITNESS: (1 << 11),
|
||||
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 12),
|
||||
VERIFY_MAST: (1 << 13),
|
||||
VERIFY_NULLFAIL: (1 << 14),
|
||||
VERIFY_SEQUENCE: (1 << 0),
|
||||
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 n, n1, n2, n3;
|
||||
var res, key, sig, type, subscript, hash;
|
||||
var i, j, m, ikey, isig;
|
||||
var i, j, m, ikey, ikey2, isig;
|
||||
var locktime;
|
||||
|
||||
if (flags == null)
|
||||
@ -835,6 +835,12 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
hash = tx.signatureHash(index, subscript, type, version);
|
||||
|
||||
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 (!res)
|
||||
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);
|
||||
|
||||
n = Script.num(stack.top(-i), flags).toNumber();
|
||||
ikey2 = n + 2;
|
||||
|
||||
if (!(n >= 0 && n <= constants.script.MAX_MULTISIG_PUBKEYS))
|
||||
throw new ScriptError('PUBKEY_COUNT', op, ip);
|
||||
@ -913,8 +920,15 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
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();
|
||||
}
|
||||
|
||||
if (stack.length < 1)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
||||
|
||||
@ -232,8 +232,8 @@
|
||||
["'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"],
|
||||
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' 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 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"],
|
||||
|
||||
@ -443,7 +443,7 @@
|
||||
|
||||
["NOP", "NOP1 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", "NOP5 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"],
|
||||
["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", "and multiple spaces should not change that."],
|
||||
@ -857,13 +857,13 @@
|
||||
["2 2 LSHIFT", "8 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"],
|
||||
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' 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 CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
||||
|
||||
["Ensure 100% coverage of discouraged NOPS"],
|
||||
["1", "NOP1", "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", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||
["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||
@ -1491,6 +1491,27 @@
|
||||
"OK",
|
||||
"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",
|
||||
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
|
||||
@ -2119,11 +2140,21 @@
|
||||
],
|
||||
|
||||
["CHECKSEQUENCEVERIFY tests"],
|
||||
["", "NOP3", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
|
||||
["-1", "NOP3", "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"],
|
||||
["0", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
|
||||
["4294967296", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
|
||||
["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
|
||||
["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
|
||||
["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
|
||||
["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
|
||||
["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
|
||||
"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"]
|
||||
]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user