Skip to content

Commit 0f5e31c

Browse files
committed
Merge bitcoin/bitcoin#28799: wallet: cache descriptor ID to avoid repeated descriptor string creation
5e6bc6d test: remove custom rpc timeout for `wallet_miniscript.py`, reorder in test_runner (Sebastian Falbesoner) f811a24 wallet: cache descriptor ID to avoid repeated descriptor string creation (Sebastian Falbesoner) Pull request description: Right now a wallet descriptor is converted to its string representation (via `Descriptor::ToString`) repeatedly at different instances: - on finding a `DescriptorScriptPubKeyMan` for a given descriptor (`CWallet::GetDescriptorScriptPubKeyMan`, e.g. used by the `importdescriptors` RPC); the string representation is created once for each spkm in the wallet and at each iteration again for the searched descriptor (`DescriptorScriptPubKeyMan::HasWalletDescriptor`) - whenever `DescriptorScriptPubKeyMan::GetID()` is called, e.g. in `TopUp` or any instances where a descriptor is written to the DB to determine the database key, also at less obvious places like `FastWalletRescanFilter` etc. As there is no good reason to calculate a fixed descriptor's string/ID more than once, add the ID as a field to `WalletDescriptor` and calculate it immediately at initialization (or deserialization). `HasWalletDescriptor` is changed to compare the spkm's and searched descriptor's ID instead of the string to take use of that. This speeds up the functional test `wallet_miniscript.py` by a factor of 5-6x on my machine (3m30.95s on master vs. 0m38.02s on PR). The recently introduced "max-size TapMiniscript" test-case introduced a descriptor that takes 2-3 seconds to create a string representation, so the repeated calls to that were significantly hurting the performance. Fixes bitcoin/bitcoin#28800. ACKs for top commit: Sjors: ACK 5e6bc6d S3RK: Code Review ACK 5e6bc6d achow101: ACK 5e6bc6d BrandonOdiwuor: ACK 5e6bc6d Tree-SHA512: 98b43963a5dde6055bb26cecd3b878dadd837d6226af4c84142383310495da80b3c4bd552e73b9107f2f2ff1c11f5e18060c6fd3d9e44bbd5224114c4d245c1c
2 parents 4cebad4 + 5e6bc6d commit 0f5e31c

File tree

4 files changed

+6
-5
lines changed

4 files changed

+6
-5
lines changed

src/wallet/scriptpubkeyman.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2601,7 +2601,7 @@ std::unique_ptr<CKeyMetadata> DescriptorScriptPubKeyMan::GetMetadata(const CTxDe
26012601
uint256 DescriptorScriptPubKeyMan::GetID() const
26022602
{
26032603
LOCK(cs_desc_man);
2604-
return DescriptorID(*m_wallet_descriptor.descriptor);
2604+
return m_wallet_descriptor.id;
26052605
}
26062606

26072607
void DescriptorScriptPubKeyMan::SetCache(const DescriptorCache& cache)
@@ -2655,7 +2655,7 @@ bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKe
26552655
bool DescriptorScriptPubKeyMan::HasWalletDescriptor(const WalletDescriptor& desc) const
26562656
{
26572657
LOCK(cs_desc_man);
2658-
return m_wallet_descriptor.descriptor != nullptr && desc.descriptor != nullptr && m_wallet_descriptor.descriptor->ToString() == desc.descriptor->ToString();
2658+
return !m_wallet_descriptor.id.IsNull() && !desc.id.IsNull() && m_wallet_descriptor.id == desc.id;
26592659
}
26602660

26612661
void DescriptorScriptPubKeyMan::WriteDescriptor()

src/wallet/walletutil.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class WalletDescriptor
8585
{
8686
public:
8787
std::shared_ptr<Descriptor> descriptor;
88+
uint256 id; // Descriptor ID (calculated once at descriptor initialization/deserialization)
8889
uint64_t creation_time = 0;
8990
int32_t range_start = 0; // First item in range; start of range, inclusive, i.e. [range_start, range_end). This never changes.
9091
int32_t range_end = 0; // Item after the last; end of range, exclusive, i.e. [range_start, range_end). This will increment with each TopUp()
@@ -99,6 +100,7 @@ class WalletDescriptor
99100
if (!descriptor) {
100101
throw std::ios_base::failure("Invalid descriptor: " + error);
101102
}
103+
id = DescriptorID(*descriptor);
102104
}
103105

104106
SERIALIZE_METHODS(WalletDescriptor, obj)
@@ -110,7 +112,7 @@ class WalletDescriptor
110112
}
111113

112114
WalletDescriptor() {}
113-
WalletDescriptor(std::shared_ptr<Descriptor> descriptor, uint64_t creation_time, int32_t range_start, int32_t range_end, int32_t next_index) : descriptor(descriptor), creation_time(creation_time), range_start(range_start), range_end(range_end), next_index(next_index) {}
115+
WalletDescriptor(std::shared_ptr<Descriptor> descriptor, uint64_t creation_time, int32_t range_start, int32_t range_end, int32_t next_index) : descriptor(descriptor), id(DescriptorID(*descriptor)), creation_time(creation_time), range_start(range_start), range_end(range_end), next_index(next_index) { }
114116
};
115117
} // namespace wallet
116118

test/functional/test_runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@
105105
'feature_maxuploadtarget.py',
106106
'mempool_updatefromblock.py',
107107
'mempool_persist.py --descriptors',
108-
'wallet_miniscript.py --descriptors',
109108
# vv Tests less than 60s vv
110109
'rpc_psbt.py --legacy-wallet',
111110
'rpc_psbt.py --descriptors',
@@ -149,6 +148,7 @@
149148
'p2p_sendheaders.py',
150149
'wallet_listtransactions.py --legacy-wallet',
151150
'wallet_listtransactions.py --descriptors',
151+
'wallet_miniscript.py --descriptors',
152152
# vv Tests less than 30s vv
153153
'p2p_invalid_messages.py',
154154
'rpc_createmultisig.py',

test/functional/wallet_miniscript.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@
205205
class WalletMiniscriptTest(BitcoinTestFramework):
206206
def add_options(self, parser):
207207
self.add_wallet_options(parser, legacy=False)
208-
self.rpc_timeout = 480
209208

210209
def set_test_params(self):
211210
self.num_nodes = 1

0 commit comments

Comments
 (0)