sCrypt
April 23, 2025, 10:55pm
8
In practice, standardness rule has SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS
, which would make any script containing OP_SUCCESSx
fail immediately, instead of succeeding .
SCRIPT_VERIFY_MINIMALDATA |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
SCRIPT_VERIFY_CLEANSTACK |
SCRIPT_VERIFY_MINIMALIF |
SCRIPT_VERIFY_NULLFAIL |
SCRIPT_VERIFY_LOW_S |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE |
SCRIPT_VERIFY_CONST_SCRIPTCODE |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};
/** For convenience, standard but not mandatory verify flags. */
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};
/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE};
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
// OP_SUCCESSx processing overrides everything, including stack element size limits
CScript::const_iterator pc = exec_script.begin();
while (pc < exec_script.end()) {
opcodetype opcode;
if (!exec_script.GetOp(pc, opcode)) {
// Note how this condition would not be reached if an unknown OP_SUCCESSx was found
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
}
// New opcodes will be listed here. May use a different sigversion to modify existing opcodes.
if (IsOpSuccess(opcode)) {
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
}
return set_success(serror);
}
}
// Tapscript enforces initial stack size limits (altstack is empty here)
if (stack.size() > MAX_STACK_SIZE) return set_error(serror, SCRIPT_ERR_STACK_SIZE);
}
So the above scheme works, assuming no miner colludes with Bob by turning off SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS
. Updated the original article .