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) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <bitcoin-build-config.h> // IWYU pragma: keep8#include <wallet/walletdb.h>10#include <common/system.h>11#include <key_io.h>12#include <primitives/transaction_identifier.h>13#include <protocol.h>14#include <script/script.h>15#include <serialize.h>16#include <sync.h>17#include <util/bip32.h>18#include <util/check.h>19#include <util/fs.h>20#include <util/time.h>21#include <util/translation.h>22#include <wallet/migrate.h>23#include <wallet/sqlite.h>24#include <wallet/wallet.h>26#include <atomic>27#include <optional>28#include <string>30namespace wallet {31namespace DBKeys {32const std::string ACENTRY{"acentry"};33const std::string ACTIVEEXTERNALSPK{"activeexternalspk"};34const std::string ACTIVEINTERNALSPK{"activeinternalspk"};35const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"};36const std::string BESTBLOCK{"bestblock"};37const std::string CRYPTED_KEY{"ckey"};38const std::string CSCRIPT{"cscript"};39const std::string DEFAULTKEY{"defaultkey"};40const std::string DESTDATA{"destdata"};41const std::string FLAGS{"flags"};42const std::string HDCHAIN{"hdchain"};43const std::string KEYMETA{"keymeta"};44const std::string KEY{"key"};45const std::string LOCKED_UTXO{"lockedutxo"};46const std::string MASTER_KEY{"mkey"};47const std::string MINVERSION{"minversion"};48const std::string NAME{"name"};49const std::string OLD_KEY{"wkey"};50const std::string ORDERPOSNEXT{"orderposnext"};51const std::string POOL{"pool"};52const std::string PURPOSE{"purpose"};53const std::string SETTINGS{"settings"};54const std::string TX{"tx"};55const std::string WTX_VARIANT{"wtxvariant"};56const std::string VERSION{"version"};57const std::string WALLETDESCRIPTOR{"walletdescriptor"};58const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"};59const std::string WALLETDESCRIPTORLHCACHE{"walletdescriptorlhcache"};60const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};61const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};62const std::string WATCHMETA{"watchmeta"};63const std::string WATCHS{"watchs"};64const std::unordered_set<std::string> LEGACY_TYPES{CRYPTED_KEY, CSCRIPT, DEFAULTKEY, HDCHAIN, KEYMETA, KEY, OLD_KEY, POOL, WATCHMETA, WATCHS};65} // namespace DBKeys67void LogDBInfo()68{69// Add useful DB information here. This will be printed during startup.70LogInfo("Using SQLite Version %s", SQLiteDatabaseVersion());71}73//74// WalletBatch75//77bool WalletBatch::WriteName(const std::string& strAddress, const std::string& strName)78{79return WriteIC(std::make_pair(DBKeys::NAME, strAddress), strName);80}82bool WalletBatch::EraseName(const std::string& strAddress)83{84// This should only be used for sending addresses, never for receiving addresses,85// receiving addresses must always have an address book entry if they're not change return.86return EraseIC(std::make_pair(DBKeys::NAME, strAddress));87}89bool WalletBatch::WritePurpose(const std::string& strAddress, const std::string& strPurpose)90{91return WriteIC(std::make_pair(DBKeys::PURPOSE, strAddress), strPurpose);92}94bool WalletBatch::ErasePurpose(const std::string& strAddress)95{96return EraseIC(std::make_pair(DBKeys::PURPOSE, strAddress));97}99bool WalletBatch::WriteFullTx(const CWalletTx& wtx)100{101const Txid txid = wtx.GetHash();102// Persist all witness variants. Including the canonical one103for (const auto& [wtxid, tx] : wtx.GetTxs()) {104if (!WriteWtxVariant(txid, tx)) return false;105}106return WriteIC(std::make_pair(DBKeys::TX, txid), wtx);107}109bool WalletBatch::EraseTx(Txid hash)110{111if (!EraseIC(std::make_pair(DBKeys::TX, hash.ToUint256()))) return false;112// Drop all witness variant records too, so none are left dangling113return m_batch->ErasePrefix(DataStream() << DBKeys::WTX_VARIANT << hash);114}116bool WalletBatch::WriteWtxVariant(const Txid& txid, const CTransactionRef& tx)117{118return WriteIC(std::make_pair(DBKeys::WTX_VARIANT, std::make_pair(txid, tx->GetWitnessHash())), TX_WITH_WITNESS(tx));119}121bool WalletBatch::WriteTxMetadata(const CWalletTx& wtx)122{123return WriteIC(std::make_pair(DBKeys::TX, wtx.GetHash()), wtx);124}126bool WalletBatch::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite)127{128return WriteIC(std::make_pair(DBKeys::KEYMETA, pubkey), meta, overwrite);129}131bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)132{133if (!WriteKeyMetadata(keyMeta, vchPubKey, false)) {134return false;135}137// hash pubkey/privkey to accelerate wallet load138const auto keypair_hash = Hash(vchPubKey, vchPrivKey);140return WriteIC(std::make_pair(DBKeys::KEY, vchPubKey), std::make_pair(vchPrivKey, keypair_hash), false);141}143bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey,144const std::vector<unsigned char>& vchCryptedSecret,145const CKeyMetadata &keyMeta)146{147if (!WriteKeyMetadata(keyMeta, vchPubKey, true)) {148return false;149}151// Compute a checksum of the encrypted key152uint256 checksum = Hash(vchCryptedSecret);154const auto key = std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey);155if (!WriteIC(key, std::make_pair(vchCryptedSecret, checksum), false)) {156// It may already exist, so try writing just the checksum157std::vector<unsigned char> val;158if (!m_batch->Read(key, val)) {159return false;160}161if (!WriteIC(key, std::make_pair(val, checksum), true)) {162return false;163}164}165EraseIC(std::make_pair(DBKeys::KEY, vchPubKey));166return true;167}169bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)170{171return WriteIC(std::make_pair(DBKeys::MASTER_KEY, nID), kMasterKey, true);172}174bool WalletBatch::EraseMasterKey(unsigned int id)175{176return EraseIC(std::make_pair(DBKeys::MASTER_KEY, id));177}179bool WalletBatch::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)180{181if (!WriteIC(std::make_pair(DBKeys::WATCHMETA, dest), keyMeta)) {182return false;183}184return WriteIC(std::make_pair(DBKeys::WATCHS, dest), uint8_t{'1'});185}187bool WalletBatch::WriteBestBlock(const CBlockLocator& locator)188{189WriteIC(DBKeys::BESTBLOCK, CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan190return WriteIC(DBKeys::BESTBLOCK_NOMERKLE, locator);191}193bool WalletBatch::ReadBestBlock(CBlockLocator& locator)194{195if (m_batch->Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) return true;196return m_batch->Read(DBKeys::BESTBLOCK_NOMERKLE, locator);197}199bool WalletBatch::IsEncrypted()200{201DataStream prefix;202prefix << DBKeys::MASTER_KEY;203if (auto cursor = m_batch->GetNewPrefixCursor(prefix)) {204DataStream k, v;205if (cursor->Next(k, v) == DatabaseCursor::Status::MORE) return true;206}207return false;208}210bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext)211{212return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext);213}215bool WalletBatch::WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal)216{217std::string key = internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK;218return WriteIC(make_pair(key, type), id);219}221bool WalletBatch::EraseActiveScriptPubKeyMan(uint8_t type, bool internal)222{223const std::string key{internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK};224return EraseIC(make_pair(key, type));225}227bool WalletBatch::WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey)228{229// hash pubkey/privkey to accelerate wallet load230const auto keypair_hash = Hash(pubkey, privkey);232return WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey)), std::make_pair(privkey, keypair_hash), false);233}235bool WalletBatch::WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector<unsigned char>& secret)236{237if (!WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORCKEY, std::make_pair(desc_id, pubkey)), secret, false)) {238return false;239}240EraseIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey)));241return true;242}244bool WalletBatch::WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor)245{246return WriteIC(make_pair(DBKeys::WALLETDESCRIPTOR, desc_id), descriptor);247}249bool WalletBatch::WriteDescriptorDerivedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index, uint32_t der_index)250{