@@ -343,6 +343,53 @@ static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPu
343343 return true ;
344344}
345345
346+ static bool EvalChecksigFromStack (const valtype& sig, const valtype& msg, const valtype& pubkey_in, ScriptExecutionData& execdata, unsigned int flags, SigVersion sigversion, ScriptError* serror, bool & success)
347+ {
348+ /*
349+ * The following validation sequence is consensus critical. Please note how --
350+ * upgradable public key versions precede other rules;
351+ * the script execution fails when using empty signature with invalid public key;
352+ * the script execution fails when using non-empty invalid signature.
353+ */
354+ success = !sig.empty ();
355+ if (success && sigversion == SigVersion::TAPSCRIPT) {
356+ // Implement the sigops/witnesssize ratio test.
357+ // Passing with an upgradable public key version is also counted.
358+ assert (execdata.m_validation_weight_left_init );
359+ execdata.m_validation_weight_left -= VALIDATION_WEIGHT_PER_SIGOP_PASSED;
360+ if (execdata.m_validation_weight_left < 0 ) {
361+ return set_error (serror, SCRIPT_ERR_TAPSCRIPT_VALIDATION_WEIGHT);
362+ }
363+ }
364+ if (pubkey_in.size () == 0 ) {
365+ return set_error (serror, SCRIPT_ERR_PUBKEYTYPE);
366+ } else if (pubkey_in.size () == 32 ) {
367+ if (!success) {
368+ return true ;
369+ }
370+ if (sig.size () != 64 ) {
371+ return set_error (serror, SCRIPT_ERR_SCHNORR_SIG_SIZE);
372+ }
373+
374+ XOnlyPubKey pubkey{pubkey_in};
375+
376+ if (!pubkey.VerifySchnorr (msg, sig)) {
377+ return set_error (serror, SCRIPT_ERR_SCHNORR_SIG);
378+ }
379+ } else {
380+ /*
381+ * New public key version softforks should be defined before this `else` block.
382+ * Generally, the new code should not do anything but failing the script execution. To avoid
383+ * consensus bugs, it should not modify any existing values (including `success`).
384+ */
385+ if ((flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE) != 0 ) {
386+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE);
387+ }
388+ }
389+
390+ return true ;
391+ }
392+
346393static bool EvalChecksigTapscript (const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool & success)
347394{
348395 assert (sigversion == SigVersion::TAPSCRIPT);
@@ -1213,6 +1260,39 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
12131260 }
12141261 break ;
12151262
1263+ case OP_CHECKSIGFROMSTACK:
1264+ {
1265+ // OP_CHECKSIGFROMSTACK is only available in Tapscript
1266+ if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) {
1267+ return set_error (serror, SCRIPT_ERR_BAD_OPCODE);
1268+ }
1269+
1270+ // <sig> <msg> <pubkey>
1271+ if (stack.size () < 3 ) {
1272+ return set_error (serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
1273+ }
1274+
1275+ const valtype& vchSigIn = stacktop (-3 );
1276+ const valtype& vchMsg = stacktop (-2 );
1277+ const valtype& vchPubKey = stacktop (-1 );
1278+
1279+ bool fSuccess = true ;
1280+
1281+ // Note that (as with CHECKSIG) if a signature was supplied and its
1282+ // verification fails, we do _not_ push a "false" result to the stack.
1283+ // Rather, we terminate script execution immediately. This might be
1284+ // surprising if you're reading this for the first time.
1285+ if (!EvalChecksigFromStack (vchSigIn, vchMsg, vchPubKey, execdata, flags, sigversion, serror, fSuccess )) {
1286+ return false ;
1287+ }
1288+
1289+ popstack (stack);
1290+ popstack (stack);
1291+ popstack (stack);
1292+ stack.push_back (fSuccess ? vchTrue : vchFalse);
1293+ }
1294+ break ;
1295+
12161296 default :
12171297 return set_error (serror, SCRIPT_ERR_BAD_OPCODE);
12181298 }
@@ -1807,10 +1887,19 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
18071887 }
18081888 // New opcodes will be listed here. May use a different sigversion to modify existing opcodes.
18091889 if (IsOpSuccess (opcode)) {
1810- if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1811- return set_error (serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1890+ if (opcode == OP_CHECKSIGFROMSTACK) {
1891+ if (flags & SCRIPT_VERIFY_DISCOURAGE_CHECKSIGFROMSTACK) {
1892+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1893+ } else if (!(flags & SCRIPT_VERIFY_CHECKSIGFROMSTACK)) {
1894+ return set_success (serror);
1895+ }
1896+ } else {
1897+ // OP_SUCCESS behaviour
1898+ if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1899+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1900+ }
1901+ return set_success (serror);
18121902 }
1813- return set_success (serror);
18141903 }
18151904 }
18161905
0 commit comments