Skip to content

Commit

Permalink
wallet: batch MigrateToDescriptor() db transactions
Browse files Browse the repository at this point in the history
Grouping all the process db writes into a single atomic
write operation.

Speeding up the flow and preventing inconsistent states.

The descriptors migration process must either succeed or
fail, no other outcomes should be allowed.
  • Loading branch information
furszy committed Oct 1, 2023
1 parent bd41cc0 commit 1f43d7e
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
23 changes: 18 additions & 5 deletions src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1778,6 +1778,12 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
keyid_it++;
}

WalletBatch batch(m_storage.GetDatabase());
if (!batch.TxnBegin()) {
error("Error during descriptors migration, cannot initialize db transaction");
return std::nullopt;
}

// keyids is now all non-HD keys. Each key will have its own combo descriptor
for (const CKeyID& keyid : keyids) {
CKey key;
Expand Down Expand Up @@ -1807,8 +1813,8 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()

// Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
auto desc_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(m_storage, w_desc, m_keypool_size));
desc_spk_man->AddDescriptorKey(key, key.GetPubKey());
desc_spk_man->TopUp();
WITH_LOCK(desc_spk_man->cs_desc_man, desc_spk_man->AddDescriptorKeyWithDB(batch, key, key.GetPubKey()));
desc_spk_man->TopUpWithDb(batch);
auto desc_spks = desc_spk_man->GetScriptPubKeys();

// Remove the scriptPubKeys from our current set
Expand Down Expand Up @@ -1852,8 +1858,8 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()

// Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
auto desc_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(m_storage, w_desc, m_keypool_size));
desc_spk_man->AddDescriptorKey(master_key.key, master_key.key.GetPubKey());
desc_spk_man->TopUp();
WITH_LOCK(desc_spk_man->cs_desc_man, desc_spk_man->AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey()));
desc_spk_man->TopUpWithDb(batch);
auto desc_spks = desc_spk_man->GetScriptPubKeys();

// Remove the scriptPubKeys from our current set
Expand Down Expand Up @@ -1919,7 +1925,7 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
if (!GetKey(keyid, key)) {
continue;
}
desc_spk_man->AddDescriptorKey(key, key.GetPubKey());
WITH_LOCK(desc_spk_man->cs_desc_man, desc_spk_man->AddDescriptorKeyWithDB(batch, key, key.GetPubKey()));
}
desc_spk_man->TopUp();
auto desc_spks_set = desc_spk_man->GetScriptPubKeys();
Expand Down Expand Up @@ -1988,6 +1994,13 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()

// Make sure that we have accounted for all scriptPubKeys
assert(spks.size() == 0);

// Finalize transaction
if (!batch.TxnCommit()) {
error("Error during descriptors migration, cannot commit db transaction");
return std::nullopt;
}

return out;
}

Expand Down
1 change: 1 addition & 0 deletions src/wallet/scriptpubkeyman.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ class LegacySigningProvider : public SigningProvider

class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
{
friend class LegacyScriptPubKeyMan;
private:
using ScriptPubKeyMap = std::map<CScript, int32_t>; // Map of scripts to descriptor range index
using PubKeyMap = std::map<CPubKey, int32_t>; // Map of pubkeys involved in scripts to descriptor range index
Expand Down

0 comments on commit 1f43d7e

Please sign in to comment.