@@ -343,6 +343,48 @@ 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+ assert (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0 || sigversion == SigVersion::TAPSCRIPT);
349+ /*
350+ * The following validation sequence is consensus critical. Please note how --
351+ * upgradable public key versions precede other rules;
352+ * the script execution fails when using empty signature with invalid public key;
353+ * the script execution fails when using non-empty invalid signature.
354+ */
355+ success = !sig.empty ();
356+ if (success && sigversion == SigVersion::TAPSCRIPT) {
357+ // Implement the sigops/witnesssize ratio test.
358+ // Passing with an upgradable public key version is also counted.
359+ assert (execdata.m_validation_weight_left_init );
360+ execdata.m_validation_weight_left -= VALIDATION_WEIGHT_PER_SIGOP_PASSED;
361+ if (execdata.m_validation_weight_left < 0 ) {
362+ return set_error (serror, SCRIPT_ERR_TAPSCRIPT_VALIDATION_WEIGHT);
363+ }
364+ }
365+ if (pubkey_in.size () == 0 ) {
366+ return set_error (serror, SCRIPT_ERR_PUBKEYTYPE);
367+ } else if (pubkey_in.size () == 32 ) {
368+ if (!success) return true ;
369+ if (sig.size () != 64 ) return set_error (serror, SCRIPT_ERR_SCHNORR_SIG_SIZE);
370+
371+ XOnlyPubKey pubkey{pubkey_in};
372+
373+ if (!pubkey.VerifySchnorr (msg, sig)) return set_error (serror, SCRIPT_ERR_SCHNORR_SIG);
374+ } else {
375+ /*
376+ * New public key version softforks should be defined before this `else` block.
377+ * Generally, the new code should not do anything but failing the script execution. To avoid
378+ * consensus bugs, it should not modify any existing values (including `success`).
379+ */
380+ if ((flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE) != 0 ) {
381+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE);
382+ }
383+ }
384+
385+ return true ;
386+ }
387+
346388static bool EvalChecksigTapscript (const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool & success)
347389{
348390 assert (sigversion == SigVersion::TAPSCRIPT);
@@ -1213,6 +1255,31 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
12131255 }
12141256 break ;
12151257
1258+ case OP_CHECKSIGFROMSTACK: {
1259+ // DISCOURAGE for OP_CHECKSIGFROMSTACK is handled in OP_SUCCESS handling
1260+ // OP_CHECKSIGFROMSTACK is only available in Tapscript
1261+ if (opcode == OP_CHECKSIGFROMSTACK && (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0)) {
1262+ return set_error (serror, SCRIPT_ERR_BAD_OPCODE);
1263+ }
1264+
1265+ // sig message pubkey
1266+ if (stack.size () < 3 )
1267+ return set_error (serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
1268+
1269+ const valtype& vchSigIn = stacktop (-3 );
1270+ const valtype& vchMsg = stacktop (-2 );
1271+ const valtype& vchPubKey = stacktop (-1 );
1272+
1273+ bool fSuccess = true ;
1274+ if (!EvalChecksigFromStack (vchSigIn, vchMsg, vchPubKey, execdata, flags, sigversion, serror, fSuccess )) return false ;
1275+
1276+ popstack (stack);
1277+ popstack (stack);
1278+ popstack (stack);
1279+ stack.push_back (fSuccess ? vchTrue : vchFalse);
1280+ break ;
1281+ }
1282+
12161283 default :
12171284 return set_error (serror, SCRIPT_ERR_BAD_OPCODE);
12181285 }
@@ -1798,6 +1865,12 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
17981865 // Note how this condition would not be reached if an unknown OP_SUCCESSx was found
17991866 return set_error (serror, SCRIPT_ERR_BAD_OPCODE);
18001867 }
1868+ if (opcode == OP_CHECKSIGFROMSTACK) {
1869+ if (flags & SCRIPT_VERIFY_DISCOURAGE_CHECKSIGFROMSTACK)
1870+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1871+ if (flags & SCRIPT_VERIFY_CHECKSIGFROMSTACK) continue ;
1872+ return set_success (serror);
1873+ }
18011874 // New opcodes will be listed here. May use a different sigversion to modify existing opcodes.
18021875 if (IsOpSuccess (opcode)) {
18031876 if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
0 commit comments