Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501//! Satisfy an ECDSA signature check.502miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {503if (CreateSig(m_creator, m_sig_data, m_provider, sig, key, m_witness_script, SigVersion::WITNESS_V0)) {504return miniscript::Availability::YES;505}506return miniscript::Availability::NO;507}508};510/** Miniscript satisfier specific to Tapscript context. */511struct TapSatisfier: Satisfier<XOnlyPubKey> {512const uint256& m_leaf_hash;514explicit TapSatisfier(const SigningProvider& provider LIFETIMEBOUND, SignatureData& sig_data LIFETIMEBOUND,515const BaseSignatureCreator& creator LIFETIMEBOUND, const CScript& script LIFETIMEBOUND,516const uint256& leaf_hash LIFETIMEBOUND)517: Satisfier(provider, sig_data, creator, script, miniscript::MiniscriptContext::TAPSCRIPT),518m_leaf_hash(leaf_hash) {}520//! Conversion from a raw xonly public key.521template <typename I>522std::optional<XOnlyPubKey> FromPKBytes(I first, I last) const {523if (last - first != 32) return {};524XOnlyPubKey pubkey;525std::copy(first, last, pubkey.begin());526return pubkey;527}529//! Conversion from a raw xonly public key hash.530template<typename I>531std::optional<XOnlyPubKey> FromPKHBytes(I first, I last) const {532if (auto pubkey = Satisfier::CPubFromPKHBytes(first, last)) return XOnlyPubKey{*pubkey};533return {};534}536//! Satisfy a BIP340 signature check.537miniscript::Availability Sign(const XOnlyPubKey& key, std::vector<unsigned char>& sig) const {538if (CreateTaprootScriptSig(m_creator, m_sig_data, m_provider, sig, key, m_leaf_hash, SigVersion::TAPSCRIPT)) {539return miniscript::Availability::YES;540}541return miniscript::Availability::NO;542}543};545static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatureCreator& creator, SignatureData& sigdata, int leaf_version, std::span<const unsigned char> script_bytes, std::vector<valtype>& result)546{547// Only BIP342 tapscript signing is supported for now.548if (leaf_version != TAPROOT_LEAF_TAPSCRIPT) return false;550uint256 leaf_hash = ComputeTapleafHash(leaf_version, script_bytes);551CScript script = CScript(script_bytes.begin(), script_bytes.end());553TapSatisfier ms_satisfier{provider, sigdata, creator, script, leaf_hash};554const auto ms = miniscript::FromScript(script, ms_satisfier);555return ms && ms->Satisfy(ms_satisfier, result) == miniscript::Availability::YES;556}558static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCreator& creator, const WitnessV1Taproot& output, SignatureData& sigdata, std::vector<valtype>& result)559{560TaprootSpendData spenddata;561TaprootBuilder builder;563// Gather information about this output.564if (provider.GetTaprootSpendData(output, spenddata)) {565sigdata.tr_spenddata.Merge(spenddata);566}567if (provider.GetTaprootBuilder(output, builder)) {568sigdata.tr_builder = builder;569}570if (auto agg_keys = provider.GetAllMuSig2ParticipantPubkeys(); !agg_keys.empty()) {571sigdata.musig2_pubkeys.insert(agg_keys.begin(), agg_keys.end());572}575// Try key path spending.576{577KeyOriginInfo internal_key_info;578if (provider.GetKeyOriginByXOnly(sigdata.tr_spenddata.internal_key, internal_key_info)) {579auto it = sigdata.taproot_misc_pubkeys.find(sigdata.tr_spenddata.internal_key);580if (it == sigdata.taproot_misc_pubkeys.end()) {581sigdata.taproot_misc_pubkeys.emplace(sigdata.tr_spenddata.internal_key, std::make_pair(std::set<uint256>(), internal_key_info));582}583}585KeyOriginInfo output_key_info;586if (provider.GetKeyOriginByXOnly(output, output_key_info)) {587auto it = sigdata.taproot_misc_pubkeys.find(output);588if (it == sigdata.taproot_misc_pubkeys.end()) {589sigdata.taproot_misc_pubkeys.emplace(output, std::make_pair(std::set<uint256>(), output_key_info));590}591}593auto make_keypath_sig = [&](const XOnlyPubKey& pk, const uint256* merkle_root) {594std::vector<unsigned char> sig;595if (creator.CreateSchnorrSig(provider, sig, pk, nullptr, merkle_root, SigVersion::TAPROOT)) {596sigdata.taproot_key_path_sig = sig;597} else {598SignMuSig2(creator, sigdata, provider, sig, pk, merkle_root, /*leaf_hash=*/nullptr, SigVersion::TAPROOT);599}600};602// First try signing with internal key603if (sigdata.taproot_key_path_sig.size() == 0) {604make_keypath_sig(sigdata.tr_spenddata.internal_key, &sigdata.tr_spenddata.merkle_root);605}606// Try signing with output key if still no signature607if (sigdata.taproot_key_path_sig.size() == 0) {608make_keypath_sig(output, nullptr);609}610if (sigdata.taproot_key_path_sig.size()) {611result = Vector(sigdata.taproot_key_path_sig);612return true;613}614}616// Try script path spending.617std::vector<std::vector<unsigned char>> smallest_result_stack;618for (const auto& [key, control_blocks] : sigdata.tr_spenddata.scripts) {619const auto& [script, leaf_ver] = key;620std::vector<std::vector<unsigned char>> result_stack;621if (SignTaprootScript(provider, creator, sigdata, leaf_ver, script, result_stack)) {622result_stack.emplace_back(std::begin(script), std::end(script)); // Push the script623result_stack.push_back(*control_blocks.begin()); // Push the smallest control block624if (smallest_result_stack.size() == 0 ||625GetSerializeSize(result_stack) < GetSerializeSize(smallest_result_stack)) {626smallest_result_stack = std::move(result_stack);627}628}629}630if (smallest_result_stack.size() != 0) {631result = std::move(smallest_result_stack);632return true;633}635return false;636}638/**639* Sign scriptPubKey using signature made with creator.640* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),641* unless whichTypeRet is TxoutType::SCRIPTHASH, in which case scriptSigRet is the redemption script.642* Returns false if scriptPubKey could not be completely satisfied.643*/644static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey,645std::vector<valtype>& ret, TxoutType& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)646{647CScript scriptRet;648ret.clear();649std::vector<unsigned char> sig;651std::vector<valtype> vSolutions;652whichTypeRet = Solver(scriptPubKey, vSolutions);654switch (whichTypeRet) {655case TxoutType::NONSTANDARD:656case TxoutType::NULL_DATA:657case TxoutType::WITNESS_UNKNOWN:658return false;659case TxoutType::PUBKEY:660if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;661ret.push_back(std::move(sig));662return true;663case TxoutType::PUBKEYHASH: {664CKeyID keyID = CKeyID(uint160(vSolutions[0]));665CPubKey pubkey;666if (!GetPubKey(provider, sigdata, keyID, pubkey)) {667// Pubkey could not be found, add to missing668sigdata.missing_pubkeys.push_back(keyID);669return false;670}671if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false;672ret.push_back(std::move(sig));673ret.push_back(ToByteVector(pubkey));674return true;675}676case TxoutType::SCRIPTHASH: {677uint160 h160{vSolutions[0]};678if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {679ret.emplace_back(scriptRet.begin(), scriptRet.end());680return true;681}682// Could not find redeemScript, add to missing683sigdata.missing_redeem_script = h160;684return false;685}686case TxoutType::MULTISIG: {687size_t required = vSolutions.front()[0];688ret.emplace_back(); // workaround CHECKMULTISIG bug689for (size_t i = 1; i < vSolutions.size() - 1; ++i) {690CPubKey pubkey = CPubKey(vSolutions[i]);691// We need to always call CreateSig in order to fill sigdata with all692// possible signatures that we can create. This will allow further PSBT693// processing to work as it needs all possible signature and pubkey pairs694if (CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) {695if (ret.size() < required + 1) {696ret.push_back(std::move(sig));697}698}699}700bool ok = ret.size() == required + 1;701for (size_t i = 0; i + ret.size() < required + 1; ++i) {702ret.emplace_back();703}704return ok;705}706case TxoutType::WITNESS_V0_KEYHASH:707ret.push_back(vSolutions[0]);708return true;710case TxoutType::WITNESS_V0_SCRIPTHASH:711if (GetCScript(provider, sigdata, CScriptID{RIPEMD160(vSolutions[0])}, scriptRet)) {712ret.emplace_back(scriptRet.begin(), scriptRet.end());713return true;714}715// Could not find witnessScript, add to missing716sigdata.missing_witness_script = uint256(vSolutions[0]);717return false;719case TxoutType::WITNESS_V1_TAPROOT:720return SignTaproot(provider, creator, WitnessV1Taproot(XOnlyPubKey{vSolutions[0]}), sigdata, ret);722case TxoutType::ANCHOR:723return true;724} // no default case, so the compiler can warn about missing cases725assert(false);726}728static CScript PushAll(const std::vector<valtype>& values)729{730CScript result;731for (const valtype& v : values) {732if (v.size() == 0) {733result << OP_0;734} else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {735result << CScript::EncodeOP_N(v[0]);736} else if (v.size() == 1 && v[0] == 0x81) {737result << OP_1NEGATE;738} else {739result << v;740}741}742return result;743}745bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)746{747if (sigdata.complete) return true;749std::vector<valtype> result;750TxoutType whichType;