Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 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 : 732354 : {
# 17 : 732354 : auto it = map.find(key);
# 18 [ + + ][ + + ]: 732354 : if (it != map.end()) {
# [ + + ][ + + ]
# 19 : 691892 : value = it->second;
# 20 : 691892 : return true;
# 21 : 691892 : }
# 22 : 40462 : return false;
# 23 : 40462 : }
# 24 : :
# 25 : : bool HidingSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const
# 26 : 685 : {
# 27 : 685 : return m_provider->GetCScript(scriptid, script);
# 28 : 685 : }
# 29 : :
# 30 : : bool HidingSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const
# 31 : 1113 : {
# 32 : 1113 : return m_provider->GetPubKey(keyid, pubkey);
# 33 : 1113 : }
# 34 : :
# 35 : : bool HidingSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const
# 36 : 1822 : {
# 37 [ + + ]: 1822 : if (m_hide_secret) return false;
# 38 : 527 : return m_provider->GetKey(keyid, key);
# 39 : 527 : }
# 40 : :
# 41 : : bool HidingSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const
# 42 : 1822 : {
# 43 [ + + ]: 1822 : if (m_hide_origin) return false;
# 44 : 1511 : return m_provider->GetKeyOrigin(keyid, info);
# 45 : 1511 : }
# 46 : :
# 47 : 20732 : bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
# 48 : 350235 : bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
# 49 : : bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const
# 50 : 335708 : {
# 51 : 335708 : std::pair<CPubKey, KeyOriginInfo> out;
# 52 : 335708 : bool ret = LookupHelper(origins, keyid, out);
# 53 [ + + ]: 335708 : if (ret) info = std::move(out.second);
# 54 : 335708 : return ret;
# 55 : 335708 : }
# 56 : 25679 : bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
# 57 : :
# 58 : : FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)
# 59 : 563842 : {
# 60 : 563842 : FlatSigningProvider ret;
# 61 : 563842 : ret.scripts = a.scripts;
# 62 : 563842 : ret.scripts.insert(b.scripts.begin(), b.scripts.end());
# 63 : 563842 : ret.pubkeys = a.pubkeys;
# 64 : 563842 : ret.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end());
# 65 : 563842 : ret.keys = a.keys;
# 66 : 563842 : ret.keys.insert(b.keys.begin(), b.keys.end());
# 67 : 563842 : ret.origins = a.origins;
# 68 : 563842 : ret.origins.insert(b.origins.begin(), b.origins.end());
# 69 : 563842 : return ret;
# 70 : 563842 : }
# 71 : :
# 72 : : void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
# 73 : 39447 : {
# 74 : 39447 : AssertLockHeld(cs_KeyStore);
# 75 : 39447 : CKeyID key_id = pubkey.GetID();
# 76 : : // This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH
# 77 : : // outputs. Technically P2WPKH outputs don't have a redeemscript to be
# 78 : : // spent. However, our current IsMine logic requires the corresponding
# 79 : : // P2SH-P2WPKH redeemscript to be present in the wallet in order to accept
# 80 : : // payment even to P2WPKH outputs.
# 81 : : // Also note that having superfluous scripts in the keystore never hurts.
# 82 : : // They're only used to guide recursion in signing and IsMine logic - if
# 83 : : // a script is present but we can't do anything with it, it has no effect.
# 84 : : // "Implicitly" refers to fact that scripts are derived automatically from
# 85 : : // existing keys, and are present in memory, even without being explicitly
# 86 : : // loaded (e.g. from a file).
# 87 [ + + ]: 39447 : if (pubkey.IsCompressed()) {
# 88 : 37414 : CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id));
# 89 : : // This does not use AddCScript, as it may be overridden.
# 90 : 37414 : CScriptID id(script);
# 91 : 37414 : mapScripts[id] = std::move(script);
# 92 : 37414 : }
# 93 : 39447 : }
# 94 : :
# 95 : : bool FillableSigningProvider::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
# 96 : 1246979 : {
# 97 : 1246979 : CKey key;
# 98 [ + + ]: 1246979 : if (!GetKey(address, key)) {
# 99 : 33960 : return false;
# 100 : 33960 : }
# 101 : 1213019 : vchPubKeyOut = key.GetPubKey();
# 102 : 1213019 : return true;
# 103 : 1213019 : }
# 104 : :
# 105 : : bool FillableSigningProvider::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
# 106 : 38170 : {
# 107 : 38170 : LOCK(cs_KeyStore);
# 108 : 38170 : mapKeys[pubkey.GetID()] = key;
# 109 : 38170 : ImplicitlyLearnRelatedKeyScripts(pubkey);
# 110 : 38170 : return true;
# 111 : 38170 : }
# 112 : :
# 113 : : bool FillableSigningProvider::HaveKey(const CKeyID &address) const
# 114 : 1171676 : {
# 115 : 1171676 : LOCK(cs_KeyStore);
# 116 : 1171676 : return mapKeys.count(address) > 0;
# 117 : 1171676 : }
# 118 : :
# 119 : : std::set<CKeyID> FillableSigningProvider::GetKeys() const
# 120 : 5 : {
# 121 : 5 : LOCK(cs_KeyStore);
# 122 : 5 : std::set<CKeyID> set_address;
# 123 [ + + ]: 858 : for (const auto& mi : mapKeys) {
# 124 : 858 : set_address.insert(mi.first);
# 125 : 858 : }
# 126 : 5 : return set_address;
# 127 : 5 : }
# 128 : :
# 129 : : bool FillableSigningProvider::GetKey(const CKeyID &address, CKey &keyOut) const
# 130 : 1305240 : {
# 131 : 1305240 : LOCK(cs_KeyStore);
# 132 : 1305240 : KeyMap::const_iterator mi = mapKeys.find(address);
# 133 [ + + ]: 1305240 : if (mi != mapKeys.end()) {
# 134 : 1271015 : keyOut = mi->second;
# 135 : 1271015 : return true;
# 136 : 1271015 : }
# 137 : 34225 : return false;
# 138 : 34225 : }
# 139 : :
# 140 : : bool FillableSigningProvider::AddCScript(const CScript& redeemScript)
# 141 : 24099 : {
# 142 [ - + ]: 24099 : if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
# 143 : 0 : return error("FillableSigningProvider::AddCScript(): redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
# 144 : :
# 145 : 24099 : LOCK(cs_KeyStore);
# 146 : 24099 : mapScripts[CScriptID(redeemScript)] = redeemScript;
# 147 : 24099 : return true;
# 148 : 24099 : }
# 149 : :
# 150 : : bool FillableSigningProvider::HaveCScript(const CScriptID& hash) const
# 151 : 808069 : {
# 152 : 808069 : LOCK(cs_KeyStore);
# 153 : 808069 : return mapScripts.count(hash) > 0;
# 154 : 808069 : }
# 155 : :
# 156 : : std::set<CScriptID> FillableSigningProvider::GetCScripts() const
# 157 : 6 : {
# 158 : 6 : LOCK(cs_KeyStore);
# 159 : 6 : std::set<CScriptID> set_script;
# 160 [ + + ]: 1252 : for (const auto& mi : mapScripts) {
# 161 : 1252 : set_script.insert(mi.first);
# 162 : 1252 : }
# 163 : 6 : return set_script;
# 164 : 6 : }
# 165 : :
# 166 : : bool FillableSigningProvider::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
# 167 : 156818 : {
# 168 : 156818 : LOCK(cs_KeyStore);
# 169 : 156818 : ScriptMap::const_iterator mi = mapScripts.find(hash);
# 170 [ + + ]: 156818 : if (mi != mapScripts.end())
# 171 : 43445 : {
# 172 : 43445 : redeemScriptOut = (*mi).second;
# 173 : 43445 : return true;
# 174 : 43445 : }
# 175 : 113373 : return false;
# 176 : 113373 : }
# 177 : :
# 178 : : CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination& dest)
# 179 : 1452 : {
# 180 : : // Only supports destinations which map to single public keys, i.e. P2PKH,
# 181 : : // P2WPKH, and P2SH-P2WPKH.
# 182 [ + + ]: 1452 : if (auto id = std::get_if<PKHash>(&dest)) {
# 183 : 378 : return ToKeyID(*id);
# 184 : 378 : }
# 185 [ + + ]: 1074 : if (auto witness_id = std::get_if<WitnessV0KeyHash>(&dest)) {
# 186 : 654 : return ToKeyID(*witness_id);
# 187 : 654 : }
# 188 [ + + ]: 420 : if (auto script_hash = std::get_if<ScriptHash>(&dest)) {
# 189 : 377 : CScript script;
# 190 : 377 : CScriptID script_id(*script_hash);
# 191 : 377 : CTxDestination inner_dest;
# 192 [ + + ][ + + ]: 377 : if (store.GetCScript(script_id, script) && ExtractDestination(script, inner_dest)) {
# 193 [ + + ]: 322 : if (auto inner_witness_id = std::get_if<WitnessV0KeyHash>(&inner_dest)) {
# 194 : 287 : return ToKeyID(*inner_witness_id);
# 195 : 287 : }
# 196 : 133 : }
# 197 : 377 : }
# 198 : 133 : return CKeyID();
# 199 : 133 : }
|