Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #include <script/keyorigin.h>
# 7 : : #include <script/signingprovider.h>
# 8 : : #include <script/standard.h>
# 9 : :
# 10 : : #include <util/system.h>
# 11 : :
# 12 : : const SigningProvider& DUMMY_SIGNING_PROVIDER = SigningProvider();
# 13 : :
# 14 : : template<typename M, typename K, typename V>
# 15 : : bool LookupHelper(const M& map, const K& key, V& value)
# 16 : 812806 : {
# 17 : 812806 : auto it = map.find(key);
# 18 [ + + ][ + + ]: 812806 : if (it != map.end()) {
# [ + + ][ + + ]
# [ + + ]
# 19 : 703547 : value = it->second;
# 20 : 703547 : return true;
# 21 : 703547 : }
# 22 : 109259 : return false;
# 23 : 812806 : }
# 24 : :
# 25 : : bool HidingSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const
# 26 : 2182 : {
# 27 : 2182 : return m_provider->GetCScript(scriptid, script);
# 28 : 2182 : }
# 29 : :
# 30 : : bool HidingSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const
# 31 : 1777 : {
# 32 : 1777 : return m_provider->GetPubKey(keyid, pubkey);
# 33 : 1777 : }
# 34 : :
# 35 : : bool HidingSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const
# 36 : 24641 : {
# 37 [ + + ]: 24641 : if (m_hide_secret) return false;
# 38 : 10623 : return m_provider->GetKey(keyid, key);
# 39 : 24641 : }
# 40 : :
# 41 : : bool HidingSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const
# 42 : 4558 : {
# 43 [ + + ]: 4558 : if (m_hide_origin) return false;
# 44 : 3891 : return m_provider->GetKeyOrigin(keyid, info);
# 45 : 4558 : }
# 46 : :
# 47 : : bool HidingSigningProvider::GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const
# 48 : 1846 : {
# 49 : 1846 : return m_provider->GetTaprootSpendData(output_key, spenddata);
# 50 : 1846 : }
# 51 : :
# 52 : 27078 : bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
# 53 : 350817 : bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
# 54 : : bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const
# 55 : 342721 : {
# 56 : 342721 : std::pair<CPubKey, KeyOriginInfo> out;
# 57 : 342721 : bool ret = LookupHelper(origins, keyid, out);
# 58 [ + + ]: 342721 : if (ret) info = std::move(out.second);
# 59 : 342721 : return ret;
# 60 : 342721 : }
# 61 : 86348 : bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
# 62 : : bool FlatSigningProvider::GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const
# 63 : 5842 : {
# 64 : 5842 : return LookupHelper(tr_spenddata, output_key, spenddata);
# 65 : 5842 : }
# 66 : :
# 67 : : FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)
# 68 : 708329 : {
# 69 : 708329 : FlatSigningProvider ret;
# 70 : 708329 : ret.scripts = a.scripts;
# 71 : 708329 : ret.scripts.insert(b.scripts.begin(), b.scripts.end());
# 72 : 708329 : ret.pubkeys = a.pubkeys;
# 73 : 708329 : ret.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end());
# 74 : 708329 : ret.keys = a.keys;
# 75 : 708329 : ret.keys.insert(b.keys.begin(), b.keys.end());
# 76 : 708329 : ret.origins = a.origins;
# 77 : 708329 : ret.origins.insert(b.origins.begin(), b.origins.end());
# 78 : 708329 : ret.tr_spenddata = a.tr_spenddata;
# 79 [ + + ]: 708329 : for (const auto& [output_key, spenddata] : b.tr_spenddata) {
# 80 : 468 : ret.tr_spenddata[output_key].Merge(spenddata);
# 81 : 468 : }
# 82 : 708329 : return ret;
# 83 : 708329 : }
# 84 : :
# 85 : : void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
# 86 : 33602 : {
# 87 : 33602 : AssertLockHeld(cs_KeyStore);
# 88 : 33602 : CKeyID key_id = pubkey.GetID();
# 89 : : // This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH
# 90 : : // outputs. Technically P2WPKH outputs don't have a redeemscript to be
# 91 : : // spent. However, our current IsMine logic requires the corresponding
# 92 : : // P2SH-P2WPKH redeemscript to be present in the wallet in order to accept
# 93 : : // payment even to P2WPKH outputs.
# 94 : : // Also note that having superfluous scripts in the keystore never hurts.
# 95 : : // They're only used to guide recursion in signing and IsMine logic - if
# 96 : : // a script is present but we can't do anything with it, it has no effect.
# 97 : : // "Implicitly" refers to fact that scripts are derived automatically from
# 98 : : // existing keys, and are present in memory, even without being explicitly
# 99 : : // loaded (e.g. from a file).
# 100 [ + + ]: 33602 : if (pubkey.IsCompressed()) {
# 101 : 33572 : CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id));
# 102 : : // This does not use AddCScript, as it may be overridden.
# 103 : 33572 : CScriptID id(script);
# 104 : 33572 : mapScripts[id] = std::move(script);
# 105 : 33572 : }
# 106 : 33602 : }
# 107 : :
# 108 : : bool FillableSigningProvider::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
# 109 : 1074664 : {
# 110 : 1074664 : CKey key;
# 111 [ + + ]: 1074664 : if (!GetKey(address, key)) {
# 112 : 37645 : return false;
# 113 : 37645 : }
# 114 : 1037019 : vchPubKeyOut = key.GetPubKey();
# 115 : 1037019 : return true;
# 116 : 1074664 : }
# 117 : :
# 118 : : bool FillableSigningProvider::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
# 119 : 32023 : {
# 120 : 32023 : LOCK(cs_KeyStore);
# 121 : 32023 : mapKeys[pubkey.GetID()] = key;
# 122 : 32023 : ImplicitlyLearnRelatedKeyScripts(pubkey);
# 123 : 32023 : return true;
# 124 : 32023 : }
# 125 : :
# 126 : : bool FillableSigningProvider::HaveKey(const CKeyID &address) const
# 127 : 1012480 : {
# 128 : 1012480 : LOCK(cs_KeyStore);
# 129 : 1012480 : return mapKeys.count(address) > 0;
# 130 : 1012480 : }
# 131 : :
# 132 : : std::set<CKeyID> FillableSigningProvider::GetKeys() const
# 133 : 6 : {
# 134 : 6 : LOCK(cs_KeyStore);
# 135 : 6 : std::set<CKeyID> set_address;
# 136 [ + + ]: 1043 : for (const auto& mi : mapKeys) {
# 137 : 1043 : set_address.insert(mi.first);
# 138 : 1043 : }
# 139 : 6 : return set_address;
# 140 : 6 : }
# 141 : :
# 142 : : bool FillableSigningProvider::GetKey(const CKeyID &address, CKey &keyOut) const
# 143 : 1123691 : {
# 144 : 1123691 : LOCK(cs_KeyStore);
# 145 : 1123691 : KeyMap::const_iterator mi = mapKeys.find(address);
# 146 [ + + ]: 1123691 : if (mi != mapKeys.end()) {
# 147 : 1085889 : keyOut = mi->second;
# 148 : 1085889 : return true;
# 149 : 1085889 : }
# 150 : 37802 : return false;
# 151 : 1123691 : }
# 152 : :
# 153 : : bool FillableSigningProvider::AddCScript(const CScript& redeemScript)
# 154 : 23899 : {
# 155 [ - + ]: 23899 : if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
# 156 : 0 : return error("FillableSigningProvider::AddCScript(): redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
# 157 : :
# 158 : 23899 : LOCK(cs_KeyStore);
# 159 : 23899 : mapScripts[CScriptID(redeemScript)] = redeemScript;
# 160 : 23899 : return true;
# 161 : 23899 : }
# 162 : :
# 163 : : bool FillableSigningProvider::HaveCScript(const CScriptID& hash) const
# 164 : 796444 : {
# 165 : 796444 : LOCK(cs_KeyStore);
# 166 : 796444 : return mapScripts.count(hash) > 0;
# 167 : 796444 : }
# 168 : :
# 169 : : std::set<CScriptID> FillableSigningProvider::GetCScripts() const
# 170 : 7 : {
# 171 : 7 : LOCK(cs_KeyStore);
# 172 : 7 : std::set<CScriptID> set_script;
# 173 [ + + ]: 1437 : for (const auto& mi : mapScripts) {
# 174 : 1437 : set_script.insert(mi.first);
# 175 : 1437 : }
# 176 : 7 : return set_script;
# 177 : 7 : }
# 178 : :
# 179 : : bool FillableSigningProvider::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
# 180 : 122887 : {
# 181 : 122887 : LOCK(cs_KeyStore);
# 182 : 122887 : ScriptMap::const_iterator mi = mapScripts.find(hash);
# 183 [ + + ]: 122887 : if (mi != mapScripts.end())
# 184 : 65171 : {
# 185 : 65171 : redeemScriptOut = (*mi).second;
# 186 : 65171 : return true;
# 187 : 65171 : }
# 188 : 57716 : return false;
# 189 : 122887 : }
# 190 : :
# 191 : : CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination& dest)
# 192 : 1555 : {
# 193 : : // Only supports destinations which map to single public keys:
# 194 : : // P2PKH, P2WPKH, P2SH-P2WPKH, P2TR
# 195 [ + + ]: 1555 : if (auto id = std::get_if<PKHash>(&dest)) {
# 196 : 383 : return ToKeyID(*id);
# 197 : 383 : }
# 198 [ + + ]: 1172 : if (auto witness_id = std::get_if<WitnessV0KeyHash>(&dest)) {
# 199 : 653 : return ToKeyID(*witness_id);
# 200 : 653 : }
# 201 [ + + ]: 519 : if (auto script_hash = std::get_if<ScriptHash>(&dest)) {
# 202 : 390 : CScript script;
# 203 : 390 : CScriptID script_id(*script_hash);
# 204 : 390 : CTxDestination inner_dest;
# 205 [ + + ][ + + ]: 390 : if (store.GetCScript(script_id, script) && ExtractDestination(script, inner_dest)) {
# 206 [ + + ]: 335 : if (auto inner_witness_id = std::get_if<WitnessV0KeyHash>(&inner_dest)) {
# 207 : 294 : return ToKeyID(*inner_witness_id);
# 208 : 294 : }
# 209 : 335 : }
# 210 : 390 : }
# 211 [ + + ]: 225 : if (auto output_key = std::get_if<WitnessV1Taproot>(&dest)) {
# 212 : 66 : TaprootSpendData spenddata;
# 213 : 66 : CPubKey pub;
# 214 [ + - ]: 66 : if (store.GetTaprootSpendData(*output_key, spenddata)
# 215 [ + - ]: 66 : && !spenddata.internal_key.IsNull()
# 216 [ + + ]: 66 : && spenddata.merkle_root.IsNull()
# 217 [ + - ]: 66 : && store.GetPubKeyByXOnly(spenddata.internal_key, pub)) {
# 218 : 6 : return pub.GetID();
# 219 : 6 : }
# 220 : 66 : }
# 221 : 219 : return CKeyID();
# 222 : 225 : }
|