|
|
@ -1098,7 +1098,6 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (stack.empty()) |
|
|
|
if (stack.empty()) |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
|
|
|
|
|
|
|
|
if (CastToBool(stack.back()) == false) |
|
|
|
if (CastToBool(stack.back()) == false) |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
|
|
|
|
|
|
|
@ -1109,24 +1108,37 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne |
|
|
|
if (!scriptSig.IsPushOnly()) |
|
|
|
if (!scriptSig.IsPushOnly()) |
|
|
|
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY); |
|
|
|
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY); |
|
|
|
|
|
|
|
|
|
|
|
// stackCopy cannot be empty here, because if it was the
|
|
|
|
// Restore stack.
|
|
|
|
|
|
|
|
swap(stack, stackCopy); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// stack cannot be empty here, because if it was the
|
|
|
|
// P2SH HASH <> EQUAL scriptPubKey would be evaluated with
|
|
|
|
// P2SH HASH <> EQUAL scriptPubKey would be evaluated with
|
|
|
|
// an empty stack and the EvalScript above would return false.
|
|
|
|
// an empty stack and the EvalScript above would return false.
|
|
|
|
assert(!stackCopy.empty()); |
|
|
|
assert(!stack.empty()); |
|
|
|
|
|
|
|
|
|
|
|
const valtype& pubKeySerialized = stackCopy.back(); |
|
|
|
const valtype& pubKeySerialized = stack.back(); |
|
|
|
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); |
|
|
|
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); |
|
|
|
popstack(stackCopy); |
|
|
|
popstack(stack); |
|
|
|
|
|
|
|
|
|
|
|
if (!EvalScript(stackCopy, pubKey2, flags, checker, serror)) |
|
|
|
if (!EvalScript(stack, pubKey2, flags, checker, serror)) |
|
|
|
// serror is set
|
|
|
|
// serror is set
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (stackCopy.empty()) |
|
|
|
if (stack.empty()) |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
if (!CastToBool(stackCopy.back())) |
|
|
|
if (!CastToBool(stack.back())) |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
return set_error(serror, SCRIPT_ERR_EVAL_FALSE); |
|
|
|
else |
|
|
|
} |
|
|
|
return set_success(serror); |
|
|
|
|
|
|
|
|
|
|
|
// The CLEANSTACK check is only performed after potential P2SH evaluation,
|
|
|
|
|
|
|
|
// as the non-P2SH evaluation of a P2SH script will obviously not result in
|
|
|
|
|
|
|
|
// a clean stack (the P2SH inputs remain).
|
|
|
|
|
|
|
|
if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) { |
|
|
|
|
|
|
|
// Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK
|
|
|
|
|
|
|
|
// would be possible, which is not a softfork (and P2SH should be one).
|
|
|
|
|
|
|
|
assert((flags & SCRIPT_VERIFY_P2SH) != 0); |
|
|
|
|
|
|
|
if (stack.size() != 1) { |
|
|
|
|
|
|
|
return set_error(serror, SCRIPT_ERR_CLEANSTACK); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return set_success(serror); |
|
|
|
return set_success(serror); |
|
|
|