Repository: bitcoin/bitcoin
File: src/wallet/wallet.cpp (C++)

Code before:
        }
        ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
        return signer_spk_man->DisplayAddress(dest, signer);
    }
    return util::Error{_("There is no ScriptPubKeyManager for this address")};
}

bool CWallet::LockCoin(const COutPoint& output, WalletBatch* batch)
{
    AssertLockHeld(cs_wallet);
    setLockedCoins.insert(output);
    if (batch) {
        return batch->WriteLockedUTXO(output);
    }
    return true;
}

bool CWallet::UnlockCoin(const COutPoint& output, WalletBatch* batch)
{
    AssertLockHeld(cs_wallet);
    bool was_locked = setLockedCoins.erase(output);
    if (batch && was_locked) {
        return batch->EraseLockedUTXO(output);
    }
    return true;
}

bool CWallet::UnlockAllCoins()
{
    AssertLockHeld(cs_wallet);
    bool success = true;
    WalletBatch batch(GetDatabase());
    for (auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
        success &= batch.EraseLockedUTXO(*it);
    }
    setLockedCoins.clear();
    return success;
}

bool CWallet::IsLockedCoin(const COutPoint& output) const
{
    AssertLockHeld(cs_wallet);
    return setLockedCoins.count(output) > 0;
}

void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
{
    AssertLockHeld(cs_wallet);
    for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
         it != setLockedCoins.end(); it++) {
        COutPoint outpt = (*it);

Review comment (performance):
This isn't loading anything so the name is a bit odd. Perhaps instead of splitting:

```diff
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 6a40cfe97e..a633d7966e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2617,19 +2617,13 @@ util::Result<void> CWallet::DisplayAddress(const CTxDestination& dest)
     return util::Error{_("There is no ScriptPubKeyManager for this address")};
 }

-void CWallet::LoadLockedCoin(const COutPoint& coin, bool persistent)
+bool CWallet::LockCoin(const COutPoint& coin, bool persistent, bool persist_now)
 {
     AssertLockHeld(cs_wallet);
     m_locked_coins.emplace(coin, persistent);
-}
-
-bool CWallet::LockCoin(const COutPoint& output, bool persist)
-{
-    AssertLockHeld(cs_wallet);
-    LoadLockedCoin(output, persist);
-    if (persist) {
+    if (persistent && persist_now) {
         WalletBatch batch(GetDatabase());
-        return batch.WriteLockedUTXO(output);
+        return batch.WriteLockedUTXO(coin);
     }
     return true;
 }
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 7fe557f71d..7629de2f9a 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -548,8 +548,7 @@ public:
     util::Result<void> DisplayAddress(const CTxDestination& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);

     bool IsLockedCoin(const COutPoint& output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-    void LoadLockedCoin(const COutPoint& coin, bool persistent) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-    bool LockCoin(const COutPoint& output, bool persist) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+    bool LockCoin(const COutPoint& output, bool persistent, bool persist_now = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     bool UnlockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void ListLockedCoins(std::vector<COutPoint>& vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 0f0e228fc8..58f7409b58 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -1065,14 +1065,14 @@ static DBErrors LoadTxRecords(CWallet* pwallet, DatabaseBatch& batch, std::vecto
     });
     result = std::max(result, tx_res.m_result);

-    // Load locked utxo record
+    // Load utxo record and lock
     LoadResult locked_utxo_res = LoadRecords(pwallet, batch, DBKeys::LOCKED_UTXO,
         [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
         Txid hash;
         uint32_t n;
         key >> hash;
         key >> n;
-        pwallet->LoadLockedCoin(COutPoint(hash, n), /*persistent=*/true);
+        pwallet->LockCoin(COutPoint(hash, n), /*persistent=*/true, /*persist_now=*/false);
         return DBErrors::LOAD_OK;
     });
     result = std::max(result, locked_utxo_res.m_result);
```

Code after:
}

util::Result<void> CWallet::DisplayAddress(const CTxDestination& dest)
{
    CScript scriptPubKey = GetScriptForDestination(dest);
    for (const auto& spk_man : GetScriptPubKeyMans(scriptPubKey)) {
        auto signer_spk_man = dynamic_cast<ExternalSignerScriptPubKeyMan *>(spk_man);
        if (signer_spk_man == nullptr) {
            continue;
        }
        ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
        return signer_spk_man->DisplayAddress(dest, signer);
    }
    return util::Error{_("There is no ScriptPubKeyManager for this address")};
}

void CWallet::LoadLockedCoin(const COutPoint& coin, bool persistent)
{
    AssertLockHeld(cs_wallet);
    m_locked_coins.emplace(coin, persistent);
}

bool CWallet::LockCoin(const COutPoint& output, bool persist)
{
    AssertLockHeld(cs_wallet);
    LoadLockedCoin(output, persist);
    if (persist) {
        WalletBatch batch(GetDatabase());
        return batch.WriteLockedUTXO(output);
    }
    return true;
}

bool CWallet::UnlockCoin(const COutPoint& output)
{
    AssertLockHeld(cs_wallet);
    auto locked_coin_it = m_locked_coins.find(output);
    if (locked_coin_it != m_locked_coins.end()) {
        bool persisted = locked_coin_it->second;
        m_locked_coins.erase(locked_coin_it);
        if (persisted) {
            WalletBatch batch(GetDatabase());
            return batch.EraseLockedUTXO(output);
        }
    }
    return true;
}

bool CWallet::UnlockAllCoins()
{
    AssertLockHeld(cs_wallet);