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.
1// Copyright (c) 2017-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <wallet/walletutil.h>7#include <chainparams.h>8#include <common/args.h>9#include <key_io.h>10#include <util/log.h>12namespace wallet {13fs::path GetWalletDir()14{15fs::path path;17if (gArgs.IsArgSet("-walletdir")) {18path = gArgs.GetPathArg("-walletdir");19if (!fs::is_directory(path)) {20// If the path specified doesn't exist, we return the deliberately21// invalid empty string.22path = "";23}24} else {25path = gArgs.GetDataDirNet();26// If a wallets directory exists, use that, otherwise default to GetDataDir27if (fs::is_directory(path / "wallets")) {28path /= "wallets";29}30}32return path;33}35WalletDescriptor GenerateWalletDescriptor(const CExtPubKey& master_key, const OutputType& addr_type, bool internal)36{37int64_t creation_time = GetTime();39std::string xpub = EncodeExtPubKey(master_key);41// Build descriptor string42std::string desc_prefix;43std::string desc_suffix = "/*)";44switch (addr_type) {45case OutputType::LEGACY: {46desc_prefix = "pkh(" + xpub + "/44h";47break;48}49case OutputType::P2SH_SEGWIT: {50desc_prefix = "sh(wpkh(" + xpub + "/49h";51desc_suffix += ")";52break;53}54case OutputType::BECH32: {55desc_prefix = "wpkh(" + xpub + "/84h";56break;57}58case OutputType::BECH32M: {59desc_prefix = "tr(" + xpub + "/86h";60break;61}62case OutputType::UNKNOWN: {63// We should never have a DescriptorScriptPubKeyMan for an UNKNOWN OutputType,64// so if we get to this point something is wrong65assert(false);66}67} // no default case, so the compiler can warn about missing cases68assert(!desc_prefix.empty());70// Mainnet derives at 0', testnet and regtest derive at 1'71if (Params().IsTestChain()) {72desc_prefix += "/1h";73} else {74desc_prefix += "/0h";75}77std::string internal_path = internal ? "/1" : "/0";78std::string desc_str = desc_prefix + "/0h" + internal_path + desc_suffix;80// Make the descriptor81FlatSigningProvider keys;82std::string error;83std::vector<std::unique_ptr<Descriptor>> desc = Parse(desc_str, keys, error, false);84WalletDescriptor w_desc(std::move(desc.at(0)), creation_time, 0, 0, 0);85return w_desc;86}88void WalletDescriptor::UpdateFrom(const WalletDescriptor& other)89{90if (!IsCanonicallyEquivalent(other)) {91return;92}93range_start = other.range_start;94next_index = other.next_index;95range_end = other.range_end;96creation_time = other.creation_time;97cache = other.cache;98}100uint256 WalletDescriptor::GetCanonicalHash() const101{102if (!m_canonical_hash) {103m_canonical_hash.emplace();104std::string canonical = descriptor->ToCanonicalString();105CSHA256().Write((unsigned char*)canonical.data(), canonical.size()).Finalize(m_canonical_hash->begin());106}107return *m_canonical_hash;108}110bool WalletDescriptor::IsCanonicallyEquivalent(const WalletDescriptor& other) const111{112return GetCanonicalHash() == other.GetCanonicalHash();113}115} // namespace wallet