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

Code before:

void CWallet::SetupDescriptorScriptPubKeyMans(const CExtKey& master_key)
{
    AssertLockHeld(cs_wallet);

    // Create single batch txn
    WalletBatch batch(GetDatabase());
    if (!batch.TxnBegin()) throw std::runtime_error("Error: cannot create db transaction for descriptors setup");

    for (bool internal : {false, true}) {
        for (OutputType t : OUTPUT_TYPES) {
            SetupDescriptorScriptPubKeyMan(batch, master_key, t, internal);
        }
    }

    // Ensure information is committed to disk
    if (!batch.TxnCommit()) throw std::runtime_error("Error: cannot commit db transaction for descriptors setup");
}

void CWallet::SetupDescriptorScriptPubKeyMans()
{
    AssertLockHeld(cs_wallet);

    if (!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
        // Make a seed
        CKey seed_key = GenerateRandomKey();
        CPubKey seed = seed_key.GetPubKey();
        assert(seed_key.VerifyPubKey(seed));

        // Get the extended key
        CExtKey master_key;
        master_key.SetSeed(seed_key);

        SetupDescriptorScriptPubKeyMans(master_key);
    } else {
        ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();

        // TODO: add account parameter
        int account = 0;
        UniValue signer_res = signer.GetDescriptors(account);

        if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");

        WalletBatch batch(GetDatabase());
        if (!batch.TxnBegin()) throw std::runtime_error("Error: cannot create db transaction for descriptors import");

        for (bool internal : {false, true}) {
            const UniValue& descriptor_vals = signer_res.find_value(internal ? "internal" : "receive");
            if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
            for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
                const std::string& desc_str = desc_val.getValStr();

Review comment (suggestion):
could add a lock assertion here (since the method has the `EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);` annotation)
```suggestion
void CWallet::SetupOwnDescriptorScriptPubKeyMans()
{
    AssertLockHeld(cs_wallet);

    assert(!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
```

Code after:
        if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, &batch)) {
            throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
        }
    }
    spk_manager->SetupDescriptorGeneration(batch, master_key, output_type, internal);
    DescriptorScriptPubKeyMan* out = spk_manager.get();
    uint256 id = spk_manager->GetID();
    AddScriptPubKeyMan(id, std::move(spk_manager));
    AddActiveScriptPubKeyManWithDb(batch, id, output_type, internal);
    return *out;
}

void CWallet::SetupDescriptorScriptPubKeyMans(WalletBatch& batch, const CExtKey& master_key)
{
    AssertLockHeld(cs_wallet);
    for (bool internal : {false, true}) {
        for (OutputType t : OUTPUT_TYPES) {
            SetupDescriptorScriptPubKeyMan(batch, master_key, t, internal);
        }
    }
}

void CWallet::SetupOwnDescriptorScriptPubKeyMans(WalletBatch& batch)
{
    AssertLockHeld(cs_wallet);
    assert(!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
    // Make a seed
    CKey seed_key = GenerateRandomKey();
    CPubKey seed = seed_key.GetPubKey();
    assert(seed_key.VerifyPubKey(seed));

    // Get the extended key
    CExtKey master_key;
    master_key.SetSeed(seed_key);

    SetupDescriptorScriptPubKeyMans(batch, master_key);
}

void CWallet::SetupDescriptorScriptPubKeyMans()
{
    AssertLockHeld(cs_wallet);

    if (!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
        if (!RunWithinTxn(GetDatabase(), /*process_desc=*/"setup descriptors", [&](WalletBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet){
            SetupOwnDescriptorScriptPubKeyMans(batch);
            return true;
        })) throw std::runtime_error("Error: cannot process db transaction for descriptors setup");
    } else {
        ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();

        // TODO: add account parameter