bench: add script verification benchmark for P2TR key path spends

This commit is contained in:
Sebastian Falbesoner
2026-02-02 01:00:43 +01:00
parent dd93362a1d
commit d339884f1d

View File

@@ -20,36 +20,45 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
// Microbenchmark for verification of a basic P2WPKH script. Can be easily enum class ScriptType {
// modified to measure performance of other types of scripts. P2WPKH, // segwitv0, witness-pubkey-hash (ECDSA signature)
static void VerifyScriptBench(benchmark::Bench& bench) P2TR, // segwitv1, taproot key-path spend (Schnorr signature)
};
// Microbenchmark for verification of standard scripts.
static void VerifyScriptBench(benchmark::Bench& bench, ScriptType script_type)
{ {
ECC_Context ecc_context{}; ECC_Context ecc_context{};
// Create deterministic key material needed for output script creation / signing // Create deterministic key material needed for output script creation / signing
FlatSigningProvider keystore; CKey privkey;
CPubKey pubkey; privkey.Set(uint256::ONE.begin(), uint256::ONE.end(), /*fCompressedIn=*/true);
{ CPubKey pubkey = privkey.GetPubKey();
CKey privkey; CKeyID key_id = pubkey.GetID();
privkey.Set(uint256::ONE.begin(), uint256::ONE.end(), /*fCompressedIn=*/true);
pubkey = privkey.GetPubKey();
CKeyID key_id = pubkey.GetID();
keystore.keys.emplace(key_id, privkey);
keystore.pubkeys.emplace(key_id, pubkey);
}
// Create crediting and spending transactions FlatSigningProvider keystore;
CScript scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkey)); keystore.keys.emplace(key_id, privkey);
const CMutableTransaction& txCredit = BuildCreditingTransaction(scriptPubKey, 1); keystore.pubkeys.emplace(key_id, pubkey);
// Create crediting and spending transactions with provided input type
CTxDestination dest;
switch (script_type) {
case ScriptType::P2WPKH: dest = WitnessV0KeyHash(pubkey); break;
case ScriptType::P2TR: dest = WitnessV1Taproot(XOnlyPubKey{pubkey}); break;
default: assert(false);
}
const CMutableTransaction& txCredit = BuildCreditingTransaction(GetScriptForDestination(dest), 1);
CMutableTransaction txSpend = BuildSpendingTransaction(/*scriptSig=*/{}, /*scriptWitness=*/{}, CTransaction(txCredit)); CMutableTransaction txSpend = BuildSpendingTransaction(/*scriptSig=*/{}, /*scriptWitness=*/{}, CTransaction(txCredit));
// Sign spending transaction // Sign spending transaction, precompute transaction data
PrecomputedTransactionData txdata;
{ {
std::map<COutPoint, Coin> coins; std::map<COutPoint, Coin> coins;
coins[txSpend.vin[0].prevout] = Coin(txCredit.vout[0], /*nHeightIn=*/100, /*fCoinBaseIn=*/false); coins[txSpend.vin[0].prevout] = Coin(txCredit.vout[0], /*nHeightIn=*/100, /*fCoinBaseIn=*/false);
std::map<int, bilingual_str> input_errors; std::map<int, bilingual_str> input_errors;
bool complete = SignTransaction(txSpend, &keystore, coins, SIGHASH_ALL, input_errors); bool complete = SignTransaction(txSpend, &keystore, coins, SIGHASH_ALL, input_errors);
assert(complete); assert(complete);
txdata.Init(txSpend, /*spent_outputs=*/{txCredit.vout[0]});
} }
// Benchmark. // Benchmark.
@@ -60,13 +69,16 @@ static void VerifyScriptBench(benchmark::Bench& bench)
txCredit.vout[0].scriptPubKey, txCredit.vout[0].scriptPubKey,
&txSpend.vin[0].scriptWitness, &txSpend.vin[0].scriptWitness,
STANDARD_SCRIPT_VERIFY_FLAGS, STANDARD_SCRIPT_VERIFY_FLAGS,
MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue, MissingDataBehavior::ASSERT_FAIL), MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue, txdata, MissingDataBehavior::ASSERT_FAIL),
&err); &err);
assert(err == SCRIPT_ERR_OK); assert(err == SCRIPT_ERR_OK);
assert(success); assert(success);
}); });
} }
static void VerifyScriptP2WPKH(benchmark::Bench& bench) { VerifyScriptBench(bench, ScriptType::P2WPKH); }
static void VerifyScriptP2TR(benchmark::Bench& bench) { VerifyScriptBench(bench, ScriptType::P2TR); }
static void VerifyNestedIfScript(benchmark::Bench& bench) static void VerifyNestedIfScript(benchmark::Bench& bench)
{ {
std::vector<std::vector<unsigned char>> stack; std::vector<std::vector<unsigned char>> stack;
@@ -88,5 +100,6 @@ static void VerifyNestedIfScript(benchmark::Bench& bench)
}); });
} }
BENCHMARK(VerifyScriptBench); BENCHMARK(VerifyScriptP2WPKH);
BENCHMARK(VerifyScriptP2TR);
BENCHMARK(VerifyNestedIfScript); BENCHMARK(VerifyNestedIfScript);