205c858 bench: add script verification benchmark for P2TR script-path spends:
This looks like an extension of the enum, so we could reduce the noise in this already complicated method by moving it closer to the source. Modifying ScriptType should likely also require updating WitnessElementCount:
enum class ScriptType {
P2WPKH, // segwitv0, witness-pubkey-hash (ECDSA signature)
P2TR_KeyPath, // segwitv1, taproot key-path spend (Schnorr signature)
P2TR_ScriptPath, // segwitv1, taproot script-path spend (Tapscript leaf with a single OP_CHECKSIG)
};
static size_t WitnessElementCount(ScriptType script_type)
{
switch (script_type) {
case ScriptType::P2WPKH: return 2; // [pubkey, signature]
case ScriptType::P2TR_KeyPath: return 1; // [signature]
case ScriptType::P2TR_ScriptPath: return 3; // [signature, tapscript, control block]
} // no default case, so the compiler can warn about missing cases
assert(false);
}
This would also let us validate the witness shape before calling txdata.Init(), something like:
// Sign spending transaction, precompute transaction data
PrecomputedTransactionData txdata;
{
const std::map<COutPoint, Coin> coins{{txSpend.vin[0].prevout, Coin(txCredit.vout[0], /*nHeightIn=*/100, /*fCoinBaseIn=*/false)}};
std::map<int, bilingual_str> input_errors;
assert(SignTransaction(txSpend, &keystore, coins, SIGHASH_ALL, input_errors));
assert(txSpend.vin[0].scriptWitness.stack.size() == WitnessElementCount(script_type));
txdata.Init(txSpend, /*spent_outputs=*/{txCredit.vout[0]});
}
I also inlined bool complete = SignTransaction(...) since other usages in the codebase look like that.
nit: if you decide to keep it, is wit a commonly used abbreviation?
const auto expected_witness_count{[&]() -> size_t {