@@ -1414,9 +1414,26 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
1414
1414
template class GenericTransactionSignatureChecker <CTransaction>;
1415
1415
template class GenericTransactionSignatureChecker <CMutableTransaction>;
1416
1416
1417
+ static bool ExecuteWitnessScript (std::vector<valtype>::const_iterator begin, std::vector<valtype>::const_iterator end, const CScript& scriptPubKey, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptError* serror)
1418
+ {
1419
+ std::vector<valtype> stack{begin, end};
1420
+
1421
+ // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
1422
+ for (const valtype& elem : stack) {
1423
+ if (elem.size () > MAX_SCRIPT_ELEMENT_SIZE) return set_error (serror, SCRIPT_ERR_PUSH_SIZE);
1424
+ }
1425
+
1426
+ // Run the script interpreter.
1427
+ if (!EvalScript (stack, scriptPubKey, flags, checker, sigversion, serror)) return false ;
1428
+
1429
+ // Scripts inside witness implicitly require cleanstack behaviour
1430
+ if (stack.size () != 1 ) return set_error (serror, SCRIPT_ERR_CLEANSTACK);
1431
+ if (!CastToBool (stack.back ())) return set_error (serror, SCRIPT_ERR_EVAL_FALSE);
1432
+ return true ;
1433
+ }
1434
+
1417
1435
static bool VerifyWitnessProgram (const CScriptWitness& witness, int witversion, const std::vector<unsigned char >& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
1418
1436
{
1419
- std::vector<std::vector<unsigned char > > stack;
1420
1437
CScript scriptPubKey;
1421
1438
1422
1439
if (witversion == 0 ) {
@@ -1426,45 +1443,30 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
1426
1443
return set_error (serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
1427
1444
}
1428
1445
scriptPubKey = CScript (witness.stack .back ().begin (), witness.stack .back ().end ());
1429
- stack = std::vector<std::vector<unsigned char > >(witness.stack .begin (), witness.stack .end () - 1 );
1430
1446
uint256 hashScriptPubKey;
1431
1447
CSHA256 ().Write (&scriptPubKey[0 ], scriptPubKey.size ()).Finalize (hashScriptPubKey.begin ());
1432
1448
if (memcmp (hashScriptPubKey.begin (), program.data (), 32 )) {
1433
1449
return set_error (serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
1434
1450
}
1451
+ return ExecuteWitnessScript (witness.stack .begin (), witness.stack .end () - 1 , scriptPubKey, flags, SigVersion::WITNESS_V0, checker, serror);
1435
1452
} else if (program.size () == WITNESS_V0_KEYHASH_SIZE) {
1436
1453
// Special case for pay-to-pubkeyhash; signature + pubkey in witness
1437
1454
if (witness.stack .size () != 2 ) {
1438
1455
return set_error (serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness
1439
1456
}
1440
1457
scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG;
1441
- stack = witness.stack ;
1458
+ return ExecuteWitnessScript (witness. stack . begin (), witness.stack . end (), scriptPubKey, flags, SigVersion::WITNESS_V0, checker, serror) ;
1442
1459
} else {
1443
1460
return set_error (serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
1444
1461
}
1445
- } else if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
1446
- return set_error (serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
1447
1462
} else {
1463
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
1464
+ return set_error (serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
1465
+ }
1448
1466
// Higher version witness scripts return true for future softfork compatibility
1449
- return set_success (serror);
1450
- }
1451
-
1452
- // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
1453
- for (unsigned int i = 0 ; i < stack.size (); i++) {
1454
- if (stack.at (i).size () > MAX_SCRIPT_ELEMENT_SIZE)
1455
- return set_error (serror, SCRIPT_ERR_PUSH_SIZE);
1456
- }
1457
-
1458
- if (!EvalScript (stack, scriptPubKey, flags, checker, SigVersion::WITNESS_V0, serror)) {
1459
- return false ;
1467
+ return true ;
1460
1468
}
1461
-
1462
- // Scripts inside witness implicitly require cleanstack behaviour
1463
- if (stack.size () != 1 )
1464
- return set_error (serror, SCRIPT_ERR_CLEANSTACK);
1465
- if (!CastToBool (stack.back ()))
1466
- return set_error (serror, SCRIPT_ERR_EVAL_FALSE);
1467
- return true ;
1469
+ // There is intentionally no return statement here, to be able to use "control reaches end of non-void function" warnings to detect gaps in the logic above.
1468
1470
}
1469
1471
1470
1472
bool VerifyScript (const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
0 commit comments