Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2014 The Bitcoin developers 3 : // Copyright (c) 2017-2021 The PIVX Core developers 4 : // Distributed under the MIT software license, see the accompanying 5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 6 : 7 : #include "keystore.h" 8 : 9 : #include "script/script.h" 10 : #include "script/standard.h" 11 : #include "util/system.h" 12 : 13 : 14 176 : bool CKeyStore::AddKey(const CKey& key) 15 : { 16 176 : return AddKeyPubKey(key, key.GetPubKey()); 17 : } 18 : 19 3536960 : bool CBasicKeyStore::GetPubKey(const CKeyID& address, CPubKey& vchPubKeyOut) const 20 : { 21 7073920 : CKey key; 22 3536960 : if (!GetKey(address, key)) { 23 30 : WatchKeyMap::const_iterator it = mapWatchKeys.find(address); 24 30 : if (it != mapWatchKeys.end()) { 25 9 : vchPubKeyOut = it->second; 26 9 : return true; 27 : } 28 : return false; 29 : } 30 3536930 : vchPubKeyOut = key.GetPubKey(); 31 : return true; 32 : } 33 : 34 19765 : bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey& pubkey) 35 : { 36 19765 : LOCK(cs_KeyStore); 37 19765 : mapKeys[pubkey.GetID()] = key; 38 39530 : return true; 39 : } 40 : 41 36 : bool CBasicKeyStore::AddCScript(const CScript& redeemScript) 42 : { 43 65 : if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) 44 0 : return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE); 45 : 46 72 : LOCK(cs_KeyStore); 47 36 : mapScripts[CScriptID(redeemScript)] = redeemScript; 48 36 : return true; 49 : } 50 : 51 3 : bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const 52 : { 53 3 : LOCK(cs_KeyStore); 54 6 : return mapScripts.count(hash) > 0; 55 : } 56 : 57 85618 : bool CBasicKeyStore::GetCScript(const CScriptID& hash, CScript& redeemScriptOut) const 58 : { 59 85618 : LOCK(cs_KeyStore); 60 85618 : ScriptMap::const_iterator mi = mapScripts.find(hash); 61 85618 : if (mi != mapScripts.end()) { 62 669 : redeemScriptOut = (*mi).second; 63 669 : return true; 64 : } 65 : return false; 66 : } 67 : 68 53 : static bool ExtractPubKey(const CScript& dest, CPubKey& pubKeyOut) 69 : { 70 : //TODO: Use Solver to extract this? 71 53 : CScript::const_iterator pc = dest.begin(); 72 53 : opcodetype opcode; 73 106 : std::vector<unsigned char> vch; 74 53 : if (!dest.GetOp(pc, opcode, vch) || vch.size() < 33 || vch.size() > 65) 75 : return false; 76 13 : pubKeyOut = CPubKey(vch); 77 13 : if (!pubKeyOut.IsFullyValid()) 78 : return false; 79 26 : if (!dest.GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG || dest.GetOp(pc, opcode, vch)) 80 0 : return false; 81 : return true; 82 : } 83 : 84 52 : bool CBasicKeyStore::AddWatchOnly(const CScript& dest) 85 : { 86 52 : LOCK(cs_KeyStore); 87 52 : setWatchOnly.insert(dest); 88 52 : CPubKey pubKey; 89 52 : if (ExtractPubKey(dest, pubKey)) 90 13 : mapWatchKeys[pubKey.GetID()] = pubKey; 91 104 : return true; 92 : } 93 : 94 1 : bool CBasicKeyStore::RemoveWatchOnly(const CScript& dest) 95 : { 96 1 : LOCK(cs_KeyStore); 97 1 : setWatchOnly.erase(dest); 98 1 : CPubKey pubKey; 99 1 : if (ExtractPubKey(dest, pubKey)) 100 0 : mapWatchKeys.erase(pubKey.GetID()); 101 2 : return true; 102 : } 103 : 104 934503 : bool CBasicKeyStore::HaveWatchOnly(const CScript& dest) const 105 : { 106 934503 : LOCK(cs_KeyStore); 107 1869004 : return setWatchOnly.count(dest) > 0; 108 : } 109 : 110 1 : bool CBasicKeyStore::HaveWatchOnly() const 111 : { 112 1 : LOCK(cs_KeyStore); 113 1 : return (!setWatchOnly.empty()); 114 : } 115 : 116 6966618 : bool CBasicKeyStore::HaveKey(const CKeyID& address) const 117 : { 118 6966618 : bool result; 119 6966618 : { 120 6966618 : LOCK(cs_KeyStore); 121 13933256 : result = (mapKeys.count(address) > 0); 122 : } 123 6966618 : return result; 124 : } 125 : 126 7 : std::set<CKeyID> CBasicKeyStore::GetKeys() const 127 : { 128 7 : LOCK(cs_KeyStore); 129 7 : std::set<CKeyID> set_address; 130 1368 : for (const auto& mi : mapKeys) { 131 1361 : set_address.insert(mi.first); 132 : } 133 14 : return set_address; 134 : } 135 : 136 3765600 : bool CBasicKeyStore::GetKey(const CKeyID& address, CKey& keyOut) const 137 : { 138 7531190 : LOCK(cs_KeyStore); 139 3765600 : KeyMap::const_iterator mi = mapKeys.find(address); 140 3765600 : if (mi != mapKeys.end()) { 141 3765600 : keyOut = mi->second; 142 : return true; 143 : } 144 : return false; 145 : } 146 : 147 : //! Sapling 148 2299 : bool CBasicKeyStore::AddSaplingSpendingKey( 149 : const libzcash::SaplingExtendedSpendingKey& sk) 150 : { 151 4598 : LOCK(cs_KeyStore); 152 2299 : auto extfvk = sk.ToXFVK(); 153 : 154 : // if extfvk is not in SaplingFullViewingKeyMap, add it 155 2299 : if (!AddSaplingFullViewingKey(extfvk)) { 156 : return false; 157 : } 158 : 159 2299 : mapSaplingSpendingKeys[extfvk] = sk; 160 : 161 2299 : return true; 162 : } 163 : 164 2409 : bool CBasicKeyStore::AddSaplingFullViewingKey( 165 : const libzcash::SaplingExtendedFullViewingKey& extfvk) 166 : { 167 2409 : LOCK(cs_KeyStore); 168 2409 : auto ivk = extfvk.fvk.in_viewing_key(); 169 2409 : mapSaplingFullViewingKeys[ivk] = extfvk; 170 : 171 4818 : return CBasicKeyStore::AddSaplingIncomingViewingKey(ivk, extfvk.DefaultAddress()); 172 : } 173 : 174 : // This function updates the wallet's internal address->ivk map. 175 : // If we add an address that is already in the map, the map will 176 : // remain unchanged as each address only has one ivk. 177 2411 : bool CBasicKeyStore::AddSaplingIncomingViewingKey( 178 : const libzcash::SaplingIncomingViewingKey& ivk, 179 : const libzcash::SaplingPaymentAddress& addr) 180 : { 181 2411 : LOCK(cs_KeyStore); 182 : 183 : // Add addr -> SaplingIncomingViewing to SaplingIncomingViewingKeyMap 184 2411 : mapSaplingIncomingViewingKeys[addr] = ivk; 185 : 186 4822 : return true; 187 : } 188 : 189 7993 : bool CBasicKeyStore::HaveSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey& extfvk) const 190 : { 191 23979 : return WITH_LOCK(cs_KeyStore, return mapSaplingSpendingKeys.count(extfvk) > 0); 192 : } 193 : 194 21 : bool CBasicKeyStore::HaveSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey& ivk) const 195 : { 196 63 : return WITH_LOCK(cs_KeyStore, return mapSaplingFullViewingKeys.count(ivk) > 0); 197 : } 198 : 199 12 : bool CBasicKeyStore::HaveSaplingIncomingViewingKey(const libzcash::SaplingPaymentAddress& addr) const 200 : { 201 36 : return WITH_LOCK(cs_KeyStore, return mapSaplingIncomingViewingKeys.count(addr) > 0); 202 : } 203 : 204 1147 : bool CBasicKeyStore::GetSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey& extfvk, libzcash::SaplingExtendedSpendingKey& skOut) const 205 : { 206 1147 : LOCK(cs_KeyStore); 207 1147 : SaplingSpendingKeyMap::const_iterator mi = mapSaplingSpendingKeys.find(extfvk); 208 1147 : if (mi != mapSaplingSpendingKeys.end()) { 209 1144 : skOut = mi->second; 210 1144 : return true; 211 : } 212 : return false; 213 : } 214 : 215 7164 : bool CBasicKeyStore::GetSaplingFullViewingKey( 216 : const libzcash::SaplingIncomingViewingKey& ivk, 217 : libzcash::SaplingExtendedFullViewingKey& extfvkOut) const 218 : { 219 7164 : LOCK(cs_KeyStore); 220 7164 : SaplingFullViewingKeyMap::const_iterator mi = mapSaplingFullViewingKeys.find(ivk); 221 7164 : if (mi != mapSaplingFullViewingKeys.end()) { 222 7162 : extfvkOut = mi->second; 223 7162 : return true; 224 : } 225 : return false; 226 : } 227 : 228 7499 : bool CBasicKeyStore::GetSaplingIncomingViewingKey(const libzcash::SaplingPaymentAddress& addr, 229 : libzcash::SaplingIncomingViewingKey& ivkOut) const 230 : { 231 7499 : LOCK(cs_KeyStore); 232 7499 : SaplingIncomingViewingKeyMap::const_iterator mi = mapSaplingIncomingViewingKeys.find(addr); 233 7499 : if (mi != mapSaplingIncomingViewingKeys.end()) { 234 7491 : ivkOut = mi->second; 235 7491 : return true; 236 : } 237 : return false; 238 : } 239 : 240 1147 : bool CBasicKeyStore::GetSaplingExtendedSpendingKey(const libzcash::SaplingPaymentAddress& addr, 241 : libzcash::SaplingExtendedSpendingKey& extskOut) const 242 : { 243 1147 : libzcash::SaplingIncomingViewingKey ivk; 244 1147 : libzcash::SaplingExtendedFullViewingKey extfvk; 245 : 246 1147 : LOCK(cs_KeyStore); 247 2294 : return GetSaplingIncomingViewingKey(addr, ivk) && 248 2294 : GetSaplingFullViewingKey(ivk, extfvk) && 249 3441 : GetSaplingSpendingKey(extfvk, extskOut); 250 : } 251 : 252 41 : void CBasicKeyStore::GetSaplingPaymentAddresses(std::set<libzcash::SaplingPaymentAddress>& setAddress) const 253 : { 254 41 : setAddress.clear(); 255 41 : { 256 41 : LOCK(cs_KeyStore); 257 41 : auto mi = mapSaplingIncomingViewingKeys.begin(); 258 5731 : while (mi != mapSaplingIncomingViewingKeys.end()) { 259 5690 : setAddress.insert((*mi).first); 260 5731 : mi++; 261 : } 262 : } 263 41 : }