PageRenderTime 1108ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/wallet/scriptpubkeyman.cpp

https://github.com/denis2342/bitcoin
C++ | 2339 lines | 1879 code | 281 blank | 179 comment | 400 complexity | c56971318db9cccf56053dbec8df1d01 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. // Copyright (c) 2019-2020 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. #include <key_io.h>
  5. #include <logging.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/system.h>
  13. #include <util/time.h>
  14. #include <util/translation.h>
  15. #include <wallet/scriptpubkeyman.h>
  16. #include <optional>
  17. //! Value for the first BIP 32 hardened derivation. Can be used as a bit mask and as a value. See BIP 32 for more details.
  18. const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
  19. bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error)
  20. {
  21. if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
  22. error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
  23. return false;
  24. }
  25. assert(type != OutputType::BECH32M);
  26. LOCK(cs_KeyStore);
  27. error.clear();
  28. // Generate a new key that is added to wallet
  29. CPubKey new_key;
  30. if (!GetKeyFromPool(new_key, type)) {
  31. error = _("Error: Keypool ran out, please call keypoolrefill first");
  32. return false;
  33. }
  34. LearnRelatedScripts(new_key, type);
  35. dest = GetDestinationForKey(new_key, type);
  36. return true;
  37. }
  38. typedef std::vector<unsigned char> valtype;
  39. namespace {
  40. /**
  41. * This is an enum that tracks the execution context of a script, similar to
  42. * SigVersion in script/interpreter. It is separate however because we want to
  43. * distinguish between top-level scriptPubKey execution and P2SH redeemScript
  44. * execution (a distinction that has no impact on consensus rules).
  45. */
  46. enum class IsMineSigVersion
  47. {
  48. TOP = 0, //!< scriptPubKey execution
  49. P2SH = 1, //!< P2SH redeemScript
  50. WITNESS_V0 = 2, //!< P2WSH witness script execution
  51. };
  52. /**
  53. * This is an internal representation of isminetype + invalidity.
  54. * Its order is significant, as we return the max of all explored
  55. * possibilities.
  56. */
  57. enum class IsMineResult
  58. {
  59. NO = 0, //!< Not ours
  60. WATCH_ONLY = 1, //!< Included in watch-only balance
  61. SPENDABLE = 2, //!< Included in all balances
  62. INVALID = 3, //!< Not spendable by anyone (uncompressed pubkey in segwit, P2SH inside P2SH or witness, witness inside witness)
  63. };
  64. bool PermitsUncompressed(IsMineSigVersion sigversion)
  65. {
  66. return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH;
  67. }
  68. bool HaveKeys(const std::vector<valtype>& pubkeys, const LegacyScriptPubKeyMan& keystore)
  69. {
  70. for (const valtype& pubkey : pubkeys) {
  71. CKeyID keyID = CPubKey(pubkey).GetID();
  72. if (!keystore.HaveKey(keyID)) return false;
  73. }
  74. return true;
  75. }
  76. //! Recursively solve script and return spendable/watchonly/invalid status.
  77. //!
  78. //! @param keystore legacy key and script store
  79. //! @param scriptPubKey script to solve
  80. //! @param sigversion script type (top-level / redeemscript / witnessscript)
  81. //! @param recurse_scripthash whether to recurse into nested p2sh and p2wsh
  82. //! scripts or simply treat any script that has been
  83. //! stored in the keystore as spendable
  84. IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion, bool recurse_scripthash=true)
  85. {
  86. IsMineResult ret = IsMineResult::NO;
  87. std::vector<valtype> vSolutions;
  88. TxoutType whichType = Solver(scriptPubKey, vSolutions);
  89. CKeyID keyID;
  90. switch (whichType) {
  91. case TxoutType::NONSTANDARD:
  92. case TxoutType::NULL_DATA:
  93. case TxoutType::WITNESS_UNKNOWN:
  94. case TxoutType::WITNESS_V1_TAPROOT:
  95. break;
  96. case TxoutType::PUBKEY:
  97. keyID = CPubKey(vSolutions[0]).GetID();
  98. if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
  99. return IsMineResult::INVALID;
  100. }
  101. if (keystore.HaveKey(keyID)) {
  102. ret = std::max(ret, IsMineResult::SPENDABLE);
  103. }
  104. break;
  105. case TxoutType::WITNESS_V0_KEYHASH:
  106. {
  107. if (sigversion == IsMineSigVersion::WITNESS_V0) {
  108. // P2WPKH inside P2WSH is invalid.
  109. return IsMineResult::INVALID;
  110. }
  111. if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
  112. // We do not support bare witness outputs unless the P2SH version of it would be
  113. // acceptable as well. This protects against matching before segwit activates.
  114. // This also applies to the P2WSH case.
  115. break;
  116. }
  117. ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(PKHash(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
  118. break;
  119. }
  120. case TxoutType::PUBKEYHASH:
  121. keyID = CKeyID(uint160(vSolutions[0]));
  122. if (!PermitsUncompressed(sigversion)) {
  123. CPubKey pubkey;
  124. if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
  125. return IsMineResult::INVALID;
  126. }
  127. }
  128. if (keystore.HaveKey(keyID)) {
  129. ret = std::max(ret, IsMineResult::SPENDABLE);
  130. }
  131. break;
  132. case TxoutType::SCRIPTHASH:
  133. {
  134. if (sigversion != IsMineSigVersion::TOP) {
  135. // P2SH inside P2WSH or P2SH is invalid.
  136. return IsMineResult::INVALID;
  137. }
  138. CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
  139. CScript subscript;
  140. if (keystore.GetCScript(scriptID, subscript)) {
  141. ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::P2SH) : IsMineResult::SPENDABLE);
  142. }
  143. break;
  144. }
  145. case TxoutType::WITNESS_V0_SCRIPTHASH:
  146. {
  147. if (sigversion == IsMineSigVersion::WITNESS_V0) {
  148. // P2WSH inside P2WSH is invalid.
  149. return IsMineResult::INVALID;
  150. }
  151. if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
  152. break;
  153. }
  154. uint160 hash;
  155. CRIPEMD160().Write(vSolutions[0].data(), vSolutions[0].size()).Finalize(hash.begin());
  156. CScriptID scriptID = CScriptID(hash);
  157. CScript subscript;
  158. if (keystore.GetCScript(scriptID, subscript)) {
  159. ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0) : IsMineResult::SPENDABLE);
  160. }
  161. break;
  162. }
  163. case TxoutType::MULTISIG:
  164. {
  165. // Never treat bare multisig outputs as ours (they can still be made watchonly-though)
  166. if (sigversion == IsMineSigVersion::TOP) {
  167. break;
  168. }
  169. // Only consider transactions "mine" if we own ALL the
  170. // keys involved. Multi-signature transactions that are
  171. // partially owned (somebody else has a key that can spend
  172. // them) enable spend-out-from-under-you attacks, especially
  173. // in shared-wallet situations.
  174. std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
  175. if (!PermitsUncompressed(sigversion)) {
  176. for (size_t i = 0; i < keys.size(); i++) {
  177. if (keys[i].size() != 33) {
  178. return IsMineResult::INVALID;
  179. }
  180. }
  181. }
  182. if (HaveKeys(keys, keystore)) {
  183. ret = std::max(ret, IsMineResult::SPENDABLE);
  184. }
  185. break;
  186. }
  187. } // no default case, so the compiler can warn about missing cases
  188. if (ret == IsMineResult::NO && keystore.HaveWatchOnly(scriptPubKey)) {
  189. ret = std::max(ret, IsMineResult::WATCH_ONLY);
  190. }
  191. return ret;
  192. }
  193. } // namespace
  194. isminetype LegacyScriptPubKeyMan::IsMine(const CScript& script) const
  195. {
  196. switch (IsMineInner(*this, script, IsMineSigVersion::TOP)) {
  197. case IsMineResult::INVALID:
  198. case IsMineResult::NO:
  199. return ISMINE_NO;
  200. case IsMineResult::WATCH_ONLY:
  201. return ISMINE_WATCH_ONLY;
  202. case IsMineResult::SPENDABLE:
  203. return ISMINE_SPENDABLE;
  204. }
  205. assert(false);
  206. }
  207. bool LegacyScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys)
  208. {
  209. {
  210. LOCK(cs_KeyStore);
  211. assert(mapKeys.empty());
  212. bool keyPass = mapCryptedKeys.empty(); // Always pass when there are no encrypted keys
  213. bool keyFail = false;
  214. CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
  215. WalletBatch batch(m_storage.GetDatabase());
  216. for (; mi != mapCryptedKeys.end(); ++mi)
  217. {
  218. const CPubKey &vchPubKey = (*mi).second.first;
  219. const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
  220. CKey key;
  221. if (!DecryptKey(master_key, vchCryptedSecret, vchPubKey, key))
  222. {
  223. keyFail = true;
  224. break;
  225. }
  226. keyPass = true;
  227. if (fDecryptionThoroughlyChecked)
  228. break;
  229. else {
  230. // Rewrite these encrypted keys with checksums
  231. batch.WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]);
  232. }
  233. }
  234. if (keyPass && keyFail)
  235. {
  236. LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
  237. throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
  238. }
  239. if (keyFail || (!keyPass && !accept_no_keys))
  240. return false;
  241. fDecryptionThoroughlyChecked = true;
  242. }
  243. return true;
  244. }
  245. bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch)
  246. {
  247. LOCK(cs_KeyStore);
  248. encrypted_batch = batch;
  249. if (!mapCryptedKeys.empty()) {
  250. encrypted_batch = nullptr;
  251. return false;
  252. }
  253. KeyMap keys_to_encrypt;
  254. keys_to_encrypt.swap(mapKeys); // Clear mapKeys so AddCryptedKeyInner will succeed.
  255. for (const KeyMap::value_type& mKey : keys_to_encrypt)
  256. {
  257. const CKey &key = mKey.second;
  258. CPubKey vchPubKey = key.GetPubKey();
  259. CKeyingMaterial vchSecret(key.begin(), key.end());
  260. std::vector<unsigned char> vchCryptedSecret;
  261. if (!EncryptSecret(master_key, vchSecret, vchPubKey.GetHash(), vchCryptedSecret)) {
  262. encrypted_batch = nullptr;
  263. return false;
  264. }
  265. if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) {
  266. encrypted_batch = nullptr;
  267. return false;
  268. }
  269. }
  270. encrypted_batch = nullptr;
  271. return true;
  272. }
  273. bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
  274. {
  275. if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
  276. error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
  277. return false;
  278. }
  279. assert(type != OutputType::BECH32M);
  280. LOCK(cs_KeyStore);
  281. if (!CanGetAddresses(internal)) {
  282. error = _("Error: Keypool ran out, please call keypoolrefill first");
  283. return false;
  284. }
  285. if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
  286. error = _("Error: Keypool ran out, please call keypoolrefill first");
  287. return false;
  288. }
  289. address = GetDestinationForKey(keypool.vchPubKey, type);
  290. return true;
  291. }
  292. bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal)
  293. {
  294. LOCK(cs_KeyStore);
  295. if (m_storage.IsLocked()) return false;
  296. auto it = m_inactive_hd_chains.find(seed_id);
  297. if (it == m_inactive_hd_chains.end()) {
  298. return false;
  299. }
  300. CHDChain& chain = it->second;
  301. // Top up key pool
  302. int64_t target_size = std::max(gArgs.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 1);
  303. // "size" of the keypools. Not really the size, actually the difference between index and the chain counter
  304. // Since chain counter is 1 based and index is 0 based, one of them needs to be offset by 1.
  305. int64_t kp_size = (internal ? chain.nInternalChainCounter : chain.nExternalChainCounter) - (index + 1);
  306. // make sure the keypool fits the user-selected target (-keypool)
  307. int64_t missing = std::max(target_size - kp_size, (int64_t) 0);
  308. if (missing > 0) {
  309. WalletBatch batch(m_storage.GetDatabase());
  310. for (int64_t i = missing; i > 0; --i) {
  311. GenerateNewKey(batch, chain, internal);
  312. }
  313. if (internal) {
  314. WalletLogPrintf("inactive seed with id %s added %d internal keys\n", HexStr(seed_id), missing);
  315. } else {
  316. WalletLogPrintf("inactive seed with id %s added %d keys\n", HexStr(seed_id), missing);
  317. }
  318. }
  319. return true;
  320. }
  321. void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
  322. {
  323. LOCK(cs_KeyStore);
  324. // extract addresses and check if they match with an unused keypool key
  325. for (const auto& keyid : GetAffectedKeys(script, *this)) {
  326. std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
  327. if (mi != m_pool_key_to_index.end()) {
  328. WalletLogPrintf("%s: Detected a used keypool key, mark all keypool keys up to this key as used\n", __func__);
  329. MarkReserveKeysAsUsed(mi->second);
  330. if (!TopUp()) {
  331. WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
  332. }
  333. }
  334. // Find the key's metadata and check if it's seed id (if it has one) is inactive, i.e. it is not the current m_hd_chain seed id.
  335. // If so, TopUp the inactive hd chain
  336. auto it = mapKeyMetadata.find(keyid);
  337. if (it != mapKeyMetadata.end()){
  338. CKeyMetadata meta = it->second;
  339. if (!meta.hd_seed_id.IsNull() && meta.hd_seed_id != m_hd_chain.seed_id) {
  340. bool internal = (meta.key_origin.path[1] & ~BIP32_HARDENED_KEY_LIMIT) != 0;
  341. int64_t index = meta.key_origin.path[2] & ~BIP32_HARDENED_KEY_LIMIT;
  342. if (!TopUpInactiveHDChain(meta.hd_seed_id, index, internal)) {
  343. WalletLogPrintf("%s: Adding inactive seed keys failed\n", __func__);
  344. }
  345. }
  346. }
  347. }
  348. }
  349. void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
  350. {
  351. LOCK(cs_KeyStore);
  352. if (m_storage.IsLocked() || m_storage.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
  353. return;
  354. }
  355. std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(m_storage.GetDatabase());
  356. for (auto& meta_pair : mapKeyMetadata) {
  357. CKeyMetadata& meta = meta_pair.second;
  358. 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
  359. CKey key;
  360. GetKey(meta.hd_seed_id, key);
  361. CExtKey masterKey;
  362. masterKey.SetSeed(key.begin(), key.size());
  363. // Add to map
  364. CKeyID master_id = masterKey.key.GetPubKey().GetID();
  365. std::copy(master_id.begin(), master_id.begin() + 4, meta.key_origin.fingerprint);
  366. if (!ParseHDKeypath(meta.hdKeypath, meta.key_origin.path)) {
  367. throw std::runtime_error("Invalid stored hdKeypath");
  368. }
  369. meta.has_key_origin = true;
  370. if (meta.nVersion < CKeyMetadata::VERSION_WITH_KEY_ORIGIN) {
  371. meta.nVersion = CKeyMetadata::VERSION_WITH_KEY_ORIGIN;
  372. }
  373. // Write meta to wallet
  374. CPubKey pubkey;
  375. if (GetPubKey(meta_pair.first, pubkey)) {
  376. batch->WriteKeyMetadata(meta, pubkey, true);
  377. }
  378. }
  379. }
  380. }
  381. bool LegacyScriptPubKeyMan::SetupGeneration(bool force)
  382. {
  383. if ((CanGenerateKeys() && !force) || m_storage.IsLocked()) {
  384. return false;
  385. }
  386. SetHDSeed(GenerateNewSeed());
  387. if (!NewKeyPool()) {
  388. return false;
  389. }
  390. return true;
  391. }
  392. bool LegacyScriptPubKeyMan::IsHDEnabled() const
  393. {
  394. return !m_hd_chain.seed_id.IsNull();
  395. }
  396. bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) const
  397. {
  398. LOCK(cs_KeyStore);
  399. // Check if the keypool has keys
  400. bool keypool_has_keys;
  401. if (internal && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
  402. keypool_has_keys = setInternalKeyPool.size() > 0;
  403. } else {
  404. keypool_has_keys = KeypoolCountExternalKeys() > 0;
  405. }
  406. // If the keypool doesn't have keys, check if we can generate them
  407. if (!keypool_has_keys) {
  408. return CanGenerateKeys();
  409. }
  410. return keypool_has_keys;
  411. }
  412. bool LegacyScriptPubKeyMan::Upgrade(int prev_version, int new_version, bilingual_str& error)
  413. {
  414. LOCK(cs_KeyStore);
  415. bool hd_upgrade = false;
  416. bool split_upgrade = false;
  417. if (IsFeatureSupported(new_version, FEATURE_HD) && !IsHDEnabled()) {
  418. WalletLogPrintf("Upgrading wallet to HD\n");
  419. m_storage.SetMinVersion(FEATURE_HD);
  420. // generate a new master key
  421. CPubKey masterPubKey = GenerateNewSeed();
  422. SetHDSeed(masterPubKey);
  423. hd_upgrade = true;
  424. }
  425. // Upgrade to HD chain split if necessary
  426. if (!IsFeatureSupported(prev_version, FEATURE_HD_SPLIT) && IsFeatureSupported(new_version, FEATURE_HD_SPLIT)) {
  427. WalletLogPrintf("Upgrading wallet to use HD chain split\n");
  428. m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
  429. split_upgrade = FEATURE_HD_SPLIT > prev_version;
  430. // Upgrade the HDChain
  431. if (m_hd_chain.nVersion < CHDChain::VERSION_HD_CHAIN_SPLIT) {
  432. m_hd_chain.nVersion = CHDChain::VERSION_HD_CHAIN_SPLIT;
  433. if (!WalletBatch(m_storage.GetDatabase()).WriteHDChain(m_hd_chain)) {
  434. throw std::runtime_error(std::string(__func__) + ": writing chain failed");
  435. }
  436. }
  437. }
  438. // Mark all keys currently in the keypool as pre-split
  439. if (split_upgrade) {
  440. MarkPreSplitKeys();
  441. }
  442. // Regenerate the keypool if upgraded to HD
  443. if (hd_upgrade) {
  444. if (!NewKeyPool()) {
  445. error = _("Unable to generate keys");
  446. return false;
  447. }
  448. }
  449. return true;
  450. }
  451. bool LegacyScriptPubKeyMan::HavePrivateKeys() const
  452. {
  453. LOCK(cs_KeyStore);
  454. return !mapKeys.empty() || !mapCryptedKeys.empty();
  455. }
  456. void LegacyScriptPubKeyMan::RewriteDB()
  457. {
  458. LOCK(cs_KeyStore);
  459. setInternalKeyPool.clear();
  460. setExternalKeyPool.clear();
  461. m_pool_key_to_index.clear();
  462. // Note: can't top-up keypool here, because wallet is locked.
  463. // User will be prompted to unlock wallet the next operation
  464. // that requires a new key.
  465. }
  466. static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, WalletBatch& batch) {
  467. if (setKeyPool.empty()) {
  468. return GetTime();
  469. }
  470. CKeyPool keypool;
  471. int64_t nIndex = *(setKeyPool.begin());
  472. if (!batch.ReadPool(nIndex, keypool)) {
  473. throw std::runtime_error(std::string(__func__) + ": read oldest key in keypool failed");
  474. }
  475. assert(keypool.vchPubKey.IsValid());
  476. return keypool.nTime;
  477. }
  478. int64_t LegacyScriptPubKeyMan::GetOldestKeyPoolTime() const
  479. {
  480. LOCK(cs_KeyStore);
  481. WalletBatch batch(m_storage.GetDatabase());
  482. // load oldest key from keypool, get time and return
  483. int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, batch);
  484. if (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
  485. oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, batch), oldestKey);
  486. if (!set_pre_split_keypool.empty()) {
  487. oldestKey = std::max(GetOldestKeyTimeInPool(set_pre_split_keypool, batch), oldestKey);
  488. }
  489. }
  490. return oldestKey;
  491. }
  492. size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys() const
  493. {
  494. LOCK(cs_KeyStore);
  495. return setExternalKeyPool.size() + set_pre_split_keypool.size();
  496. }
  497. unsigned int LegacyScriptPubKeyMan::GetKeyPoolSize() const
  498. {
  499. LOCK(cs_KeyStore);
  500. return setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size();
  501. }
  502. int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
  503. {
  504. LOCK(cs_KeyStore);
  505. return nTimeFirstKey;
  506. }
  507. std::unique_ptr<SigningProvider> LegacyScriptPubKeyMan::GetSolvingProvider(const CScript& script) const
  508. {
  509. return std::make_unique<LegacySigningProvider>(*this);
  510. }
  511. bool LegacyScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sigdata)
  512. {
  513. IsMineResult ismine = IsMineInner(*this, script, IsMineSigVersion::TOP, /* recurse_scripthash= */ false);
  514. if (ismine == IsMineResult::SPENDABLE || ismine == IsMineResult::WATCH_ONLY) {
  515. // If ismine, it means we recognize keys or script ids in the script, or
  516. // are watching the script itself, and we can at least provide metadata
  517. // or solving information, even if not able to sign fully.
  518. return true;
  519. } else {
  520. // If, given the stuff in sigdata, we could make a valid sigature, then we can provide for this script
  521. ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, script, sigdata);
  522. if (!sigdata.signatures.empty()) {
  523. // If we could make signatures, make sure we have a private key to actually make a signature
  524. bool has_privkeys = false;
  525. for (const auto& key_sig_pair : sigdata.signatures) {
  526. has_privkeys |= HaveKey(key_sig_pair.first);
  527. }
  528. return has_privkeys;
  529. }
  530. return false;
  531. }
  532. }
  533. bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
  534. {
  535. return ::SignTransaction(tx, this, coins, sighash, input_errors);
  536. }
  537. SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
  538. {
  539. CKey key;
  540. if (!GetKey(ToKeyID(pkhash), key)) {
  541. return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
  542. }
  543. if (MessageSign(key, message, str_sig)) {
  544. return SigningResult::OK;
  545. }
  546. return SigningResult::SIGNING_FAILED;
  547. }
  548. TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, const PrecomputedTransactionData& txdata, int sighash_type, bool sign, bool bip32derivs, int* n_signed) const
  549. {
  550. if (n_signed) {
  551. *n_signed = 0;
  552. }
  553. for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
  554. const CTxIn& txin = psbtx.tx->vin[i];
  555. PSBTInput& input = psbtx.inputs.at(i);
  556. if (PSBTInputSigned(input)) {
  557. continue;
  558. }
  559. // Get the Sighash type
  560. if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
  561. return TransactionError::SIGHASH_MISMATCH;
  562. }
  563. // Check non_witness_utxo has specified prevout
  564. if (input.non_witness_utxo) {
  565. if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
  566. return TransactionError::MISSING_INPUTS;
  567. }
  568. } else if (input.witness_utxo.IsNull()) {
  569. // There's no UTXO so we can just skip this now
  570. continue;
  571. }
  572. SignatureData sigdata;
  573. input.FillSignatureData(sigdata);
  574. SignPSBTInput(HidingSigningProvider(this, !sign, !bip32derivs), psbtx, i, &txdata, sighash_type);
  575. bool signed_one = PSBTInputSigned(input);
  576. if (n_signed && (signed_one || !sign)) {
  577. // If sign is false, we assume that we _could_ sign if we get here. This
  578. // will never have false negatives; it is hard to tell under what i
  579. // circumstances it could have false positives.
  580. (*n_signed)++;
  581. }
  582. }
  583. // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
  584. for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
  585. UpdatePSBTOutput(HidingSigningProvider(this, true, !bip32derivs), psbtx, i);
  586. }
  587. return TransactionError::OK;
  588. }
  589. std::unique_ptr<CKeyMetadata> LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const
  590. {
  591. LOCK(cs_KeyStore);
  592. CKeyID key_id = GetKeyForDestination(*this, dest);
  593. if (!key_id.IsNull()) {
  594. auto it = mapKeyMetadata.find(key_id);
  595. if (it != mapKeyMetadata.end()) {
  596. return std::make_unique<CKeyMetadata>(it->second);
  597. }
  598. }
  599. CScript scriptPubKey = GetScriptForDestination(dest);
  600. auto it = m_script_metadata.find(CScriptID(scriptPubKey));
  601. if (it != m_script_metadata.end()) {
  602. return std::make_unique<CKeyMetadata>(it->second);
  603. }
  604. return nullptr;
  605. }
  606. uint256 LegacyScriptPubKeyMan::GetID() const
  607. {
  608. return uint256::ONE;
  609. }
  610. /**
  611. * Update wallet first key creation time. This should be called whenever keys
  612. * are added to the wallet, with the oldest key creation time.
  613. */
  614. void LegacyScriptPubKeyMan::UpdateTimeFirstKey(int64_t nCreateTime)
  615. {
  616. AssertLockHeld(cs_KeyStore);
  617. if (nCreateTime <= 1) {
  618. // Cannot determine birthday information, so set the wallet birthday to
  619. // the beginning of time.
  620. nTimeFirstKey = 1;
  621. } else if (!nTimeFirstKey || nCreateTime < nTimeFirstKey) {
  622. nTimeFirstKey = nCreateTime;
  623. }
  624. }
  625. bool LegacyScriptPubKeyMan::LoadKey(const CKey& key, const CPubKey &pubkey)
  626. {
  627. return AddKeyPubKeyInner(key, pubkey);
  628. }
  629. bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
  630. {
  631. LOCK(cs_KeyStore);
  632. WalletBatch batch(m_storage.GetDatabase());
  633. return LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(batch, secret, pubkey);
  634. }
  635. bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& secret, const CPubKey& pubkey)
  636. {
  637. AssertLockHeld(cs_KeyStore);
  638. // Make sure we aren't adding private keys to private key disabled wallets
  639. assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
  640. // FillableSigningProvider has no concept of wallet databases, but calls AddCryptedKey
  641. // which is overridden below. To avoid flushes, the database handle is
  642. // tunneled through to it.
  643. bool needsDB = !encrypted_batch;
  644. if (needsDB) {
  645. encrypted_batch = &batch;
  646. }
  647. if (!AddKeyPubKeyInner(secret, pubkey)) {
  648. if (needsDB) encrypted_batch = nullptr;
  649. return false;
  650. }
  651. if (needsDB) encrypted_batch = nullptr;
  652. // check if we need to remove from watch-only
  653. CScript script;
  654. script = GetScriptForDestination(PKHash(pubkey));
  655. if (HaveWatchOnly(script)) {
  656. RemoveWatchOnly(script);
  657. }
  658. script = GetScriptForRawPubKey(pubkey);
  659. if (HaveWatchOnly(script)) {
  660. RemoveWatchOnly(script);
  661. }
  662. if (!m_storage.HasEncryptionKeys()) {
  663. return batch.WriteKey(pubkey,
  664. secret.GetPrivKey(),
  665. mapKeyMetadata[pubkey.GetID()]);
  666. }
  667. m_storage.UnsetBlankWalletFlag(batch);
  668. return true;
  669. }
  670. bool LegacyScriptPubKeyMan::LoadCScript(const CScript& redeemScript)
  671. {
  672. /* A sanity check was added in pull #3843 to avoid adding redeemScripts
  673. * that never can be redeemed. However, old wallets may still contain
  674. * these. Do not add them to the wallet and warn. */
  675. if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
  676. {
  677. std::string strAddr = EncodeDestination(ScriptHash(redeemScript));
  678. 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);
  679. return true;
  680. }
  681. return FillableSigningProvider::AddCScript(redeemScript);
  682. }
  683. void LegacyScriptPubKeyMan::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata& meta)
  684. {
  685. LOCK(cs_KeyStore);
  686. UpdateTimeFirstKey(meta.nCreateTime);
  687. mapKeyMetadata[keyID] = meta;
  688. }
  689. void LegacyScriptPubKeyMan::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata& meta)
  690. {
  691. LOCK(cs_KeyStore);
  692. UpdateTimeFirstKey(meta.nCreateTime);
  693. m_script_metadata[script_id] = meta;
  694. }
  695. bool LegacyScriptPubKeyMan::AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey)
  696. {
  697. LOCK(cs_KeyStore);
  698. if (!m_storage.HasEncryptionKeys()) {
  699. return FillableSigningProvider::AddKeyPubKey(key, pubkey);
  700. }
  701. if (m_storage.IsLocked()) {
  702. return false;
  703. }
  704. std::vector<unsigned char> vchCryptedSecret;
  705. CKeyingMaterial vchSecret(key.begin(), key.end());
  706. if (!EncryptSecret(m_storage.GetEncryptionKey(), vchSecret, pubkey.GetHash(), vchCryptedSecret)) {
  707. return false;
  708. }
  709. if (!AddCryptedKey(pubkey, vchCryptedSecret)) {
  710. return false;
  711. }
  712. return true;
  713. }
  714. bool LegacyScriptPubKeyMan::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret, bool checksum_valid)
  715. {
  716. // Set fDecryptionThoroughlyChecked to false when the checksum is invalid
  717. if (!checksum_valid) {
  718. fDecryptionThoroughlyChecked = false;
  719. }
  720. return AddCryptedKeyInner(vchPubKey, vchCryptedSecret);
  721. }
  722. bool LegacyScriptPubKeyMan::AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
  723. {
  724. LOCK(cs_KeyStore);
  725. assert(mapKeys.empty());
  726. mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
  727. ImplicitlyLearnRelatedKeyScripts(vchPubKey);
  728. return true;
  729. }
  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. bool LegacyScriptPubKeyMan::HaveWatchOnly(const CScript &dest) const
  748. {
  749. LOCK(cs_KeyStore);
  750. return setWatchOnly.count(dest) > 0;
  751. }
  752. bool LegacyScriptPubKeyMan::HaveWatchOnly() const
  753. {
  754. LOCK(cs_KeyStore);
  755. return (!setWatchOnly.empty());
  756. }
  757. static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
  758. {
  759. std::vector<std::vector<unsigned char>> solutions;
  760. return Solver(dest, solutions) == TxoutType::PUBKEY &&
  761. (pubKeyOut = CPubKey(solutions[0])).IsFullyValid();
  762. }
  763. bool LegacyScriptPubKeyMan::RemoveWatchOnly(const CScript &dest)
  764. {
  765. {
  766. LOCK(cs_KeyStore);
  767. setWatchOnly.erase(dest);
  768. CPubKey pubKey;
  769. if (ExtractPubKey(dest, pubKey)) {
  770. mapWatchKeys.erase(pubKey.GetID());
  771. }
  772. // Related CScripts are not removed; having superfluous scripts around is
  773. // harmless (see comment in ImplicitlyLearnRelatedKeyScripts).
  774. }
  775. if (!HaveWatchOnly())
  776. NotifyWatchonlyChanged(false);
  777. if (!WalletBatch(m_storage.GetDatabase()).EraseWatchOnly(dest))
  778. return false;
  779. return true;
  780. }
  781. bool LegacyScriptPubKeyMan::LoadWatchOnly(const CScript &dest)
  782. {
  783. return AddWatchOnlyInMem(dest);
  784. }
  785. bool LegacyScriptPubKeyMan::AddWatchOnlyInMem(const CScript &dest)
  786. {
  787. LOCK(cs_KeyStore);
  788. setWatchOnly.insert(dest);
  789. CPubKey pubKey;
  790. if (ExtractPubKey(dest, pubKey)) {
  791. mapWatchKeys[pubKey.GetID()] = pubKey;
  792. ImplicitlyLearnRelatedKeyScripts(pubKey);
  793. }
  794. return true;
  795. }
  796. bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest)
  797. {
  798. if (!AddWatchOnlyInMem(dest))
  799. return false;
  800. const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
  801. UpdateTimeFirstKey(meta.nCreateTime);
  802. NotifyWatchonlyChanged(true);
  803. if (batch.WriteWatchOnly(dest, meta)) {
  804. m_storage.UnsetBlankWalletFlag(batch);
  805. return true;
  806. }
  807. return false;
  808. }
  809. bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest, int64_t create_time)
  810. {
  811. m_script_metadata[CScriptID(dest)].nCreateTime = create_time;
  812. return AddWatchOnlyWithDB(batch, dest);
  813. }
  814. bool LegacyScriptPubKeyMan::AddWatchOnly(const CScript& dest)
  815. {
  816. WalletBatch batch(m_storage.GetDatabase());
  817. return AddWatchOnlyWithDB(batch, dest);
  818. }
  819. bool LegacyScriptPubKeyMan::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
  820. {
  821. m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime;
  822. return AddWatchOnly(dest);
  823. }
  824. void LegacyScriptPubKeyMan::LoadHDChain(const CHDChain& chain)
  825. {
  826. LOCK(cs_KeyStore);
  827. m_hd_chain = chain;
  828. }
  829. void LegacyScriptPubKeyMan::AddHDChain(const CHDChain& chain)
  830. {
  831. LOCK(cs_KeyStore);
  832. // Store the new chain
  833. if (!WalletBatch(m_storage.GetDatabase()).WriteHDChain(chain)) {
  834. throw std::runtime_error(std::string(__func__) + ": writing chain failed");
  835. }
  836. // When there's an old chain, add it as an inactive chain as we are now rotating hd chains
  837. if (!m_hd_chain.seed_id.IsNull()) {
  838. AddInactiveHDChain(m_hd_chain);
  839. }
  840. m_hd_chain = chain;
  841. }
  842. void LegacyScriptPubKeyMan::AddInactiveHDChain(const CHDChain& chain)
  843. {
  844. LOCK(cs_KeyStore);
  845. assert(!chain.seed_id.IsNull());
  846. m_inactive_hd_chains[chain.seed_id] = chain;
  847. }
  848. bool LegacyScriptPubKeyMan::HaveKey(const CKeyID &address) const
  849. {
  850. LOCK(cs_KeyStore);
  851. if (!m_storage.HasEncryptionKeys()) {
  852. return FillableSigningProvider::HaveKey(address);
  853. }
  854. return mapCryptedKeys.count(address) > 0;
  855. }
  856. bool LegacyScriptPubKeyMan::GetKey(const CKeyID &address, CKey& keyOut) const
  857. {
  858. LOCK(cs_KeyStore);
  859. if (!m_storage.HasEncryptionKeys()) {
  860. return FillableSigningProvider::GetKey(address, keyOut);
  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. bool LegacyScriptPubKeyMan::GetKeyOrigin(const CKeyID& keyID, KeyOriginInfo& info) const
  872. {
  873. CKeyMetadata meta;
  874. {
  875. LOCK(cs_KeyStore);
  876. auto it = mapKeyMetadata.find(keyID);
  877. if (it != mapKeyMetadata.end()) {
  878. meta = it->second;
  879. }
  880. }
  881. if (meta.has_key_origin) {
  882. std::copy(meta.key_origin.fingerprint, meta.key_origin.fingerprint + 4, info.fingerprint);
  883. info.path = meta.key_origin.path;
  884. } else { // Single pubkeys get the master fingerprint of themselves
  885. std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint);
  886. }
  887. return true;
  888. }
  889. bool LegacyScriptPubKeyMan::GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
  890. {
  891. LOCK(cs_KeyStore);
  892. WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
  893. if (it != mapWatchKeys.end()) {
  894. pubkey_out = it->second;
  895. return true;
  896. }
  897. return false;
  898. }
  899. bool LegacyScriptPubKeyMan::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
  900. {
  901. LOCK(cs_KeyStore);
  902. if (!m_storage.HasEncryptionKeys()) {
  903. if (!FillableSigningProvider::GetPubKey(address, vchPubKeyOut)) {
  904. return GetWatchPubKey(address, vchPubKeyOut);
  905. }
  906. return true;
  907. }
  908. CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
  909. if (mi != mapCryptedKeys.end())
  910. {
  911. vchPubKeyOut = (*mi).second.first;
  912. return true;
  913. }
  914. // Check for watch-only pubkeys
  915. return GetWatchPubKey(address, vchPubKeyOut);
  916. }
  917. CPubKey LegacyScriptPubKeyMan::GenerateNewKey(WalletBatch &batch, CHDChain& hd_chain, bool internal)
  918. {
  919. assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
  920. assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
  921. AssertLockHeld(cs_KeyStore);
  922. bool fCompressed = m_storage.CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
  923. CKey secret;
  924. // Create new metadata
  925. int64_t nCreationTime = GetTime();
  926. CKeyMetadata metadata(nCreationTime);
  927. // use HD key derivation if HD was enabled during wallet creation and a seed is present
  928. if (IsHDEnabled()) {
  929. DeriveNewChildKey(batch, metadata, secret, hd_chain, (m_storage.CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
  930. } else {
  931. secret.MakeNewKey(fCompressed);
  932. }
  933. // Compressed public keys were introduced in version 0.6.0
  934. if (fCompressed) {
  935. m_storage.SetMinVersion(FEATURE_COMPRPUBKEY);
  936. }
  937. CPubKey pubkey = secret.GetPubKey();
  938. assert(secret.VerifyPubKey(pubkey));
  939. mapKeyMetadata[pubkey.GetID()] = metadata;
  940. UpdateTimeFirstKey(nCreationTime);
  941. if (!AddKeyPubKeyWithDB(batch, secret, pubkey)) {
  942. throw std::runtime_error(std::string(__func__) + ": AddKey failed");
  943. }
  944. return pubkey;
  945. }
  946. void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal)
  947. {
  948. // for now we use a fixed keypath scheme of m/0'/0'/k
  949. CKey seed; //seed (256bit)
  950. CExtKey masterKey; //hd master key
  951. CExtKey accountKey; //key at m/0'
  952. CExtKey chainChildKey; //key at m/0'/0' (external) or m/0'/1' (internal)
  953. CExtKey childKey; //key at m/0'/0'/<n>'
  954. // try to get the seed
  955. if (!GetKey(hd_chain.seed_id, seed))
  956. throw std::runtime_error(std::string(__func__) + ": seed not found");
  957. masterKey.SetSeed(seed.begin(), seed.size());
  958. // derive m/0'
  959. // use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
  960. masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT);
  961. // derive m/0'/0' (external chain) OR m/0'/1' (internal chain)
  962. assert(internal ? m_storage.CanSupportFeature(FEATURE_HD_SPLIT) : true);
  963. accountKey.Derive(chainChildKey, BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0));
  964. // derive child key at next index, skip keys already known to the wallet
  965. do {
  966. // always derive hardened keys
  967. // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
  968. // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
  969. if (internal) {
  970. chainChildKey.Derive(childKey, hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
  971. metadata.hdKeypath = "m/0'/1'/" + ToString(hd_chain.nInternalChainCounter) + "'";
  972. metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
  973. metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT);
  974. metadata.key_origin.path.push_back(hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
  975. hd_chain.nInternalChainCounter++;
  976. }
  977. else {
  978. chainChildKey.Derive(childKey, hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
  979. metadata.hdKeypath = "m/0'/0'/" + ToString(hd_chain.nExternalChainCounter) + "'";
  980. metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
  981. metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
  982. metadata.key_origin.path.push_back(hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
  983. hd_chain.nExternalChainCounter++;
  984. }
  985. } while (HaveKey(childKey.key.GetPubKey().GetID()));
  986. secret = childKey.key;
  987. metadata.hd_seed_id = hd_chain.seed_id;
  988. CKeyID master_id = masterKey.key.GetPubKey().GetID();
  989. std::copy(master_id.begin(), master_id.begin() + 4, metadata.key_origin.fingerprint);
  990. metadata.has_key_origin = true;
  991. // update the chain model in the database
  992. if (hd_chain.seed_id == m_hd_chain.seed_id && !batch.WriteHDChain(hd_chain))
  993. throw std::runtime_error(std::string(__func__) + ": writing HD chain model failed");
  994. }
  995. void LegacyScriptPubKeyMan::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
  996. {
  997. LOCK(cs_KeyStore);
  998. if (keypool.m_pre_split) {
  999. set_pre_split_keypool.insert(nIndex);
  1000. } else if (keypool.fInternal) {
  1001. setInternalKeyPool.insert(nIndex);
  1002. } else {
  1003. setExternalKeyPool.insert(nIndex);
  1004. }
  1005. m_max_keypool_index = std::max(m_max_keypool_index, nIndex);
  1006. m_pool_key_to_index[keypool.vchPubKey.GetID()] = nIndex;
  1007. // If no metadata exists yet, create a default with the pool key's
  1008. // creation time. Note that this may be overwritten by actually
  1009. // stored metadata for that key later, which is fine.
  1010. CKeyID keyid = keypool.vchPubKey.GetID();
  1011. if (mapKeyMetadata.count(keyid) == 0)
  1012. mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
  1013. }
  1014. bool LegacyScriptPubKeyMan::CanGenerateKeys() const
  1015. {
  1016. // A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a non-HD wallet (pre FEATURE_HD)
  1017. LOCK(cs_KeyStore);
  1018. return IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD);
  1019. }
  1020. CPubKey LegacyScriptPubKeyMan::GenerateNewSeed()
  1021. {
  1022. assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
  1023. CKey key;
  1024. key.MakeNewKey(true);
  1025. return DeriveNewSeed(key);
  1026. }
  1027. CPubKey LegacyScriptPubKeyMan::DeriveNewSeed(const CKey& key)
  1028. {
  1029. int64_t nCreationTime = GetTime();
  1030. CKeyMetadata metadata(nCreationTime);
  1031. // calculate the seed
  1032. CPubKey seed = key.GetPubKey();
  1033. assert(key.VerifyPubKey(seed));
  1034. // set the hd keypath to "s" -> Seed, refers the seed to itself
  1035. metadata.hdKeypath = "s";
  1036. metadata.has_key_origin = false;
  1037. metadata.hd_seed_id = seed.GetID();
  1038. {
  1039. LOCK(cs_KeyStore);
  1040. // mem store the metadata
  1041. mapKeyMetadata[seed.GetID()] = metadata;
  1042. // write the key&metadata to the database
  1043. if (!AddKeyPubKey(key, seed))
  1044. throw std::runtime_error(std::string(__func__) + ": AddKeyPubKey failed");
  1045. }
  1046. return seed;
  1047. }
  1048. void LegacyScriptPubKeyMan::SetHDSeed(const CPubKey& seed)
  1049. {
  1050. LOCK(cs_KeyStore);
  1051. // store the keyid (hash160) together with
  1052. // the child index counter in the database
  1053. // as a hdchain object
  1054. CHDChain newHdChain;
  1055. newHdChain.nVersion = m_storage.CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
  1056. newHdChain.seed_id = seed.GetID();
  1057. AddHDChain(newHdChain);
  1058. NotifyCanGetAddressesChanged();
  1059. WalletBatch batch(m_storage.GetDatabase());
  1060. m_storage.UnsetBlankWalletFlag(batch);
  1061. }
  1062. /**
  1063. * Mark old keypool keys as used,
  1064. * and generate all new keys
  1065. */
  1066. bool LegacyScriptPubKeyMan::NewKeyPool()
  1067. {
  1068. if (m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
  1069. return false;
  1070. }
  1071. {
  1072. LOCK(cs_KeyStore);
  1073. WalletBatch batch(m_storage.GetDatabase());
  1074. for (const int64_t nIndex : setInternalKeyPool) {
  1075. batch.ErasePool(nIndex);
  1076. }
  1077. setInternalKeyPool.clear();
  1078. for (const int64_t nIndex : setExternalKeyPool) {
  1079. batch.ErasePool(nIndex);
  1080. }
  1081. setExternalKeyPool.clear();
  1082. for (const int64_t nIndex : set_pre_split_keypool) {
  1083. batch.ErasePool(nIndex);
  1084. }
  1085. set_pre_split_keypool.clear();
  1086. m_pool_key_to_index.clear();
  1087. if (!TopUp()) {
  1088. return false;
  1089. }
  1090. WalletLogPrintf("LegacyScriptPubKeyMan::NewKeyPool rewrote keypool\n");
  1091. }
  1092. return true;
  1093. }
  1094. bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize)
  1095. {
  1096. if (!CanGenerateKeys()) {
  1097. return false;
  1098. }
  1099. {
  1100. LOCK(cs_KeyStore);
  1101. if (m_storage.IsLocked()) return false;
  1102. // Top up key pool
  1103. unsigned int nTargetSize;
  1104. if (kpSize > 0)
  1105. nTargetSize = kpSize;
  1106. else
  1107. nTargetSize = std::max(gArgs.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 0);
  1108. // count amount of available keys (internal, external)
  1109. // make sure the keypool of external and internal keys fits the user selected target (-keypool)
  1110. int64_t missingExternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setExternalKeyPool.size(), (int64_t) 0);
  1111. int64_t missingInternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setInternalKeyPool.size(), (int64_t) 0);
  1112. if (!IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD_SPLIT))
  1113. {
  1114. // don't create extra internal keys
  1115. missingInternal = 0;
  1116. }
  1117. bool internal = false;
  1118. WalletBatch batch(m_storage.GetDatabase());
  1119. for (int64_t i = missingInternal + missingExternal; i--;)
  1120. {
  1121. if (i < missingInternal) {
  1122. internal = true;
  1123. }
  1124. CPubKey pubkey(GenerateNewKey(batch, m_hd_chain, internal));
  1125. AddKeypoolPubkeyWithDB(pubkey, internal, batch);
  1126. }
  1127. if (missingInternal + missingExternal > 0) {
  1128. 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());
  1129. }
  1130. }
  1131. NotifyCanGetAddressesChanged();
  1132. return true;
  1133. }
  1134. void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch)
  1135. {
  1136. LOCK(cs_KeyStore);
  1137. assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys?
  1138. int64_t index = ++m_max_keypool_index;
  1139. if (!batch.WritePool(index, CKeyPool(pubkey, internal))) {
  1140. throw std::runtime_error(std::string(__func__) + ": writing imported pubkey failed");
  1141. }
  1142. if (internal) {
  1143. setInternalKeyPool.insert(index);
  1144. } else {
  1145. setExternalKeyPool.insert(index);
  1146. }
  1147. m_pool_key_to_index[pubkey.GetID()] = index;
  1148. }
  1149. void LegacyScriptPubKeyMan::KeepDestination(int64_t nIndex, const OutputType& type)
  1150. {
  1151. assert(type != OutputType::BECH32M);
  1152. // Remove from key pool
  1153. WalletBatch batch(m_storage.GetDatabase());
  1154. batch.ErasePool(nIndex);
  1155. CPubKey pubkey;
  1156. bool have_pk = GetPubKey(m_index_to_reserved_key.at(nIndex), pubkey);
  1157. assert(have_pk);
  1158. LearnRelatedScripts(pubkey, type);
  1159. m_index_to_reserved_key.erase(nIndex);
  1160. WalletLogPrintf("keypool keep %d\n", nIndex);
  1161. }
  1162. void LegacyScriptPubKeyMan::ReturnDestination(int64_t nIndex, bool fInternal, const CTxDestination&)
  1163. {
  1164. // Return to key pool
  1165. {
  1166. LOCK(cs_KeyStore);
  1167. if (fInternal) {
  1168. setInternalKeyPool.insert(nIndex);
  1169. } else if (!set_pre_split_keypool.empty()) {
  1170. set_pre_split_keypool.insert(nIndex);
  1171. } else {
  1172. setExternalKeyPool.insert(nIndex);
  1173. }
  1174. CKeyID& pubkey_id = m_index_to_reserved_key.at(nIndex);
  1175. m_pool_key_to_index[pubkey_id] = nIndex;
  1176. m_index_to_reserved_key.erase(nIndex);
  1177. NotifyCanGetAddressesChanged();
  1178. }
  1179. WalletLogPrintf("keypool return %d\n", nIndex);
  1180. }
  1181. bool LegacyScriptPubKeyMan::GetKeyFromPool(CPubKey& result, const OutputType type, bool internal)
  1182. {
  1183. assert(type != OutputType::BECH32M);
  1184. if (!CanGetAddresses(internal)) {
  1185. return false;
  1186. }
  1187. CKeyPool keypool;
  1188. {
  1189. LOCK(cs_KeyStore);
  1190. int64_t nIndex;
  1191. if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) && !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
  1192. if (m_storage.IsLocked()) return false;
  1193. WalletBatch batch(m_storage.GetDatabase());
  1194. result = GenerateNewKey(batch, m_hd_chain, internal);
  1195. return true;
  1196. }
  1197. KeepDestination(nIndex, type);
  1198. result = keypool.vchPubKey;
  1199. }
  1200. return true;
  1201. }
  1202. bool LegacyScriptPubKeyMan::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
  1203. {
  1204. nIndex = -1;
  1205. keypool.vchPubKey = CPubKey();
  1206. {
  1207. LOCK(cs_KeyStore);
  1208. bool fReturningInternal = fRequestedInternal;
  1209. fReturningInternal &= (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) || m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
  1210. bool use_split_keypool = set_pre_split_keypool.empty();
  1211. std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
  1212. // Get the oldest key
  1213. if (setKeyPool.empty()) {
  1214. return false;
  1215. }
  1216. WalletBatch batch(m_storage.GetDatabase());
  1217. auto it = setKeyPool.begin();
  1218. nIndex = *it;
  1219. setKeyPool.erase(it);
  1220. if (!batch.ReadPool(nIndex, keypool)) {
  1221. throw std::runtime_error(std::string(__func__) + ": read failed");
  1222. }
  1223. CPubKey pk;
  1224. if (!GetPubKey(keypool.vchPubKey.GetID(), pk)) {
  1225. throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
  1226. }
  1227. // If the key was pre-split keypool, we don't care about what type it is
  1228. if (use_split_keypool && keypool.fInternal != fReturningInternal) {
  1229. throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified");
  1230. }
  1231. if (!keypool.vchPubKey.IsValid()) {
  1232. throw std::runtime_error(std::string(__func__) + ": keypool entry invalid");
  1233. }
  1234. assert(m_index_to_reserved_key.count(nIndex) == 0);
  1235. m_index_to_reserved_key[nIndex] = keypool.vchPubKey.GetID();
  1236. m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
  1237. WalletLogPrintf("keypool reserve %d\n", nIndex);
  1238. }

Large files files are truncated, but you can click here to view the full file