1 // Copyright (c) 2019 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <key_io.h>
6 #include <outputtype.h>
7 #include <script/descriptor.h>
8 #include <script/sign.h>
9 #include <util/bip32.h>
10 #include <util/strencodings.h>
11 #include <util/string.h>
12 #include <util/translation.h>
13 #include <wallet/scriptpubkeyman.h>
14 
GetNewDestination(const OutputType type,CTxDestination & dest,std::string & error)15 bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error)
16 {
17     LOCK(cs_KeyStore);
18     error.clear();
19 
20     // Generate a new key that is added to wallet
21     CPubKey new_key;
22     if (!GetKeyFromPool(new_key, type)) {
23         error = "Error: Keypool ran out, please call keypoolrefill first";
24         return false;
25     }
26     LearnRelatedScripts(new_key, type);
27     dest = GetDestinationForKey(new_key, type);
28     return true;
29 }
30 
31 typedef std::vector<unsigned char> valtype;
32 
33 namespace {
34 
35 /**
36  * This is an enum that tracks the execution context of a script, similar to
37  * SigVersion in script/interpreter. It is separate however because we want to
38  * distinguish between top-level scriptPubKey execution and P2SH redeemScript
39  * execution (a distinction that has no impact on consensus rules).
40  */
41 enum class IsMineSigVersion
42 {
43     TOP = 0,        //!< scriptPubKey execution
44     P2SH = 1,       //!< P2SH redeemScript
45     WITNESS_V0 = 2, //!< P2WSH witness script execution
46 };
47 
48 /**
49  * This is an internal representation of isminetype + invalidity.
50  * Its order is significant, as we return the max of all explored
51  * possibilities.
52  */
53 enum class IsMineResult
54 {
55     NO = 0,         //!< Not ours
56     WATCH_ONLY = 1, //!< Included in watch-only balance
57     SPENDABLE = 2,  //!< Included in all balances
58     INVALID = 3,    //!< Not spendable by anyone (uncompressed pubkey in segwit, P2SH inside P2SH or witness, witness inside witness)
59 };
60 
PermitsUncompressed(IsMineSigVersion sigversion)61 bool PermitsUncompressed(IsMineSigVersion sigversion)
62 {
63     return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH;
64 }
65 
HaveKeys(const std::vector<valtype> & pubkeys,const LegacyScriptPubKeyMan & keystore)66 bool HaveKeys(const std::vector<valtype>& pubkeys, const LegacyScriptPubKeyMan& keystore)
67 {
68     for (const valtype& pubkey : pubkeys) {
69         CKeyID keyID = CPubKey(pubkey).GetID();
70         if (!keystore.HaveKey(keyID)) return false;
71     }
72     return true;
73 }
74 
75 //! Recursively solve script and return spendable/watchonly/invalid status.
76 //!
77 //! @param keystore            legacy key and script store
78 //! @param script              script to solve
79 //! @param sigversion          script type (top-level / redeemscript / witnessscript)
80 //! @param recurse_scripthash  whether to recurse into nested p2sh and p2wsh
81 //!                            scripts or simply treat any script that has been
82 //!                            stored in the keystore as spendable
IsMineInner(const LegacyScriptPubKeyMan & keystore,const CScript & scriptPubKey,IsMineSigVersion sigversion,bool recurse_scripthash=true)83 IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion, bool recurse_scripthash=true)
84 {
85     IsMineResult ret = IsMineResult::NO;
86 
87     std::vector<valtype> vSolutions;
88     txnouttype whichType = Solver(scriptPubKey, vSolutions);
89 
90     CKeyID keyID;
91     switch (whichType)
92     {
93     case TX_NONSTANDARD:
94     case TX_NULL_DATA:
95     case TX_WITNESS_UNKNOWN:
96         break;
97     case TX_PUBKEY:
98         keyID = CPubKey(vSolutions[0]).GetID();
99         if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
100             return IsMineResult::INVALID;
101         }
102         if (keystore.HaveKey(keyID)) {
103             ret = std::max(ret, IsMineResult::SPENDABLE);
104         }
105         break;
106     case TX_WITNESS_V0_KEYHASH:
107     {
108         if (sigversion == IsMineSigVersion::WITNESS_V0) {
109             // P2WPKH inside P2WSH is invalid.
110             return IsMineResult::INVALID;
111         }
112         if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
113             // We do not support bare witness outputs unless the P2SH version of it would be
114             // acceptable as well. This protects against matching before segwit activates.
115             // This also applies to the P2WSH case.
116             break;
117         }
118         ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(PKHash(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
119         break;
120     }
121     case TX_PUBKEYHASH:
122         keyID = CKeyID(uint160(vSolutions[0]));
123         if (!PermitsUncompressed(sigversion)) {
124             CPubKey pubkey;
125             if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
126                 return IsMineResult::INVALID;
127             }
128         }
129         if (keystore.HaveKey(keyID)) {
130             ret = std::max(ret, IsMineResult::SPENDABLE);
131         }
132         break;
133     case TX_SCRIPTHASH:
134     {
135         if (sigversion != IsMineSigVersion::TOP) {
136             // P2SH inside P2WSH or P2SH is invalid.
137             return IsMineResult::INVALID;
138         }
139         CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
140         CScript subscript;
141         if (keystore.GetCScript(scriptID, subscript)) {
142             ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::P2SH) : IsMineResult::SPENDABLE);
143         }
144         break;
145     }
146     case TX_WITNESS_V0_SCRIPTHASH:
147     {
148         if (sigversion == IsMineSigVersion::WITNESS_V0) {
149             // P2WSH inside P2WSH is invalid.
150             return IsMineResult::INVALID;
151         }
152         if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
153             break;
154         }
155         uint160 hash;
156         CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin());
157         CScriptID scriptID = CScriptID(hash);
158         CScript subscript;
159         if (keystore.GetCScript(scriptID, subscript)) {
160             ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0) : IsMineResult::SPENDABLE);
161         }
162         break;
163     }
164 
165     case TX_MULTISIG:
166     {
167         // Never treat bare multisig outputs as ours (they can still be made watchonly-though)
168         if (sigversion == IsMineSigVersion::TOP) {
169             break;
170         }
171 
172         // Only consider transactions "mine" if we own ALL the
173         // keys involved. Multi-signature transactions that are
174         // partially owned (somebody else has a key that can spend
175         // them) enable spend-out-from-under-you attacks, especially
176         // in shared-wallet situations.
177         std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
178         if (!PermitsUncompressed(sigversion)) {
179             for (size_t i = 0; i < keys.size(); i++) {
180                 if (keys[i].size() != 33) {
181                     return IsMineResult::INVALID;
182                 }
183             }
184         }
185         if (HaveKeys(keys, keystore)) {
186             ret = std::max(ret, IsMineResult::SPENDABLE);
187         }
188         break;
189     }
190 
191     default:
192         break;
193     }
194 
195     if (ret == IsMineResult::NO && keystore.HaveWatchOnly(scriptPubKey)) {
196         ret = std::max(ret, IsMineResult::WATCH_ONLY);
197     }
198     return ret;
199 }
200 
201 } // namespace
202 
IsMine(const CScript & script) const203 isminetype LegacyScriptPubKeyMan::IsMine(const CScript& script) const
204 {
205     switch (IsMineInner(*this, script, IsMineSigVersion::TOP)) {
206     case IsMineResult::INVALID:
207     case IsMineResult::NO:
208         return ISMINE_NO;
209     case IsMineResult::WATCH_ONLY:
210         return ISMINE_WATCH_ONLY;
211     case IsMineResult::SPENDABLE:
212         return ISMINE_SPENDABLE;
213     }
214     assert(false);
215 }
216 
CheckDecryptionKey(const CKeyingMaterial & master_key,bool accept_no_keys)217 bool LegacyScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys)
218 {
219     {
220         LOCK(cs_KeyStore);
221         assert(mapKeys.empty());
222 
223         bool keyPass = mapCryptedKeys.empty(); // Always pass when there are no encrypted keys
224         bool keyFail = false;
225         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
226         for (; mi != mapCryptedKeys.end(); ++mi)
227         {
228             const CPubKey &vchPubKey = (*mi).second.first;
229             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
230             CKey key;
231             if (!DecryptKey(master_key, vchCryptedSecret, vchPubKey, key))
232             {
233                 keyFail = true;
234                 break;
235             }
236             keyPass = true;
237             if (fDecryptionThoroughlyChecked)
238                 break;
239         }
240         if (keyPass && keyFail)
241         {
242             LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
243             throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
244         }
245         if (keyFail || (!keyPass && !accept_no_keys))
246             return false;
247         fDecryptionThoroughlyChecked = true;
248     }
249     return true;
250 }
251 
Encrypt(const CKeyingMaterial & master_key,WalletBatch * batch)252 bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch)
253 {
254     LOCK(cs_KeyStore);
255     encrypted_batch = batch;
256     if (!mapCryptedKeys.empty()) {
257         encrypted_batch = nullptr;
258         return false;
259     }
260 
261     KeyMap keys_to_encrypt;
262     keys_to_encrypt.swap(mapKeys); // Clear mapKeys so AddCryptedKeyInner will succeed.
263     for (const KeyMap::value_type& mKey : keys_to_encrypt)
264     {
265         const CKey &key = mKey.second;
266         CPubKey vchPubKey = key.GetPubKey();
267         CKeyingMaterial vchSecret(key.begin(), key.end());
268         std::vector<unsigned char> vchCryptedSecret;
269         if (!EncryptSecret(master_key, vchSecret, vchPubKey.GetHash(), vchCryptedSecret)) {
270             encrypted_batch = nullptr;
271             return false;
272         }
273         if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) {
274             encrypted_batch = nullptr;
275             return false;
276         }
277     }
278     encrypted_batch = nullptr;
279     return true;
280 }
281 
GetReservedDestination(const OutputType type,bool internal,CTxDestination & address,int64_t & index,CKeyPool & keypool)282 bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool)
283 {
284     LOCK(cs_KeyStore);
285     if (!CanGetAddresses(internal)) {
286         return false;
287     }
288 
289     if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
290         return false;
291     }
292     address = GetDestinationForKey(keypool.vchPubKey, type);
293     return true;
294 }
295 
MarkUnusedAddresses(const CScript & script)296 void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
297 {
298     LOCK(cs_KeyStore);
299     // extract addresses and check if they match with an unused keypool key
300     for (const auto& keyid : GetAffectedKeys(script, *this)) {
301         std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
302         if (mi != m_pool_key_to_index.end()) {
303             WalletLogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
304             MarkReserveKeysAsUsed(mi->second);
305 
306             if (!TopUp()) {
307                 WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
308             }
309         }
310     }
311 }
312 
UpgradeKeyMetadata()313 void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
314 {
315     LOCK(cs_KeyStore);
316     if (m_storage.IsLocked() || m_storage.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
317         return;
318     }
319 
320     std::unique_ptr<WalletBatch> batch = MakeUnique<WalletBatch>(m_storage.GetDatabase());
321     for (auto& meta_pair : mapKeyMetadata) {
322         CKeyMetadata& meta = meta_pair.second;
323         if (!meta.hd_seed_id.IsNull() && !meta.has_key_origin && meta.hdKeypath != "s") { // If the hdKeypath is "s", that's the seed and it doesn't have a key origin
324             CKey key;
325             GetKey(meta.hd_seed_id, key);
326             CExtKey masterKey;
327             masterKey.SetSeed(key.begin(), key.size());
328             // Add to map
329             CKeyID master_id = masterKey.key.GetPubKey().GetID();
330             std::copy(master_id.begin(), master_id.begin() + 4, meta.key_origin.fingerprint);
331             if (!ParseHDKeypath(meta.hdKeypath, meta.key_origin.path)) {
332                 throw std::runtime_error("Invalid stored hdKeypath");
333             }
334             meta.has_key_origin = true;
335             if (meta.nVersion < CKeyMetadata::VERSION_WITH_KEY_ORIGIN) {
336                 meta.nVersion = CKeyMetadata::VERSION_WITH_KEY_ORIGIN;
337             }
338 
339             // Write meta to wallet
340             CPubKey pubkey;
341             if (GetPubKey(meta_pair.first, pubkey)) {
342                 batch->WriteKeyMetadata(meta, pubkey, true);
343             }
344         }
345     }
346 }
347 
SetupGeneration(bool force)348 bool LegacyScriptPubKeyMan::SetupGeneration(bool force)
349 {
350     if ((CanGenerateKeys() && !force) || m_storage.IsLocked()) {
351         return false;
352     }
353 
354     SetHDSeed(GenerateNewSeed());
355     if (!NewKeyPool()) {
356         return false;
357     }
358     return true;
359 }
360 
IsHDEnabled() const361 bool LegacyScriptPubKeyMan::IsHDEnabled() const
362 {
363     return !hdChain.seed_id.IsNull();
364 }
365 
CanGetAddresses(bool internal) const366 bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) const
367 {
368     LOCK(cs_KeyStore);
369     // Check if the keypool has keys
370     bool keypool_has_keys;
371     if (internal && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
372         keypool_has_keys = setInternalKeyPool.size() > 0;
373     } else {
374         keypool_has_keys = KeypoolCountExternalKeys() > 0;
375     }
376     // If the keypool doesn't have keys, check if we can generate them
377     if (!keypool_has_keys) {
378         return CanGenerateKeys();
379     }
380     return keypool_has_keys;
381 }
382 
Upgrade(int prev_version,std::string & error)383 bool LegacyScriptPubKeyMan::Upgrade(int prev_version, std::string& error)
384 {
385     LOCK(cs_KeyStore);
386     error = "";
387     bool hd_upgrade = false;
388     bool split_upgrade = false;
389     if (m_storage.CanSupportFeature(FEATURE_HD) && !IsHDEnabled()) {
390         WalletLogPrintf("Upgrading wallet to HD\n");
391         m_storage.SetMinVersion(FEATURE_HD);
392 
393         // generate a new master key
394         CPubKey masterPubKey = GenerateNewSeed();
395         SetHDSeed(masterPubKey);
396         hd_upgrade = true;
397     }
398     // Upgrade to HD chain split if necessary
399     if (m_storage.CanSupportFeature(FEATURE_HD_SPLIT) && CHDChain::VERSION_HD_CHAIN_SPLIT) {
400         WalletLogPrintf("Upgrading wallet to use HD chain split\n");
401         m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
402         split_upgrade = FEATURE_HD_SPLIT > prev_version;
403     }
404     // Mark all keys currently in the keypool as pre-split
405     if (split_upgrade) {
406         MarkPreSplitKeys();
407     }
408     // Regenerate the keypool if upgraded to HD
409     if (hd_upgrade) {
410         if (!TopUp()) {
411             error = _("Unable to generate keys").translated;
412             return false;
413         }
414     }
415     return true;
416 }
417 
HavePrivateKeys() const418 bool LegacyScriptPubKeyMan::HavePrivateKeys() const
419 {
420     LOCK(cs_KeyStore);
421     return !mapKeys.empty() || !mapCryptedKeys.empty();
422 }
423 
RewriteDB()424 void LegacyScriptPubKeyMan::RewriteDB()
425 {
426     LOCK(cs_KeyStore);
427     setInternalKeyPool.clear();
428     setExternalKeyPool.clear();
429     m_pool_key_to_index.clear();
430     // Note: can't top-up keypool here, because wallet is locked.
431     // User will be prompted to unlock wallet the next operation
432     // that requires a new key.
433 }
434 
GetOldestKeyTimeInPool(const std::set<int64_t> & setKeyPool,WalletBatch & batch)435 static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, WalletBatch& batch) {
436     if (setKeyPool.empty()) {
437         return GetTime();
438     }
439 
440     CKeyPool keypool;
441     int64_t nIndex = *(setKeyPool.begin());
442     if (!batch.ReadPool(nIndex, keypool)) {
443         throw std::runtime_error(std::string(__func__) + ": read oldest key in keypool failed");
444     }
445     assert(keypool.vchPubKey.IsValid());
446     return keypool.nTime;
447 }
448 
GetOldestKeyPoolTime() const449 int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime() const
450 {
451     LOCK(cs_KeyStore);
452 
453     WalletBatch batch(m_storage.GetDatabase());
454 
455     // load oldest key from keypool, get time and return
456     int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, batch);
457     if (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
458         oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, batch), oldestKey);
459         if (!set_pre_split_keypool.empty()) {
460             oldestKey = std::max(GetOldestKeyTimeInPool(set_pre_split_keypool, batch), oldestKey);
461         }
462     }
463 
464     return oldestKey;
465 }
466 
KeypoolCountExternalKeys() const467 size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys() const
468 {
469     LOCK(cs_KeyStore);
470     return setExternalKeyPool.size() + set_pre_split_keypool.size();
471 }
472 
GetKeyPoolSize() const473 unsigned int LegacyScriptPubKeyMan::GetKeyPoolSize() const
474 {
475     LOCK(cs_KeyStore);
476     return setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size();
477 }
478 
GetTimeFirstKey() const479 int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
480 {
481     LOCK(cs_KeyStore);
482     return nTimeFirstKey;
483 }
484 
GetSolvingProvider(const CScript & script) const485 std::unique_ptr<SigningProvider> LegacyScriptPubKeyMan::GetSolvingProvider(const CScript& script) const
486 {
487     return MakeUnique<LegacySigningProvider>(*this);
488 }
489 
CanProvide(const CScript & script,SignatureData & sigdata)490 bool LegacyScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sigdata)
491 {
492     IsMineResult ismine = IsMineInner(*this, script, IsMineSigVersion::TOP, /* recurse_scripthash= */ false);
493     if (ismine == IsMineResult::SPENDABLE || ismine == IsMineResult::WATCH_ONLY) {
494         // If ismine, it means we recognize keys or script ids in the script, or
495         // are watching the script itself, and we can at least provide metadata
496         // or solving information, even if not able to sign fully.
497         return true;
498     } else {
499         // If, given the stuff in sigdata, we could make a valid sigature, then we can provide for this script
500         ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, script, sigdata);
501         if (!sigdata.signatures.empty()) {
502             // If we could make signatures, make sure we have a private key to actually make a signature
503             bool has_privkeys = false;
504             for (const auto& key_sig_pair : sigdata.signatures) {
505                 has_privkeys |= HaveKey(key_sig_pair.first);
506             }
507             return has_privkeys;
508         }
509         return false;
510     }
511 }
512 
SignTransaction(CMutableTransaction & tx,const std::map<COutPoint,Coin> & coins,int sighash,std::map<int,std::string> & input_errors) const513 bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
514 {
515     return ::SignTransaction(tx, this, coins, sighash, input_errors);
516 }
517 
SignMessage(const std::string & message,const PKHash & pkhash,std::string & str_sig) const518 SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
519 {
520     CKeyID key_id(pkhash);
521     CKey key;
522     if (!GetKey(key_id, key)) {
523         return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
524     }
525 
526     if (MessageSign(key, message, str_sig)) {
527         return SigningResult::OK;
528     }
529     return SigningResult::SIGNING_FAILED;
530 }
531 
FillPSBT(PartiallySignedTransaction & psbtx,int sighash_type,bool sign,bool bip32derivs) const532 TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs) const
533 {
534     for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
535         const CTxIn& txin = psbtx.tx->vin[i];
536         PSBTInput& input = psbtx.inputs.at(i);
537 
538         if (PSBTInputSigned(input)) {
539             continue;
540         }
541 
542         // Get the Sighash type
543         if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
544             return TransactionError::SIGHASH_MISMATCH;
545         }
546 
547         // Check non_witness_utxo has specified prevout
548         if (input.non_witness_utxo) {
549             if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
550                 return TransactionError::MISSING_INPUTS;
551             }
552         } else if (input.witness_utxo.IsNull()) {
553             // There's no UTXO so we can just skip this now
554             continue;
555         }
556         SignatureData sigdata;
557         input.FillSignatureData(sigdata);
558         SignPSBTInput(HidingSigningProvider(this, !sign, !bip32derivs), psbtx, i, sighash_type);
559     }
560 
561     // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
562     for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
563         UpdatePSBTOutput(HidingSigningProvider(this, true, !bip32derivs), psbtx, i);
564     }
565 
566     return TransactionError::OK;
567 }
568 
GetMetadata(const CTxDestination & dest) const569 const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
570 {
571     LOCK(cs_KeyStore);
572 
573     CKeyID key_id = GetKeyForDestination(*this, dest);
574     if (!key_id.IsNull()) {
575         auto it = mapKeyMetadata.find(key_id);
576         if (it != mapKeyMetadata.end()) {
577             return &it->second;
578         }
579     }
580 
581     CScript scriptPubKey = GetScriptForDestination(dest);
582     auto it = m_script_metadata.find(CScriptID(scriptPubKey));
583     if (it != m_script_metadata.end()) {
584         return &it->second;
585     }
586 
587     return nullptr;
588 }
589 
GetID() const590 uint256 LegacyScriptPubKeyMan::GetID() const
591 {
592     return UINT256_ONE();
593 }
594 
595 /**
596  * Update wallet first key creation time. This should be called whenever keys
597  * are added to the wallet, with the oldest key creation time.
598  */
UpdateTimeFirstKey(int64_t nCreateTime)599 void LegacyScriptPubKeyMan::UpdateTimeFirstKey(int64_t nCreateTime)
600 {
601     AssertLockHeld(cs_KeyStore);
602     if (nCreateTime <= 1) {
603         // Cannot determine birthday information, so set the wallet birthday to
604         // the beginning of time.
605         nTimeFirstKey = 1;
606     } else if (!nTimeFirstKey || nCreateTime < nTimeFirstKey) {
607         nTimeFirstKey = nCreateTime;
608     }
609 }
610 
LoadKey(const CKey & key,const CPubKey & pubkey)611 bool LegacyScriptPubKeyMan::LoadKey(const CKey& key, const CPubKey &pubkey)
612 {
613     return AddKeyPubKeyInner(key, pubkey);
614 }
615 
AddKeyPubKey(const CKey & secret,const CPubKey & pubkey)616 bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
617 {
618     LOCK(cs_KeyStore);
619     WalletBatch batch(m_storage.GetDatabase());
620     return LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(batch, secret, pubkey);
621 }
622 
AddKeyPubKeyWithDB(WalletBatch & batch,const CKey & secret,const CPubKey & pubkey)623 bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& secret, const CPubKey& pubkey)
624 {
625     AssertLockHeld(cs_KeyStore);
626 
627     // Make sure we aren't adding private keys to private key disabled wallets
628     assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
629 
630     // FillableSigningProvider has no concept of wallet databases, but calls AddCryptedKey
631     // which is overridden below.  To avoid flushes, the database handle is
632     // tunneled through to it.
633     bool needsDB = !encrypted_batch;
634     if (needsDB) {
635         encrypted_batch = &batch;
636     }
637     if (!AddKeyPubKeyInner(secret, pubkey)) {
638         if (needsDB) encrypted_batch = nullptr;
639         return false;
640     }
641     if (needsDB) encrypted_batch = nullptr;
642 
643     // check if we need to remove from watch-only
644     CScript script;
645     script = GetScriptForDestination(PKHash(pubkey));
646     if (HaveWatchOnly(script)) {
647         RemoveWatchOnly(script);
648     }
649     script = GetScriptForRawPubKey(pubkey);
650     if (HaveWatchOnly(script)) {
651         RemoveWatchOnly(script);
652     }
653 
654     if (!m_storage.HasEncryptionKeys()) {
655         return batch.WriteKey(pubkey,
656                                                  secret.GetPrivKey(),
657                                                  mapKeyMetadata[pubkey.GetID()]);
658     }
659     m_storage.UnsetBlankWalletFlag(batch);
660     return true;
661 }
662 
LoadCScript(const CScript & redeemScript)663 bool LegacyScriptPubKeyMan::LoadCScript(const CScript& redeemScript)
664 {
665     /* A sanity check was added in pull #3843 to avoid adding redeemScripts
666      * that never can be redeemed. However, old wallets may still contain
667      * these. Do not add them to the wallet and warn. */
668     if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
669     {
670         std::string strAddr = EncodeDestination(ScriptHash(redeemScript));
671         WalletLogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
672         return true;
673     }
674 
675     return FillableSigningProvider::AddCScript(redeemScript);
676 }
677 
LoadKeyMetadata(const CKeyID & keyID,const CKeyMetadata & meta)678 void LegacyScriptPubKeyMan::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata& meta)
679 {
680     LOCK(cs_KeyStore);
681     UpdateTimeFirstKey(meta.nCreateTime);
682     mapKeyMetadata[keyID] = meta;
683 }
684 
LoadScriptMetadata(const CScriptID & script_id,const CKeyMetadata & meta)685 void LegacyScriptPubKeyMan::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata& meta)
686 {
687     LOCK(cs_KeyStore);
688     UpdateTimeFirstKey(meta.nCreateTime);
689     m_script_metadata[script_id] = meta;
690 }
691 
AddKeyPubKeyInner(const CKey & key,const CPubKey & pubkey)692 bool LegacyScriptPubKeyMan::AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey)
693 {
694     LOCK(cs_KeyStore);
695     if (!m_storage.HasEncryptionKeys()) {
696         return FillableSigningProvider::AddKeyPubKey(key, pubkey);
697     }
698 
699     if (m_storage.IsLocked()) {
700         return false;
701     }
702 
703     std::vector<unsigned char> vchCryptedSecret;
704     CKeyingMaterial vchSecret(key.begin(), key.end());
705     if (!EncryptSecret(m_storage.GetEncryptionKey(), vchSecret, pubkey.GetHash(), vchCryptedSecret)) {
706         return false;
707     }
708 
709     if (!AddCryptedKey(pubkey, vchCryptedSecret)) {
710         return false;
711     }
712     return true;
713 }
714 
LoadCryptedKey(const CPubKey & vchPubKey,const std::vector<unsigned char> & vchCryptedSecret)715 bool LegacyScriptPubKeyMan::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
716 {
717     return AddCryptedKeyInner(vchPubKey, vchCryptedSecret);
718 }
719 
AddCryptedKeyInner(const CPubKey & vchPubKey,const std::vector<unsigned char> & vchCryptedSecret)720 bool LegacyScriptPubKeyMan::AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
721 {
722     LOCK(cs_KeyStore);
723     assert(mapKeys.empty());
724 
725     mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
726     ImplicitlyLearnRelatedKeyScripts(vchPubKey);
727     return true;
728 }
729 
AddCryptedKey(const CPubKey & vchPubKey,const std::vector<unsigned char> & vchCryptedSecret)730 bool LegacyScriptPubKeyMan::AddCryptedKey(const CPubKey &vchPubKey,
731                             const std::vector<unsigned char> &vchCryptedSecret)
732 {
733     if (!AddCryptedKeyInner(vchPubKey, vchCryptedSecret))
734         return false;
735     {
736         LOCK(cs_KeyStore);
737         if (encrypted_batch)
738             return encrypted_batch->WriteCryptedKey(vchPubKey,
739                                                         vchCryptedSecret,
740                                                         mapKeyMetadata[vchPubKey.GetID()]);
741         else
742             return WalletBatch(m_storage.GetDatabase()).WriteCryptedKey(vchPubKey,
743                                                             vchCryptedSecret,
744                                                             mapKeyMetadata[vchPubKey.GetID()]);
745     }
746 }
747 
HaveWatchOnly(const CScript & dest) const748 bool LegacyScriptPubKeyMan::HaveWatchOnly(const CScript &dest) const
749 {
750     LOCK(cs_KeyStore);
751     return setWatchOnly.count(dest) > 0;
752 }
753 
HaveWatchOnly() const754 bool LegacyScriptPubKeyMan::HaveWatchOnly() const
755 {
756     LOCK(cs_KeyStore);
757     return (!setWatchOnly.empty());
758 }
759 
ExtractPubKey(const CScript & dest,CPubKey & pubKeyOut)760 static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
761 {
762     std::vector<std::vector<unsigned char>> solutions;
763     return Solver(dest, solutions) == TX_PUBKEY &&
764         (pubKeyOut = CPubKey(solutions[0])).IsFullyValid();
765 }
766 
RemoveWatchOnly(const CScript & dest)767 bool LegacyScriptPubKeyMan::RemoveWatchOnly(const CScript &dest)
768 {
769     {
770         LOCK(cs_KeyStore);
771         setWatchOnly.erase(dest);
772         CPubKey pubKey;
773         if (ExtractPubKey(dest, pubKey)) {
774             mapWatchKeys.erase(pubKey.GetID());
775         }
776         // Related CScripts are not removed; having superfluous scripts around is
777         // harmless (see comment in ImplicitlyLearnRelatedKeyScripts).
778     }
779 
780     if (!HaveWatchOnly())
781         NotifyWatchonlyChanged(false);
782     if (!WalletBatch(m_storage.GetDatabase()).EraseWatchOnly(dest))
783         return false;
784 
785     return true;
786 }
787 
LoadWatchOnly(const CScript & dest)788 bool LegacyScriptPubKeyMan::LoadWatchOnly(const CScript &dest)
789 {
790     return AddWatchOnlyInMem(dest);
791 }
792 
AddWatchOnlyInMem(const CScript & dest)793 bool LegacyScriptPubKeyMan::AddWatchOnlyInMem(const CScript &dest)
794 {
795     LOCK(cs_KeyStore);
796     setWatchOnly.insert(dest);
797     CPubKey pubKey;
798     if (ExtractPubKey(dest, pubKey)) {
799         mapWatchKeys[pubKey.GetID()] = pubKey;
800         ImplicitlyLearnRelatedKeyScripts(pubKey);
801     }
802     return true;
803 }
804 
AddWatchOnlyWithDB(WalletBatch & batch,const CScript & dest)805 bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest)
806 {
807     if (!AddWatchOnlyInMem(dest))
808         return false;
809     const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
810     UpdateTimeFirstKey(meta.nCreateTime);
811     NotifyWatchonlyChanged(true);
812     if (batch.WriteWatchOnly(dest, meta)) {
813         m_storage.UnsetBlankWalletFlag(batch);
814         return true;
815     }
816     return false;
817 }
818 
AddWatchOnlyWithDB(WalletBatch & batch,const CScript & dest,int64_t create_time)819 bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest, int64_t create_time)
820 {
821     m_script_metadata[CScriptID(dest)].nCreateTime = create_time;
822     return AddWatchOnlyWithDB(batch, dest);
823 }
824 
AddWatchOnly(const CScript & dest)825 bool LegacyScriptPubKeyMan::AddWatchOnly(const CScript& dest)
826 {
827     WalletBatch batch(m_storage.GetDatabase());
828     return AddWatchOnlyWithDB(batch, dest);
829 }
830 
AddWatchOnly(const CScript & dest,int64_t nCreateTime)831 bool LegacyScriptPubKeyMan::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
832 {
833     m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime;
834     return AddWatchOnly(dest);
835 }
836 
SetHDChain(const CHDChain & chain,bool memonly)837 void LegacyScriptPubKeyMan::SetHDChain(const CHDChain& chain, bool memonly)
838 {
839     LOCK(cs_KeyStore);
840     if (!memonly && !WalletBatch(m_storage.GetDatabase()).WriteHDChain(chain))
841         throw std::runtime_error(std::string(__func__) + ": writing chain failed");
842 
843     hdChain = chain;
844 }
845 
HaveKey(const CKeyID & address) const846 bool LegacyScriptPubKeyMan::HaveKey(const CKeyID &address) const
847 {
848     LOCK(cs_KeyStore);
849     if (!m_storage.HasEncryptionKeys()) {
850         return FillableSigningProvider::HaveKey(address);
851     }
852     return mapCryptedKeys.count(address) > 0;
853 }
854 
GetKey(const CKeyID & address,CKey & keyOut) const855 bool LegacyScriptPubKeyMan::GetKey(const CKeyID &address, CKey& keyOut) const
856 {
857     LOCK(cs_KeyStore);
858     if (!m_storage.HasEncryptionKeys()) {
859         return FillableSigningProvider::GetKey(address, keyOut);
860     }
861 
862     CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
863     if (mi != mapCryptedKeys.end())
864     {
865         const CPubKey &vchPubKey = (*mi).second.first;
866         const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
867         return DecryptKey(m_storage.GetEncryptionKey(), vchCryptedSecret, vchPubKey, keyOut);
868     }
869     return false;
870 }
871 
GetKeyOrigin(const CKeyID & keyID,KeyOriginInfo & info) const872 bool LegacyScriptPubKeyMan::GetKeyOrigin(const CKeyID& keyID, KeyOriginInfo& info) const
873 {
874     CKeyMetadata meta;
875     {
876         LOCK(cs_KeyStore);
877         auto it = mapKeyMetadata.find(keyID);
878         if (it != mapKeyMetadata.end()) {
879             meta = it->second;
880         }
881     }
882     if (meta.has_key_origin) {
883         std::copy(meta.key_origin.fingerprint, meta.key_origin.fingerprint + 4, info.fingerprint);
884         info.path = meta.key_origin.path;
885     } else { // Single pubkeys get the master fingerprint of themselves
886         std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint);
887     }
888     return true;
889 }
890 
GetWatchPubKey(const CKeyID & address,CPubKey & pubkey_out) const891 bool LegacyScriptPubKeyMan::GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
892 {
893     LOCK(cs_KeyStore);
894     WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
895     if (it != mapWatchKeys.end()) {
896         pubkey_out = it->second;
897         return true;
898     }
899     return false;
900 }
901 
GetPubKey(const CKeyID & address,CPubKey & vchPubKeyOut) const902 bool LegacyScriptPubKeyMan::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
903 {
904     LOCK(cs_KeyStore);
905     if (!m_storage.HasEncryptionKeys()) {
906         if (!FillableSigningProvider::GetPubKey(address, vchPubKeyOut)) {
907             return GetWatchPubKey(address, vchPubKeyOut);
908         }
909         return true;
910     }
911 
912     CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
913     if (mi != mapCryptedKeys.end())
914     {
915         vchPubKeyOut = (*mi).second.first;
916         return true;
917     }
918     // Check for watch-only pubkeys
919     return GetWatchPubKey(address, vchPubKeyOut);
920 }
921 
GenerateNewKey(WalletBatch & batch,bool internal)922 CPubKey LegacyScriptPubKeyMan::GenerateNewKey(WalletBatch &batch, bool internal)
923 {
924     assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
925     assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
926     AssertLockHeld(cs_KeyStore);
927     bool fCompressed = m_storage.CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
928 
929     CKey secret;
930 
931     // Create new metadata
932     int64_t nCreationTime = GetTime();
933     CKeyMetadata metadata(nCreationTime);
934 
935     // use HD key derivation if HD was enabled during wallet creation and a seed is present
936     if (IsHDEnabled()) {
937         DeriveNewChildKey(batch, metadata, secret, (m_storage.CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
938     } else {
939         secret.MakeNewKey(fCompressed);
940     }
941 
942     // Compressed public keys were introduced in version 0.6.0
943     if (fCompressed) {
944         m_storage.SetMinVersion(FEATURE_COMPRPUBKEY);
945     }
946 
947     CPubKey pubkey = secret.GetPubKey();
948     assert(secret.VerifyPubKey(pubkey));
949 
950     mapKeyMetadata[pubkey.GetID()] = metadata;
951     UpdateTimeFirstKey(nCreationTime);
952 
953     if (!AddKeyPubKeyWithDB(batch, secret, pubkey)) {
954         throw std::runtime_error(std::string(__func__) + ": AddKey failed");
955     }
956     return pubkey;
957 }
958 
959 const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
960 
DeriveNewChildKey(WalletBatch & batch,CKeyMetadata & metadata,CKey & secret,bool internal)961 void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal)
962 {
963     // for now we use a fixed keypath scheme of m/88'/0'/k
964     CKey seed;                     //seed (256bit)
965     CExtKey masterKey;             //hd master key
966     CExtKey accountKey;            //key at m/88'
967     CExtKey chainChildKey;         //key at m/88'/0' (external) or m/88'/1' (internal)
968     CExtKey childKey;              //key at m/88'/0'/<n>'
969 
970     // try to get the seed
971     if (!GetKey(hdChain.seed_id, seed))
972         throw std::runtime_error(std::string(__func__) + ": seed not found");
973 
974     masterKey.SetSeed(seed.begin(), seed.size());
975 
976     // derive m/0'
977     // use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
978     masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT);
979 
980     // derive m/0'/0' (external chain) OR m/88'/1' (internal chain)
981     assert(internal ? m_storage.CanSupportFeature(FEATURE_HD_SPLIT) : true);
982     accountKey.Derive(chainChildKey, BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0));
983 
984     // derive child key at next index, skip keys already known to the wallet
985     do {
986         // always derive hardened keys
987         // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
988         // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
989         if (internal) {
990             chainChildKey.Derive(childKey, hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
991             metadata.hdKeypath = "m/88'/1'/" + ToString(hdChain.nInternalChainCounter) + "'";
992             metadata.key_origin.path.push_back(88 | BIP32_HARDENED_KEY_LIMIT);
993             metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT);
994             metadata.key_origin.path.push_back(hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
995             hdChain.nInternalChainCounter++;
996         }
997         else {
998             chainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
999             metadata.hdKeypath = "m/88'/0'/" + ToString(hdChain.nExternalChainCounter) + "'";
1000             metadata.key_origin.path.push_back(88 | BIP32_HARDENED_KEY_LIMIT);
1001             metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
1002             metadata.key_origin.path.push_back(hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
1003             hdChain.nExternalChainCounter++;
1004         }
1005     } while (HaveKey(childKey.key.GetPubKey().GetID()));
1006     secret = childKey.key;
1007     metadata.hd_seed_id = hdChain.seed_id;
1008     CKeyID master_id = masterKey.key.GetPubKey().GetID();
1009     std::copy(master_id.begin(), master_id.begin() + 4, metadata.key_origin.fingerprint);
1010     metadata.has_key_origin = true;
1011     // update the chain model in the database
1012     if (!batch.WriteHDChain(hdChain))
1013         throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed");
1014 }
1015 
LoadKeyPool(int64_t nIndex,const CKeyPool & keypool)1016 void LegacyScriptPubKeyMan::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
1017 {
1018     LOCK(cs_KeyStore);
1019     if (keypool.m_pre_split) {
1020         set_pre_split_keypool.insert(nIndex);
1021     } else if (keypool.fInternal) {
1022         setInternalKeyPool.insert(nIndex);
1023     } else {
1024         setExternalKeyPool.insert(nIndex);
1025     }
1026     m_max_keypool_index = std::max(m_max_keypool_index, nIndex);
1027     m_pool_key_to_index[keypool.vchPubKey.GetID()] = nIndex;
1028 
1029     // If no metadata exists yet, create a default with the pool key's
1030     // creation time. Note that this may be overwritten by actually
1031     // stored metadata for that key later, which is fine.
1032     CKeyID keyid = keypool.vchPubKey.GetID();
1033     if (mapKeyMetadata.count(keyid) == 0)
1034         mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
1035 }
1036 
CanGenerateKeys() const1037 bool LegacyScriptPubKeyMan::CanGenerateKeys() const
1038 {
1039     // A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a non-HD wallet (pre FEATURE_HD)
1040     LOCK(cs_KeyStore);
1041     return IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD);
1042 }
1043 
GenerateNewSeed()1044 CPubKey LegacyScriptPubKeyMan::GenerateNewSeed()
1045 {
1046     assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
1047     CKey key;
1048     key.MakeNewKey(true);
1049     return DeriveNewSeed(key);
1050 }
1051 
DeriveNewSeed(const CKey & key)1052 CPubKey LegacyScriptPubKeyMan::DeriveNewSeed(const CKey& key)
1053 {
1054     int64_t nCreationTime = GetTime();
1055     CKeyMetadata metadata(nCreationTime);
1056 
1057     // calculate the seed
1058     CPubKey seed = key.GetPubKey();
1059     assert(key.VerifyPubKey(seed));
1060 
1061     // set the hd keypath to "s" -> Seed, refers the seed to itself
1062     metadata.hdKeypath     = "s";
1063     metadata.has_key_origin = false;
1064     metadata.hd_seed_id = seed.GetID();
1065 
1066     {
1067         LOCK(cs_KeyStore);
1068 
1069         // mem store the metadata
1070         mapKeyMetadata[seed.GetID()] = metadata;
1071 
1072         // write the key&metadata to the database
1073         if (!AddKeyPubKey(key, seed))
1074             throw std::runtime_error(std::string(__func__) + ": AddKeyPubKey failed");
1075     }
1076 
1077     return seed;
1078 }
1079 
SetHDSeed(const CPubKey & seed)1080 void LegacyScriptPubKeyMan::SetHDSeed(const CPubKey& seed)
1081 {
1082     LOCK(cs_KeyStore);
1083     // store the keyid (hash160) together with
1084     // the child index counter in the database
1085     // as a hdchain object
1086     CHDChain newHdChain;
1087     newHdChain.nVersion = m_storage.CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
1088     newHdChain.seed_id = seed.GetID();
1089     SetHDChain(newHdChain, false);
1090     NotifyCanGetAddressesChanged();
1091     WalletBatch batch(m_storage.GetDatabase());
1092     m_storage.UnsetBlankWalletFlag(batch);
1093 }
1094 
1095 /**
1096  * Mark old keypool keys as used,
1097  * and generate all new keys
1098  */
NewKeyPool()1099 bool LegacyScriptPubKeyMan::NewKeyPool()
1100 {
1101     if (m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1102         return false;
1103     }
1104     {
1105         LOCK(cs_KeyStore);
1106         WalletBatch batch(m_storage.GetDatabase());
1107 
1108         for (const int64_t nIndex : setInternalKeyPool) {
1109             batch.ErasePool(nIndex);
1110         }
1111         setInternalKeyPool.clear();
1112 
1113         for (const int64_t nIndex : setExternalKeyPool) {
1114             batch.ErasePool(nIndex);
1115         }
1116         setExternalKeyPool.clear();
1117 
1118         for (const int64_t nIndex : set_pre_split_keypool) {
1119             batch.ErasePool(nIndex);
1120         }
1121         set_pre_split_keypool.clear();
1122 
1123         m_pool_key_to_index.clear();
1124 
1125         if (!TopUp()) {
1126             return false;
1127         }
1128         WalletLogPrintf("LegacyScriptPubKeyMan::NewKeyPool rewrote keypool\n");
1129     }
1130     return true;
1131 }
1132 
TopUp(unsigned int kpSize)1133 bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize)
1134 {
1135     if (!CanGenerateKeys()) {
1136         return false;
1137     }
1138     {
1139         LOCK(cs_KeyStore);
1140 
1141         if (m_storage.IsLocked()) return false;
1142 
1143         // Top up key pool
1144         unsigned int nTargetSize;
1145         if (kpSize > 0)
1146             nTargetSize = kpSize;
1147         else
1148             nTargetSize = std::max(gArgs.GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 0);
1149 
1150         // count amount of available keys (internal, external)
1151         // make sure the keypool of external and internal keys fits the user selected target (-keypool)
1152         int64_t missingExternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setExternalKeyPool.size(), (int64_t) 0);
1153         int64_t missingInternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setInternalKeyPool.size(), (int64_t) 0);
1154 
1155         if (!IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD_SPLIT))
1156         {
1157             // don't create extra internal keys
1158             missingInternal = 0;
1159         }
1160         bool internal = false;
1161         WalletBatch batch(m_storage.GetDatabase());
1162         for (int64_t i = missingInternal + missingExternal; i--;)
1163         {
1164             if (i < missingInternal) {
1165                 internal = true;
1166             }
1167 
1168             CPubKey pubkey(GenerateNewKey(batch, internal));
1169             AddKeypoolPubkeyWithDB(pubkey, internal, batch);
1170         }
1171         if (missingInternal + missingExternal > 0) {
1172             WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size());
1173         }
1174     }
1175     NotifyCanGetAddressesChanged();
1176     return true;
1177 }
1178 
AddKeypoolPubkeyWithDB(const CPubKey & pubkey,const bool internal,WalletBatch & batch)1179 void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch)
1180 {
1181     LOCK(cs_KeyStore);
1182     assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys?
1183     int64_t index = ++m_max_keypool_index;
1184     if (!batch.WritePool(index, CKeyPool(pubkey, internal))) {
1185         throw std::runtime_error(std::string(__func__) + ": writing imported pubkey failed");
1186     }
1187     if (internal) {
1188         setInternalKeyPool.insert(index);
1189     } else {
1190         setExternalKeyPool.insert(index);
1191     }
1192     m_pool_key_to_index[pubkey.GetID()] = index;
1193 }
1194 
KeepDestination(int64_t nIndex,const OutputType & type)1195 void LegacyScriptPubKeyMan::KeepDestination(int64_t nIndex, const OutputType& type)
1196 {
1197     // Remove from key pool
1198     WalletBatch batch(m_storage.GetDatabase());
1199     batch.ErasePool(nIndex);
1200     CPubKey pubkey;
1201     bool have_pk = GetPubKey(m_index_to_reserved_key.at(nIndex), pubkey);
1202     assert(have_pk);
1203     LearnRelatedScripts(pubkey, type);
1204     m_index_to_reserved_key.erase(nIndex);
1205     WalletLogPrintf("keypool keep %d\n", nIndex);
1206 }
1207 
ReturnDestination(int64_t nIndex,bool fInternal,const CTxDestination &)1208 void LegacyScriptPubKeyMan::ReturnDestination(int64_t nIndex, bool fInternal, const CTxDestination&)
1209 {
1210     // Return to key pool
1211     {
1212         LOCK(cs_KeyStore);
1213         if (fInternal) {
1214             setInternalKeyPool.insert(nIndex);
1215         } else if (!set_pre_split_keypool.empty()) {
1216             set_pre_split_keypool.insert(nIndex);
1217         } else {
1218             setExternalKeyPool.insert(nIndex);
1219         }
1220         CKeyID& pubkey_id = m_index_to_reserved_key.at(nIndex);
1221         m_pool_key_to_index[pubkey_id] = nIndex;
1222         m_index_to_reserved_key.erase(nIndex);
1223         NotifyCanGetAddressesChanged();
1224     }
1225     WalletLogPrintf("keypool return %d\n", nIndex);
1226 }
1227 
GetKeyFromPool(CPubKey & result,const OutputType type,bool internal)1228 bool LegacyScriptPubKeyMan::GetKeyFromPool(CPubKey& result, const OutputType type, bool internal)
1229 {
1230     if (!CanGetAddresses(internal)) {
1231         return false;
1232     }
1233 
1234     CKeyPool keypool;
1235     {
1236         LOCK(cs_KeyStore);
1237         int64_t nIndex;
1238         if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) && !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1239             if (m_storage.IsLocked()) return false;
1240             WalletBatch batch(m_storage.GetDatabase());
1241             result = GenerateNewKey(batch, internal);
1242             return true;
1243         }
1244         KeepDestination(nIndex, type);
1245         result = keypool.vchPubKey;
1246     }
1247     return true;
1248 }
1249 
ReserveKeyFromKeyPool(int64_t & nIndex,CKeyPool & keypool,bool fRequestedInternal)1250 bool LegacyScriptPubKeyMan::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
1251 {
1252     nIndex = -1;
1253     keypool.vchPubKey = CPubKey();
1254     {
1255         LOCK(cs_KeyStore);
1256 
1257         bool fReturningInternal = fRequestedInternal;
1258         fReturningInternal &= (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) || m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
1259         bool use_split_keypool = set_pre_split_keypool.empty();
1260         std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
1261 
1262         // Get the oldest key
1263         if (setKeyPool.empty()) {
1264             return false;
1265         }
1266 
1267         WalletBatch batch(m_storage.GetDatabase());
1268 
1269         auto it = setKeyPool.begin();
1270         nIndex = *it;
1271         setKeyPool.erase(it);
1272         if (!batch.ReadPool(nIndex, keypool)) {
1273             throw std::runtime_error(std::string(__func__) + ": read failed");
1274         }
1275         CPubKey pk;
1276         if (!GetPubKey(keypool.vchPubKey.GetID(), pk)) {
1277             throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
1278         }
1279         // If the key was pre-split keypool, we don't care about what type it is
1280         if (use_split_keypool && keypool.fInternal != fReturningInternal) {
1281             throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified");
1282         }
1283         if (!keypool.vchPubKey.IsValid()) {
1284             throw std::runtime_error(std::string(__func__) + ": keypool entry invalid");
1285         }
1286 
1287         assert(m_index_to_reserved_key.count(nIndex) == 0);
1288         m_index_to_reserved_key[nIndex] = keypool.vchPubKey.GetID();
1289         m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
1290         WalletLogPrintf("keypool reserve %d\n", nIndex);
1291     }
1292     NotifyCanGetAddressesChanged();
1293     return true;
1294 }
1295 
LearnRelatedScripts(const CPubKey & key,OutputType type)1296 void LegacyScriptPubKeyMan::LearnRelatedScripts(const CPubKey& key, OutputType type)
1297 {
1298     if (key.IsCompressed() && (type == OutputType::P2SH_SEGWIT || type == OutputType::BECH32)) {
1299         CTxDestination witdest = WitnessV0KeyHash(key.GetID());
1300         CScript witprog = GetScriptForDestination(witdest);
1301         // Make sure the resulting program is solvable.
1302         assert(IsSolvable(*this, witprog));
1303         AddCScript(witprog);
1304     }
1305 }
1306 
LearnAllRelatedScripts(const CPubKey & key)1307 void LegacyScriptPubKeyMan::LearnAllRelatedScripts(const CPubKey& key)
1308 {
1309     // OutputType::P2SH_SEGWIT always adds all necessary scripts for all types.
1310     LearnRelatedScripts(key, OutputType::P2SH_SEGWIT);
1311 }
1312 
MarkReserveKeysAsUsed(int64_t keypool_id)1313 void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
1314 {
1315     AssertLockHeld(cs_KeyStore);
1316     bool internal = setInternalKeyPool.count(keypool_id);
1317     if (!internal) assert(setExternalKeyPool.count(keypool_id) || set_pre_split_keypool.count(keypool_id));
1318     std::set<int64_t> *setKeyPool = internal ? &setInternalKeyPool : (set_pre_split_keypool.empty() ? &setExternalKeyPool : &set_pre_split_keypool);
1319     auto it = setKeyPool->begin();
1320 
1321     WalletBatch batch(m_storage.GetDatabase());
1322     while (it != std::end(*setKeyPool)) {
1323         const int64_t& index = *(it);
1324         if (index > keypool_id) break; // set*KeyPool is ordered
1325 
1326         CKeyPool keypool;
1327         if (batch.ReadPool(index, keypool)) { //TODO: This should be unnecessary
1328             m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
1329         }
1330         LearnAllRelatedScripts(keypool.vchPubKey);
1331         batch.ErasePool(index);
1332         WalletLogPrintf("keypool index %d removed\n", index);
1333         it = setKeyPool->erase(it);
1334     }
1335 }
1336 
GetAffectedKeys(const CScript & spk,const SigningProvider & provider)1337 std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider)
1338 {
1339     std::vector<CScript> dummy;
1340     FlatSigningProvider out;
1341     InferDescriptor(spk, provider)->Expand(0, DUMMY_SIGNING_PROVIDER, dummy, out);
1342     std::vector<CKeyID> ret;
1343     for (const auto& entry : out.pubkeys) {
1344         ret.push_back(entry.first);
1345     }
1346     return ret;
1347 }
1348 
MarkPreSplitKeys()1349 void LegacyScriptPubKeyMan::MarkPreSplitKeys()
1350 {
1351     WalletBatch batch(m_storage.GetDatabase());
1352     for (auto it = setExternalKeyPool.begin(); it != setExternalKeyPool.end();) {
1353         int64_t index = *it;
1354         CKeyPool keypool;
1355         if (!batch.ReadPool(index, keypool)) {
1356             throw std::runtime_error(std::string(__func__) + ": read keypool entry failed");
1357         }
1358         keypool.m_pre_split = true;
1359         if (!batch.WritePool(index, keypool)) {
1360             throw std::runtime_error(std::string(__func__) + ": writing modified keypool entry failed");
1361         }
1362         set_pre_split_keypool.insert(index);
1363         it = setExternalKeyPool.erase(it);
1364     }
1365 }
1366 
AddCScript(const CScript & redeemScript)1367 bool LegacyScriptPubKeyMan::AddCScript(const CScript& redeemScript)
1368 {
1369     WalletBatch batch(m_storage.GetDatabase());
1370     return AddCScriptWithDB(batch, redeemScript);
1371 }
1372 
AddCScriptWithDB(WalletBatch & batch,const CScript & redeemScript)1373 bool LegacyScriptPubKeyMan::AddCScriptWithDB(WalletBatch& batch, const CScript& redeemScript)
1374 {
1375     if (!FillableSigningProvider::AddCScript(redeemScript))
1376         return false;
1377     if (batch.WriteCScript(Hash160(redeemScript), redeemScript)) {
1378         m_storage.UnsetBlankWalletFlag(batch);
1379         return true;
1380     }
1381     return false;
1382 }
1383 
AddKeyOriginWithDB(WalletBatch & batch,const CPubKey & pubkey,const KeyOriginInfo & info)1384 bool LegacyScriptPubKeyMan::AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info)
1385 {
1386     LOCK(cs_KeyStore);
1387     std::copy(info.fingerprint, info.fingerprint + 4, mapKeyMetadata[pubkey.GetID()].key_origin.fingerprint);
1388     mapKeyMetadata[pubkey.GetID()].key_origin.path = info.path;
1389     mapKeyMetadata[pubkey.GetID()].has_key_origin = true;
1390     mapKeyMetadata[pubkey.GetID()].hdKeypath = WriteHDKeypath(info.path);
1391     return batch.WriteKeyMetadata(mapKeyMetadata[pubkey.GetID()], pubkey, true);
1392 }
1393 
ImportScripts(const std::set<CScript> scripts,int64_t timestamp)1394 bool LegacyScriptPubKeyMan::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1395 {
1396     WalletBatch batch(m_storage.GetDatabase());
1397     for (const auto& entry : scripts) {
1398         CScriptID id(entry);
1399         if (HaveCScript(id)) {
1400             WalletLogPrintf("Already have script %s, skipping\n", HexStr(entry));
1401             continue;
1402         }
1403         if (!AddCScriptWithDB(batch, entry)) {
1404             return false;
1405         }
1406 
1407         if (timestamp > 0) {
1408             m_script_metadata[CScriptID(entry)].nCreateTime = timestamp;
1409         }
1410     }
1411     if (timestamp > 0) {
1412         UpdateTimeFirstKey(timestamp);
1413     }
1414 
1415     return true;
1416 }
1417 
ImportPrivKeys(const std::map<CKeyID,CKey> & privkey_map,const int64_t timestamp)1418 bool LegacyScriptPubKeyMan::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1419 {
1420     WalletBatch batch(m_storage.GetDatabase());
1421     for (const auto& entry : privkey_map) {
1422         const CKey& key = entry.second;
1423         CPubKey pubkey = key.GetPubKey();
1424         const CKeyID& id = entry.first;
1425         assert(key.VerifyPubKey(pubkey));
1426         // Skip if we already have the key
1427         if (HaveKey(id)) {
1428             WalletLogPrintf("Already have key with pubkey %s, skipping\n", HexStr(pubkey));
1429             continue;
1430         }
1431         mapKeyMetadata[id].nCreateTime = timestamp;
1432         // If the private key is not present in the wallet, insert it.
1433         if (!AddKeyPubKeyWithDB(batch, key, pubkey)) {
1434             return false;
1435         }
1436         UpdateTimeFirstKey(timestamp);
1437     }
1438     return true;
1439 }
1440 
ImportPubKeys(const std::vector<CKeyID> & ordered_pubkeys,const std::map<CKeyID,CPubKey> & pubkey_map,const std::map<CKeyID,std::pair<CPubKey,KeyOriginInfo>> & key_origins,const bool add_keypool,const bool internal,const int64_t timestamp)1441 bool LegacyScriptPubKeyMan::ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp)
1442 {
1443     WalletBatch batch(m_storage.GetDatabase());
1444     for (const auto& entry : key_origins) {
1445         AddKeyOriginWithDB(batch, entry.second.first, entry.second.second);
1446     }
1447     for (const CKeyID& id : ordered_pubkeys) {
1448         auto entry = pubkey_map.find(id);
1449         if (entry == pubkey_map.end()) {
1450             continue;
1451         }
1452         const CPubKey& pubkey = entry->second;
1453         CPubKey temp;
1454         if (GetPubKey(id, temp)) {
1455             // Already have pubkey, skipping
1456             WalletLogPrintf("Already have pubkey %s, skipping\n", HexStr(temp));
1457             continue;
1458         }
1459         if (!AddWatchOnlyWithDB(batch, GetScriptForRawPubKey(pubkey), timestamp)) {
1460             return false;
1461         }
1462         mapKeyMetadata[id].nCreateTime = timestamp;
1463 
1464         // Add to keypool only works with pubkeys
1465         if (add_keypool) {
1466             AddKeypoolPubkeyWithDB(pubkey, internal, batch);
1467             NotifyCanGetAddressesChanged();
1468         }
1469     }
1470     return true;
1471 }
1472 
ImportScriptPubKeys(const std::set<CScript> & script_pub_keys,const bool have_solving_data,const int64_t timestamp)1473 bool LegacyScriptPubKeyMan::ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp)
1474 {
1475     WalletBatch batch(m_storage.GetDatabase());
1476     for (const CScript& script : script_pub_keys) {
1477         if (!have_solving_data || !IsMine(script)) { // Always call AddWatchOnly for non-solvable watch-only, so that watch timestamp gets updated
1478             if (!AddWatchOnlyWithDB(batch, script, timestamp)) {
1479                 return false;
1480             }
1481         }
1482     }
1483     return true;
1484 }
1485 
GetKeys() const1486 std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const
1487 {
1488     LOCK(cs_KeyStore);
1489     if (!m_storage.HasEncryptionKeys()) {
1490         return FillableSigningProvider::GetKeys();
1491     }
1492     std::set<CKeyID> set_address;
1493     for (const auto& mi : mapCryptedKeys) {
1494         set_address.insert(mi.first);
1495     }
1496     return set_address;
1497 }
1498