Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
751out.desc_spkms.push_back(std::move(desc_spk_man));752}754// Remove the scriptPubKeys from our current set755for (const CScript& desc_spk : desc_spks) {756auto del_it = spks.find(desc_spk);757assert(del_it != spks.end());758assert(IsMine(desc_spk));759it = spks.erase(del_it);760}761}763// Make sure that we have accounted for all scriptPubKeys764if (!Assume(spks.empty())) {765LogError("%s", STR_INTERNAL_BUG("Error: Some output scripts were not migrated."));766return std::nullopt;767}769// Legacy wallets can also contain scripts whose P2SH, P2WSH, or P2SH-P2WSH it is not watching for770// but can provide script data to a PSBT spending them. These "solvable" output scripts will need to771// be put into the separate "solvables" wallet.772// These can be detected by going through the entire candidate output scripts, finding the not IsMine scripts,773// and checking CanProvide() which will dummy sign.774for (const CScript& script : GetCandidateScriptPubKeys()) {775// Since we only care about P2SH, P2WSH, and P2SH-P2WSH, filter out any scripts that are not those776if (!script.IsPayToScriptHash() && !script.IsPayToWitnessScriptHash()) {777continue;778}779if (IsMine(script)) {780continue;781}782SignatureData dummy_sigdata;783if (!CanProvide(script, dummy_sigdata)) {784continue;785}787// Get birthdate from script meta788uint64_t creation_time = 0;789const auto& it = m_script_metadata.find(CScriptID(script));790if (it != m_script_metadata.end()) {791creation_time = it->second.nCreateTime;792}794// InferDescriptor as that will get us all the solving info if it is there795std::unique_ptr<Descriptor> desc = InferDescriptor(script, *GetSolvingProvider(script));796if (!desc->IsSolvable()) {797// The wallet was able to provide some information, but not enough to make a descriptor that actually798// contains anything useful. This is probably because the script itself is actually unsignable (e.g. P2WSH-P2WSH).799continue;800}802// Past bugs in InferDescriptor have caused it to create descriptors which cannot be re-parsed803// Re-parse the descriptors to detect that, and skip any that do not parse.804{805std::string desc_str = desc->ToString();806FlatSigningProvider parsed_keys;807std::string parse_error;808std::vector<std::unique_ptr<Descriptor>> parsed_descs = Parse(desc_str, parsed_keys, parse_error, false);809if (parsed_descs.empty()) {810continue;811}812}814out.solvable_descs.emplace_back(desc->ToString(), creation_time);815}817// Finalize transaction818if (!batch.TxnCommit()) {819LogWarning("Error generating descriptors for migration, cannot commit db transaction");820return std::nullopt;821}823return out;824}826bool LegacyDataSPKM::DeleteRecordsWithDB(WalletBatch& batch)827{828LOCK(cs_KeyStore);829return batch.EraseRecords(DBKeys::LEGACY_TYPES);830}832std::unique_ptr<DescriptorScriptPubKeyMan> DescriptorScriptPubKeyMan::CreateFromImport(WalletStorage& storage, WalletDescriptor& descriptor, int64_t keypool_size, const FlatSigningProvider& provider)833{834auto spkm = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(storage, descriptor, keypool_size));835LOCK(spkm->cs_desc_man);836WalletBatch batch(storage.GetDatabase());837spkm->UpdateWithSigningProvider(batch, provider);838return spkm;839}841std::unique_ptr<DescriptorScriptPubKeyMan> DescriptorScriptPubKeyMan::CreateFromMigration(WalletStorage& storage, WalletBatch& batch, WalletDescriptor& descriptor, int64_t keypool_size, const FlatSigningProvider& provider)842{843auto spkm = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(storage, descriptor, keypool_size));844LOCK(spkm->cs_desc_man);845spkm->UpdateWithSigningProvider(batch, provider);846return spkm;847}849DescriptorScriptPubKeyMan::DescriptorScriptPubKeyMan(WalletStorage& storage, const uint256& id, WalletDescriptor& descriptor, int64_t keypool_size, const KeyMap& keys, const CryptedKeyMap& ckeys)850: ScriptPubKeyMan(storage),851m_map_keys(keys),852m_map_crypted_keys(ckeys),853m_keypool_size(keypool_size),854m_id(id),855m_wallet_descriptor(descriptor)856{857if (!keys.empty() && !ckeys.empty()) {858throw std::runtime_error("Wallet contains both unencrypted and encrypted keys");859}860Load();861}863std::unique_ptr<DescriptorScriptPubKeyMan> DescriptorScriptPubKeyMan::LoadFromStorage(WalletStorage& storage, const uint256& id, WalletDescriptor& descriptor, int64_t keypool_size, const KeyMap& keys, const CryptedKeyMap& ckeys)864{865return std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(storage, id, descriptor, keypool_size, keys, ckeys));866}868std::unique_ptr<DescriptorScriptPubKeyMan> DescriptorScriptPubKeyMan::GenerateNewSingleSig(WalletStorage& storage, WalletBatch& batch, int64_t keypool_size, const CExtKey& master_key, OutputType addr_type, bool internal)869{870WalletDescriptor desc = GenerateWalletDescriptor(master_key.Neuter(), addr_type, internal);872auto spkm = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(storage, desc, keypool_size));874LOCK(spkm->cs_desc_man);875Assert(spkm->m_storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));877// Store the master private key, and descriptor878if (!spkm->AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey())) {879throw std::runtime_error(std::string(__func__) + ": writing descriptor master private key failed");880}881if (!batch.WriteDescriptor(spkm->GetID(), spkm->m_wallet_descriptor)) {882throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");883}885// Set m_decryption_thoroughly_checked for encrypted wallets886if (spkm->m_storage.HasEncryptionKeys()) {887spkm->m_decryption_thoroughly_checked = true;888}890// TopUp891spkm->TopUpWithDB(batch);893spkm->m_storage.UnsetBlankWalletFlag(batch);894return spkm;895}897void DescriptorScriptPubKeyMan::IncIndex()898{899AssertLockHeld(cs_desc_man);901const auto old_can = CanGetAddresses();902m_wallet_descriptor.IncNext();903const auto new_can = CanGetAddresses();904if (old_can != new_can) {905NotifyCanGetAddressesChanged();906}907}909void DescriptorScriptPubKeyMan::DecIndex()910{911AssertLockHeld(cs_desc_man);913const auto old_can = CanGetAddresses();914m_wallet_descriptor.DecNext();915const auto new_can = CanGetAddresses();916if (old_can != new_can) {917NotifyCanGetAddressesChanged();918}919}921void DescriptorScriptPubKeyMan::SetRangeEnd(int32_t end)922{923AssertLockHeld(cs_desc_man);925const auto old_can = CanGetAddresses();926m_wallet_descriptor.SetEnd(end);927const auto new_can = CanGetAddresses();928if (old_can != new_can) {929NotifyCanGetAddressesChanged();930}931}933util::Result<CTxDestination> DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type)934{935// Returns true if this descriptor supports getting new addresses. Conditions where we may be unable to fetch them (e.g. locked) are caught later936if (!CanGetAddresses()) {937return util::Error{_("No addresses available")};938}939{940LOCK(cs_desc_man);941assert(m_wallet_descriptor.descriptor->IsSingleType()); // This is a combo descriptor which should not be an active descriptor942std::optional<OutputType> desc_addr_type = m_wallet_descriptor.descriptor->GetOutputType();943assert(desc_addr_type);944if (type != *desc_addr_type) {945throw std::runtime_error(std::string(__func__) + ": Types are inconsistent. Stored type does not match type of newly generated address");946}948TopUp();950// Get the scriptPubKey from the descriptor951FlatSigningProvider out_keys;952std::vector<CScript> scripts_temp;953if (m_wallet_descriptor.GetEnd() <= m_max_cached_index && !TopUp(1)) {954// We can't generate anymore keys955return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};956}957if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.GetNext(), m_wallet_descriptor.cache, scripts_temp, out_keys)) {958// We can't generate anymore keys959return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};960}962CTxDestination dest;963if (!ExtractDestination(scripts_temp[0], dest)) {964return util::Error{_("Error: Cannot extract destination from the generated scriptpubkey")}; // shouldn't happen965}966IncIndex();967WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);968return dest;969}970}972bool DescriptorScriptPubKeyMan::IsMine(const CScript& script) const973{974LOCK(cs_desc_man);975return m_map_script_pub_keys.contains(script);976}978bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key)979{980LOCK(cs_desc_man);981if (!m_map_keys.empty()) {982return false;983}985bool keyPass = m_map_crypted_keys.empty(); // Always pass when there are no encrypted keys986bool keyFail = false;987for (const auto& mi : m_map_crypted_keys) {988const CPubKey &pubkey = mi.second.first;989const std::vector<unsigned char> &crypted_secret = mi.second.second;990CKey key;991if (!DecryptKey(master_key, crypted_secret, pubkey, key)) {992keyFail = true;993break;994}995keyPass = true;996if (m_decryption_thoroughly_checked)997break;998}999if (keyPass && keyFail) {1000LogWarning("The wallet is probably corrupted: Some keys decrypt but not all.");