@@ -343,6 +343,53 @@ static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPu
343
343
return true ;
344
344
}
345
345
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
+
346
393
static bool EvalChecksigTapscript (const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool & success)
347
394
{
348
395
assert (sigversion == SigVersion::TAPSCRIPT);
@@ -1213,6 +1260,39 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
1213
1260
}
1214
1261
break ;
1215
1262
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
+
1216
1296
default :
1217
1297
return set_error (serror, SCRIPT_ERR_BAD_OPCODE);
1218
1298
}
@@ -1800,8 +1880,18 @@ static bool ExecuteWitnessScript(const std::span<const valtype>& stack_span, con
1800
1880
}
1801
1881
// New opcodes will be listed here. May use a different sigversion to modify existing opcodes.
1802
1882
if (IsOpSuccess (opcode)) {
1803
- if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1804
- return set_error (serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1883
+ if (opcode == OP_CHECKSIGFROMSTACK) {
1884
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_CHECKSIGFROMSTACK) {
1885
+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1886
+ } else if (!(flags & SCRIPT_VERIFY_CHECKSIGFROMSTACK)) {
1887
+ return set_success (serror);
1888
+ }
1889
+ } else {
1890
+ // OP_SUCCESS behaviour
1891
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1892
+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1893
+ }
1894
+ return set_success (serror);
1805
1895
}
1806
1896
return set_success (serror);
1807
1897
}
0 commit comments