MCPcopy Create free account
hub / github.com/ElementsProject/elements / IsWitnessStandard

Function IsWitnessStandard

src/policy/policy.cpp:221–309  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

219}
220
221bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
222{
223 if (tx.IsCoinBase())
224 return true; // Coinbases are skipped
225
226 for (unsigned int i = 0; i < tx.vin.size(); i++)
227 {
228 // We don't care if witness for this input is empty, since it must not be bloated.
229 // If the script is invalid without witness, it would be caught sooner or later during validation.
230 if (tx.witness.vtxinwit.size() <= i || tx.witness.vtxinwit[i].scriptWitness.IsNull()) {
231 continue;
232 }
233
234 const CTxOut &prev = tx.vin[i].m_is_pegin ? GetPeginOutputFromWitness(tx.witness.vtxinwit[i].m_pegin_witness) : mapInputs.AccessCoin(tx.vin[i].prevout).out;
235
236 // get the scriptPubKey corresponding to this input:
237 CScript prevScript = prev.scriptPubKey;
238
239 bool p2sh = false;
240 if (prevScript.IsPayToScriptHash()) {
241 std::vector <std::vector<unsigned char> > stack;
242 // If the scriptPubKey is P2SH, we try to extract the redeemScript casually by converting the scriptSig
243 // into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway.
244 // If the check fails at this stage, we know that this txid must be a bad one.
245 if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
246 return false;
247 if (stack.empty())
248 return false;
249 prevScript = CScript(stack.back().begin(), stack.back().end());
250 p2sh = true;
251 }
252
253 int witnessversion = 0;
254 std::vector<unsigned char> witnessprogram;
255
256 // Non-witness program must not be associated with any witness
257 if (!prevScript.IsWitnessProgram(witnessversion, witnessprogram))
258 return false;
259
260 // Check P2WSH standard limits
261 if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
262 const CScriptWitness& scriptWitness = tx.witness.vtxinwit[i].scriptWitness;
263 if (scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
264 return false;
265 size_t sizeWitnessStack = scriptWitness.stack.size() - 1;
266 if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS)
267 return false;
268 for (unsigned int j = 0; j < sizeWitnessStack; j++) {
269 if (scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
270 return false;
271 }
272 }
273
274 // Check policy limits for Taproot spends:
275 // - MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE limit for stack item size
276 // - No annexes
277 if (witnessversion == 1 && witnessprogram.size() == WITNESS_V1_TAPROOT_SIZE && !p2sh) {
278 // Missing witness; invalid by consensus rules

Callers 3

PreChecksMethod · 0.85
FUZZ_TARGET_INITFunction · 0.85
FUZZ_TARGET_INITFunction · 0.85

Calls 12

EvalScriptFunction · 0.85
IsPayToScriptHashMethod · 0.80
IsWitnessProgramMethod · 0.80
CScriptClass · 0.50
IsCoinBaseMethod · 0.45
sizeMethod · 0.45
IsNullMethod · 0.45
emptyMethod · 0.45
beginMethod · 0.45
endMethod · 0.45

Tested by 2

FUZZ_TARGET_INITFunction · 0.68
FUZZ_TARGET_INITFunction · 0.68