diff --git a/src/core_read.cpp b/src/core_read.cpp --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -26,8 +26,8 @@ static std::map mapOpNames; if (mapOpNames.empty()) { - for (int op = 0; op <= OP_NOP10; op++) { - // Allow OP_RESERVED to get into mapOpNames + for (int op = 0; op <= MAX_DEFINED_OP_VALUE; op++) { + // ignore all "PUSHDATA" ops, but dont ignore OP_RESERVED if (op < OP_NOP && op != OP_RESERVED) { continue; } diff --git a/src/script/interpreter.h b/src/script/interpreter.h --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -107,6 +107,10 @@ // Do we accept signature using SIGHASH_FORKID // SCRIPT_ENABLE_SIGHASH_FORKID = (1U << 16), + + // Enable new opcodes activated from 15 May 2018 HF + // + SCRIPT_ENABLE_OPCODES_MONOLITH = (1U << 17), }; bool CheckSignatureEncoding(const std::vector &vchSig, uint32_t flags, diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -312,6 +312,8 @@ } int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; + bool fEnabledOpCodesMonolith = + (flags & SCRIPT_ENABLE_OPCODES_MONOLITH) != 0; try { while (pc < pend) { @@ -332,7 +334,7 @@ return set_error(serror, SCRIPT_ERR_OP_COUNT); } - if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || + if (opcode == OP_CAT || opcode == OP_SPLIT || opcode == OP_LEFT || opcode == OP_RIGHT || opcode == OP_INVERT || opcode == OP_AND || opcode == OP_OR || opcode == OP_XOR || opcode == OP_2MUL || opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV || diff --git a/src/script/script.h b/src/script/script.h --- a/src/script/script.h +++ b/src/script/script.h @@ -102,7 +102,7 @@ // splice ops OP_CAT = 0x7e, - OP_SUBSTR = 0x7f, + OP_SPLIT = 0x7f, OP_LEFT = 0x80, OP_RIGHT = 0x81, OP_SIZE = 0x82, @@ -134,6 +134,8 @@ OP_MOD = 0x97, OP_LSHIFT = 0x98, OP_RSHIFT = 0x99, + OP_BIN2NUM = 0xba, + OP_NUM2BIN = 0xbb, OP_BOOLAND = 0x9a, OP_BOOLOR = 0x9b, @@ -184,6 +186,9 @@ OP_INVALIDOPCODE = 0xff, }; +// the op_code with the maximum value out of all defined opcodes +#define MAX_DEFINED_OP_VALUE OP_NUM2BIN + const char *GetOpName(opcodetype opcode); class scriptnum_error : public std::runtime_error { diff --git a/src/script/script.cpp b/src/script/script.cpp --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -121,8 +121,8 @@ // splice ops case OP_CAT: return "OP_CAT"; - case OP_SUBSTR: - return "OP_SUBSTR"; + case OP_SPLIT: + return "OP_SPLIT"; case OP_LEFT: return "OP_LEFT"; case OP_RIGHT: @@ -179,6 +179,10 @@ return "OP_LSHIFT"; case OP_RSHIFT: return "OP_RSHIFT"; + case OP_BIN2NUM: + return "OP_BIN2NUM"; + case OP_NUM2BIN: + return "OP_NUM2BIN"; case OP_BOOLAND: return "OP_BOOLAND"; case OP_BOOLOR: diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -240,9 +240,9 @@ ["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discouraged NOPs are allowed if not executed"], -["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above NOP10 invalid if executed"], -["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], -["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF BIN2NUM ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "BIN2NUM invalid unless ENABLE_OPCODES_MONOLITH"], +["0", "IF NUM2BIN ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "NUM2BIN invalid unless ENABLE_OPCODES_MONOLITH"], +["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above MAX_VALID_OP_VALUE invalid if executed"], ["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], @@ -819,8 +819,8 @@ ["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], ["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], -["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], -["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], +["'abc' 1 1", "SPLIT", "P2SH,STRICTENC", "DISABLED_OPCODE", "SPLIT disabled"], +["'abc' 1 1 0", "IF SPLIT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SPLIT disabled"], ["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "LEFT disabled"], ["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "RIGHT disabled"], @@ -878,9 +878,9 @@ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], ["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], -["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above NOP10 invalid if executed"], -["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF BIN2NUM ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "BIN2NUM invalid unless ENABLE_OPCODES_MONOLITH"], +["1", "IF NUM2BIN ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "NUM2BIN invalid unless ENABLE_OPCODES_MONOLITH"], +["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above MAX_VALID_OP_VALUE invalid if executed"], ["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], @@ -1001,7 +1001,9 @@ ["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], ["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], ["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], -["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == OP_NOP10 + 1"], +["1","BIN2NUM", "P2SH,STRICTENC", "BAD_OPCODE", "BIN2NUM invalid unless ENABLE_OPCODES_MONOLITH"], +["1","NUM2BIN", "P2SH,STRICTENC", "BAD_OPCODE", "BIN2NUM invalid unless ENABLE_OPCODES_MONOLITH"], +["1","0xbc", "P2SH,STRICTENC", "BAD_OPCODE", "0xbc == MAX_VALID_OP_VALUE + 1"], ["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], diff --git a/src/test/scriptflags.cpp b/src/test/scriptflags.cpp --- a/src/test/scriptflags.cpp +++ b/src/test/scriptflags.cpp @@ -32,6 +32,7 @@ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM}, {"COMPRESSED_PUBKEYTYPE", SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE}, {"SIGHASH_FORKID", SCRIPT_ENABLE_SIGHASH_FORKID}, + {"ENABLE_OPCODES_MONOLITH", SCRIPT_ENABLE_OPCODES_MONOLITH}, }; uint32_t ParseScriptFlags(std::string strFlags) { diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -48,6 +48,7 @@ class CScriptOp(int): + """A single script opcode""" __slots__ = [] @@ -178,7 +179,7 @@ # splice ops OP_CAT = CScriptOp(0x7e) -OP_SUBSTR = CScriptOp(0x7f) +OP_SPLIT = CScriptOp(0x7f) OP_LEFT = CScriptOp(0x80) OP_RIGHT = CScriptOp(0x81) OP_SIZE = CScriptOp(0x82) @@ -210,6 +211,8 @@ OP_MOD = CScriptOp(0x97) OP_LSHIFT = CScriptOp(0x98) OP_RSHIFT = CScriptOp(0x99) +OP_BIN2NUM = CScriptOp(0xba) +OP_NUM2BIN = CScriptOp(0xbb) OP_BOOLAND = CScriptOp(0x9a) OP_BOOLOR = CScriptOp(0x9b) @@ -309,7 +312,7 @@ OP_TUCK, OP_CAT, - OP_SUBSTR, + OP_SPLIT, OP_LEFT, OP_RIGHT, OP_SIZE, @@ -339,6 +342,8 @@ OP_MOD, OP_LSHIFT, OP_RSHIFT, + OP_BIN2NUM, + OP_NUM2BIN, OP_BOOLAND, OP_BOOLOR, @@ -435,7 +440,7 @@ OP_SWAP: 'OP_SWAP', OP_TUCK: 'OP_TUCK', OP_CAT: 'OP_CAT', - OP_SUBSTR: 'OP_SUBSTR', + OP_SPLIT: 'OP_SPLIT', OP_LEFT: 'OP_LEFT', OP_RIGHT: 'OP_RIGHT', OP_SIZE: 'OP_SIZE', @@ -462,6 +467,8 @@ OP_MOD: 'OP_MOD', OP_LSHIFT: 'OP_LSHIFT', OP_RSHIFT: 'OP_RSHIFT', + OP_BIN2NUM: 'OP_BIN2NUM', + OP_NUM2BIN: 'OP_NUM2BIN', OP_BOOLAND: 'OP_BOOLAND', OP_BOOLOR: 'OP_BOOLOR', OP_NUMEQUAL: 'OP_NUMEQUAL', @@ -554,7 +561,7 @@ 'OP_SWAP': OP_SWAP, 'OP_TUCK': OP_TUCK, 'OP_CAT': OP_CAT, - 'OP_SUBSTR': OP_SUBSTR, + 'OP_SPLIT': OP_SPLIT, 'OP_LEFT': OP_LEFT, 'OP_RIGHT': OP_RIGHT, 'OP_SIZE': OP_SIZE, @@ -581,6 +588,8 @@ 'OP_MOD': OP_MOD, 'OP_LSHIFT': OP_LSHIFT, 'OP_RSHIFT': OP_RSHIFT, + 'OP_BIN2NUM': OP_BIN2NUM, + 'OP_NUM2BIN': OP_NUM2BIN, 'OP_BOOLAND': OP_BOOLAND, 'OP_BOOLOR': OP_BOOLOR, 'OP_NUMEQUAL': OP_NUMEQUAL, @@ -621,11 +630,13 @@ class CScriptInvalidError(Exception): + """Base class for CScript exceptions""" pass class CScriptTruncatedPushDataError(CScriptInvalidError): + """Invalid pushdata due to truncation""" def __init__(self, msg, data): @@ -636,6 +647,7 @@ class CScriptNum(): + def __init__(self, d=0): self.value = d @@ -657,6 +669,7 @@ class CScript(bytes): + """Serialized script A bytes subclass, so you can use this directly whenever bytes are accepted.