mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 03:47:29 -03:00
wallet: descriptors setup, batch db operations
Instead of doing one db transaction per descriptor setup, batch all descriptors' setup writes in a single db txn. Speeding up the process and preventing the wallet from entering an inconsistent state if any of the intermediate transactions fail.
This commit is contained in:
parent
3eb769f150
commit
1f65241b73
4 changed files with 20 additions and 10 deletions
|
@ -2275,7 +2275,7 @@ bool DescriptorScriptPubKeyMan::AddDescriptorKeyWithDB(WalletBatch& batch, const
|
|||
}
|
||||
}
|
||||
|
||||
bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_key, OutputType addr_type, bool internal)
|
||||
bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(WalletBatch& batch, const CExtKey& master_key, OutputType addr_type, bool internal)
|
||||
{
|
||||
LOCK(cs_desc_man);
|
||||
assert(m_storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
|
||||
|
@ -2336,9 +2336,6 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_
|
|||
m_wallet_descriptor = w_desc;
|
||||
|
||||
// Store the master private key, and descriptor
|
||||
WalletBatch batch(m_storage.GetDatabase());
|
||||
if (!batch.TxnBegin()) throw std::runtime_error(std::string(__func__) + ": cannot start db transaction");
|
||||
|
||||
if (!AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey())) {
|
||||
throw std::runtime_error(std::string(__func__) + ": writing descriptor master private key failed");
|
||||
}
|
||||
|
@ -2350,8 +2347,6 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_
|
|||
TopUpWithDB(batch);
|
||||
|
||||
m_storage.UnsetBlankWalletFlag(batch);
|
||||
|
||||
if (!batch.TxnCommit()) throw std::runtime_error(std::string(__func__) + ": error committing db transaction");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -621,7 +621,7 @@ public:
|
|||
bool IsHDEnabled() const override;
|
||||
|
||||
//! Setup descriptors based on the given CExtkey
|
||||
bool SetupDescriptorGeneration(const CExtKey& master_key, OutputType addr_type, bool internal);
|
||||
bool SetupDescriptorGeneration(WalletBatch& batch, const CExtKey& master_key, OutputType addr_type, bool internal);
|
||||
|
||||
/** Provide a descriptor at setup time
|
||||
* Returns false if already setup or setup fails, true if setup is successful
|
||||
|
|
|
@ -3535,6 +3535,10 @@ 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) {
|
||||
auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, m_keypool_size));
|
||||
|
@ -3542,16 +3546,19 @@ void CWallet::SetupDescriptorScriptPubKeyMans(const CExtKey& master_key)
|
|||
if (IsLocked()) {
|
||||
throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
|
||||
}
|
||||
if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
|
||||
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(master_key, t, internal);
|
||||
spk_manager->SetupDescriptorGeneration(batch, master_key, t, internal);
|
||||
uint256 id = spk_manager->GetID();
|
||||
AddScriptPubKeyMan(id, std::move(spk_manager));
|
||||
AddActiveScriptPubKeyMan(id, t, internal);
|
||||
AddActiveScriptPubKeyManWithDb(batch, id, 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()
|
||||
|
@ -3606,6 +3613,11 @@ void CWallet::SetupDescriptorScriptPubKeyMans()
|
|||
void CWallet::AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
|
||||
{
|
||||
WalletBatch batch(GetDatabase());
|
||||
return AddActiveScriptPubKeyManWithDb(batch, id, type, internal);
|
||||
}
|
||||
|
||||
void CWallet::AddActiveScriptPubKeyManWithDb(WalletBatch& batch, uint256 id, OutputType type, bool internal)
|
||||
{
|
||||
if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
|
||||
throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
|
||||
}
|
||||
|
|
|
@ -419,6 +419,9 @@ private:
|
|||
// Must be the only method adding data to it.
|
||||
void AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKeyMan> spkm_man);
|
||||
|
||||
// Same as 'AddActiveScriptPubKeyMan' but designed for use within a batch transaction context
|
||||
void AddActiveScriptPubKeyManWithDb(WalletBatch& batch, uint256 id, OutputType type, bool internal);
|
||||
|
||||
/**
|
||||
* Catch wallet up to current chain, scanning new blocks, updating the best
|
||||
* block locator and m_last_block_processed, and registering for
|
||||
|
|
Loading…
Reference in a new issue