From c27ea986059aee9bbb719a3d3af615bc5d799b8c Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Tue, 8 Jan 2019 14:29:14 +0000 Subject: [PATCH] Add OP_CHECKSIGFROMSTACK[VERIFY] --- src/script/interpreter.cpp | 36 +++++++++++++++++++++++++++++++++ src/script/script.cpp | 5 ++++- src/script/script.h | 4 +++- src/test/data/script_tests.json | 4 ---- src/test/script_tests.cpp | 2 +- 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 9c726c0d9b..d0e1bc8317 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1126,6 +1126,42 @@ bool EvalScript(std::vector >& stack, const CScript& } break; + case OP_CHECKSIGFROMSTACK: + case OP_CHECKSIGFROMSTACKVERIFY: + { + // (sig data pubkey -- bool) + if (stack.size() < 3) + return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); + + valtype& vchSig = stacktop(-3); + valtype& vchData = stacktop(-2); + valtype& vchPubKey = stacktop(-1); + + // Sigs from stack have no hash byte ever + if (!CheckSignatureEncoding(vchSig, (flags | SCRIPT_NO_SIGHASH_BYTE), serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) { + //serror is set + return false; + } + + valtype vchHash(32); + CSHA256().Write(vchData.data(), vchData.size()).Finalize(vchHash.data()); + uint256 hash(vchHash); + + CPubKey pubkey(vchPubKey); + bool fSuccess = pubkey.Verify(hash, vchSig); + + popstack(stack); + popstack(stack); + popstack(stack); + stack.push_back(fSuccess ? vchTrue : vchFalse); + if (opcode == OP_CHECKSIGFROMSTACKVERIFY) + popstack(stack); + + if (!fSuccess) + return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY); + } + break; + default: return set_error(serror, SCRIPT_ERR_BAD_OPCODE); } diff --git a/src/script/script.cpp b/src/script/script.cpp index 373f09bf9f..532860fe18 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -127,6 +127,8 @@ const char* GetOpName(opcodetype opcode) case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG"; case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY"; case OP_DETERMINISTICRANDOM : return "OP_DETERMINISTICRANDOM"; + case OP_CHECKSIGFROMSTACK : return "OP_CHECKSIGFROMSTACK"; + case OP_CHECKSIGFROMSTACKVERIFY: return "OP_CHECKSIGFROMSTACKVERIFY"; // expansion case OP_NOP1 : return "OP_NOP1"; @@ -157,7 +159,8 @@ unsigned int CScript::GetSigOpCount(bool fAccurate) const opcodetype opcode; if (!GetOp(pc, opcode)) break; - if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY) + if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY || + opcode == OP_CHECKSIGFROMSTACK || opcode == OP_CHECKSIGFROMSTACKVERIFY) n++; else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY) { diff --git a/src/script/script.h b/src/script/script.h index e27937a990..e811bab302 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -174,6 +174,8 @@ enum opcodetype OP_CHECKMULTISIG = 0xae, OP_CHECKMULTISIGVERIFY = 0xaf, OP_DETERMINISTICRANDOM = 0xc0, + OP_CHECKSIGFROMSTACK = 0xc1, + OP_CHECKSIGFROMSTACKVERIFY = 0xc2, // expansion OP_NOP1 = 0xb0, @@ -193,7 +195,7 @@ enum opcodetype }; // Maximum value that an opcode can be -static const unsigned int MAX_OPCODE = OP_DETERMINISTICRANDOM; +static const unsigned int MAX_OPCODE = OP_CHECKSIGFROMSTACKVERIFY; const char* GetOpName(opcodetype opcode); diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 59079dceb7..58ef1f732f 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -258,8 +258,6 @@ ["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"], -["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], -["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], @@ -893,8 +891,6 @@ ["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"], -["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index d5796ea8a3..0c23b7a353 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1474,7 +1474,7 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps) BOOST_CHECK(script.HasValidOps()); script = ScriptFromHex("ff88ac"); // Script with OP_INVALIDOPCODE explicit BOOST_CHECK(!script.HasValidOps()); - script = ScriptFromHex("88acc1"); // Script with undefined opcode: one higher then MAX_OPCODE + script = ScriptFromHex("88acc3"); // Script with undefined opcode: one higher then MAX_OPCODE BOOST_CHECK(!script.HasValidOps()); }