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.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <script/signingprovider.h>8#include <musig.h>9#include <script/interpreter.h>10#include <script/keyorigin.h>11#include <util/check.h>12#include <util/log.h>14#include <algorithm>15#include <cstddef>16#include <variant>18const SigningProvider& DUMMY_SIGNING_PROVIDER = SigningProvider();20template<typename M, typename K, typename V>21bool LookupHelper(const M& map, const K& key, V& value)22{23auto it = map.find(key);24if (it != map.end()) {25value = it->second;26return true;27}28return false;29}31bool HidingSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const32{33return m_provider->GetCScript(scriptid, script);34}36bool HidingSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const37{38return m_provider->GetPubKey(keyid, pubkey);39}41bool HidingSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const42{43if (m_hide_secret) return false;44return m_provider->GetKey(keyid, key);45}47bool HidingSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const48{49if (m_hide_origin) return false;50return m_provider->GetKeyOrigin(keyid, info);51}53bool HidingSigningProvider::GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const54{55return m_provider->GetTaprootSpendData(output_key, spenddata);56}57bool HidingSigningProvider::GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const58{59return m_provider->GetTaprootBuilder(output_key, builder);60}61std::vector<CPubKey> HidingSigningProvider::GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const62{63if (m_hide_origin) return {};64return m_provider->GetMuSig2ParticipantPubkeys(pubkey);65}67std::map<CPubKey, std::vector<CPubKey>> HidingSigningProvider::GetAllMuSig2ParticipantPubkeys() const68{69return m_provider->GetAllMuSig2ParticipantPubkeys();70}72void HidingSigningProvider::SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const73{74m_provider->SetMuSig2SecNonce(id, std::move(nonce));75}77std::optional<std::reference_wrapper<MuSig2SecNonce>> HidingSigningProvider::GetMuSig2SecNonce(const uint256& session_id) const78{79return m_provider->GetMuSig2SecNonce(session_id);80}82void HidingSigningProvider::DeleteMuSig2Session(const uint256& session_id) const83{84m_provider->DeleteMuSig2Session(session_id);85}87bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }88bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }89bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const90{91std::pair<CPubKey, KeyOriginInfo> out;92bool ret = LookupHelper(origins, keyid, out);93if (ret) info = std::move(out.second);94return ret;95}96bool FlatSigningProvider::HaveKey(const CKeyID &keyid) const97{98CKey key;99return LookupHelper(keys, keyid, key);100}101bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }102bool FlatSigningProvider::GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const103{104TaprootBuilder builder;105if (LookupHelper(tr_trees, output_key, builder)) {106spenddata = builder.GetSpendData();107return true;108}109return false;110}111bool FlatSigningProvider::GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const112{113return LookupHelper(tr_trees, output_key, builder);114}116std::vector<CPubKey> FlatSigningProvider::GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const117{118std::vector<CPubKey> participant_pubkeys;119LookupHelper(aggregate_pubkeys, pubkey, participant_pubkeys);120return participant_pubkeys;121}123std::map<CPubKey, std::vector<CPubKey>> FlatSigningProvider::GetAllMuSig2ParticipantPubkeys() const124{125return aggregate_pubkeys;126}128void FlatSigningProvider::SetMuSig2SecNonce(const uint256& session_id, MuSig2SecNonce&& nonce) const129{130if (!Assume(musig2_secnonces)) return;131auto [it, inserted] = musig2_secnonces->try_emplace(session_id, std::move(nonce));132// No secnonce should exist for this session yet.133Assert(inserted);134}136std::optional<std::reference_wrapper<MuSig2SecNonce>> FlatSigningProvider::GetMuSig2SecNonce(const uint256& session_id) const137{138if (!Assume(musig2_secnonces)) return std::nullopt;139const auto& it = musig2_secnonces->find(session_id);140if (it == musig2_secnonces->end()) return std::nullopt;141return it->second;142}144void FlatSigningProvider::DeleteMuSig2Session(const uint256& session_id) const145{146if (!Assume(musig2_secnonces)) return;147musig2_secnonces->erase(session_id);148}150FlatSigningProvider& FlatSigningProvider::Merge(FlatSigningProvider&& b)151{152scripts.merge(b.scripts);153pubkeys.merge(b.pubkeys);154keys.merge(b.keys);155origins.merge(b.origins);156tr_trees.merge(b.tr_trees);157aggregate_pubkeys.merge(b.aggregate_pubkeys);158// We shouldn't be merging 2 different sessions, just overwrite with b's sessions.159if (!musig2_secnonces) musig2_secnonces = b.musig2_secnonces;160return *this;161}163void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)164{165AssertLockHeld(cs_KeyStore);166CKeyID key_id = pubkey.GetID();167// This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH168// outputs. Technically P2WPKH outputs don't have a redeemscript to be169// spent. However, our current IsMine logic requires the corresponding170// P2SH-P2WPKH redeemscript to be present in the wallet in order to accept171// payment even to P2WPKH outputs.172// Also note that having superfluous scripts in the keystore never hurts.173// They're only used to guide recursion in signing and IsMine logic - if174// a script is present but we can't do anything with it, it has no effect.175// "Implicitly" refers to fact that scripts are derived automatically from176// existing keys, and are present in memory, even without being explicitly177// loaded (e.g. from a file).178if (pubkey.IsCompressed()) {179CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id));180// This does not use AddCScript, as it may be overridden.181CScriptID id(script);182mapScripts[id] = std::move(script);183}184}186bool FillableSigningProvider::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const187{188CKey key;189if (!GetKey(address, key)) {190return false;191}192vchPubKeyOut = key.GetPubKey();193return true;194}196bool FillableSigningProvider::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)197{198LOCK(cs_KeyStore);199mapKeys[pubkey.GetID()] = key;200ImplicitlyLearnRelatedKeyScripts(pubkey);201return true;202}204bool FillableSigningProvider::HaveKey(const CKeyID &address) const205{206LOCK(cs_KeyStore);207return mapKeys.contains(address);208}210std::set<CKeyID> FillableSigningProvider::GetKeys() const211{212LOCK(cs_KeyStore);213std::set<CKeyID> set_address;214for (const auto& mi : mapKeys) {215set_address.insert(mi.first);216}217return set_address;218}220bool FillableSigningProvider::GetKey(const CKeyID &address, CKey &keyOut) const221{222LOCK(cs_KeyStore);223KeyMap::const_iterator mi = mapKeys.find(address);224if (mi != mapKeys.end()) {225keyOut = mi->second;226return true;227}228return false;229}231bool FillableSigningProvider::AddCScript(const CScript& redeemScript)232{233if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) {234LogError("FillableSigningProvider::AddCScript(): redeemScripts > %i bytes are invalid\n", MAX_SCRIPT_ELEMENT_SIZE);235return false;236}238LOCK(cs_KeyStore);239mapScripts[CScriptID(redeemScript)] = redeemScript;240return true;241}243bool FillableSigningProvider::HaveCScript(const CScriptID& hash) const244{245LOCK(cs_KeyStore);246return mapScripts.contains(hash);247}249std::set<CScriptID> FillableSigningProvider::GetCScripts() const250{
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.