* Check transaction inputs. * * This does three things: * * Prevents mempool acceptance of spends of future * segwit versions we don't know how to validate * * Mitigates a potential denial-of-service attack with * P2SH scripts with a crazy number of expensive * CHECKSIG/CHECKMULTISIG operations. * * Prevents spends of unknown/irregular scriptPubKeys, * which mitigates poten
| 212 | * We also check the total number of non-witness sigops across the whole transaction, as per BIP54. |
| 213 | */ |
| 214 | TxValidationState ValidateInputsStandardness(const CTransaction& tx, const CCoinsViewCache& mapInputs) |
| 215 | { |
| 216 | TxValidationState state; |
| 217 | if (tx.IsCoinBase()) { |
| 218 | return state; // Coinbases don't use vin normally |
| 219 | } |
| 220 | |
| 221 | if (!CheckSigopsBIP54(tx, mapInputs)) { |
| 222 | state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs", "non-witness sigops exceed bip54 limit"); |
| 223 | return state; |
| 224 | } |
| 225 | |
| 226 | for (unsigned int i = 0; i < tx.vin.size(); i++) { |
| 227 | const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out; |
| 228 | |
| 229 | std::vector<std::vector<unsigned char> > vSolutions; |
| 230 | TxoutType whichType = Solver(prev.scriptPubKey, vSolutions); |
| 231 | if (whichType == TxoutType::NONSTANDARD) { |
| 232 | state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs", strprintf("input %u script unknown", i)); |
| 233 | return state; |
| 234 | } else if (whichType == TxoutType::WITNESS_UNKNOWN) { |
| 235 | // WITNESS_UNKNOWN failures are typically also caught with a policy |
| 236 | // flag in the script interpreter, but it can be helpful to catch |
| 237 | // this type of NONSTANDARD transaction earlier in transaction |
| 238 | // validation. |
| 239 | state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs", strprintf("input %u witness program is undefined", i)); |
| 240 | return state; |
| 241 | } else if (whichType == TxoutType::SCRIPTHASH) { |
| 242 | std::vector<std::vector<unsigned char> > stack; |
| 243 | ScriptError serror; |
| 244 | // convert the scriptSig into a stack, so we can inspect the redeemScript |
| 245 | if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE, &serror)) { |
| 246 | state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs", strprintf("p2sh scriptsig malformed (input %u: %s)", i, ScriptErrorString(serror))); |
| 247 | return state; |
| 248 | } |
| 249 | if (stack.empty()) { |
| 250 | state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs", strprintf("input %u P2SH redeemscript missing", i)); |
| 251 | return state; |
| 252 | } |
| 253 | CScript subscript(stack.back().begin(), stack.back().end()); |
| 254 | unsigned int sigop_count = subscript.GetSigOpCount(true); |
| 255 | if (sigop_count > MAX_P2SH_SIGOPS) { |
| 256 | state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs", strprintf("p2sh redeemscript sigops exceed limit (input %u: %u > %u)", i, sigop_count, MAX_P2SH_SIGOPS)); |
| 257 | return state; |
| 258 | } |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | return state; |
| 263 | } |
| 264 | |
| 265 | bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) |
| 266 | { |