@@ -1533,9 +1533,99 @@ void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal,
1533
1533
{
1534
1534
}
1535
1535
1536
+ std::map<CKeyID, CKey> DescriptorScriptPubKeyMan::GetKeys () const
1537
+ {
1538
+ AssertLockHeld (cs_desc_man);
1539
+ if (m_storage.HasEncryptionKeys () && !m_storage.IsLocked ()) {
1540
+ KeyMap keys;
1541
+ for (auto key_pair : m_map_crypted_keys) {
1542
+ const CPubKey& pubkey = key_pair.second .first ;
1543
+ const std::vector<unsigned char >& crypted_secret = key_pair.second .second ;
1544
+ CKey key;
1545
+ DecryptKey (m_storage.GetEncryptionKey (), crypted_secret, pubkey, key);
1546
+ keys[pubkey.GetID ()] = key;
1547
+ }
1548
+ return keys;
1549
+ }
1550
+ return m_map_keys;
1551
+ }
1552
+
1536
1553
bool DescriptorScriptPubKeyMan::TopUp (unsigned int size)
1537
1554
{
1538
- return false ;
1555
+ LOCK (cs_desc_man);
1556
+ unsigned int target_size;
1557
+ if (size > 0 ) {
1558
+ target_size = size;
1559
+ } else {
1560
+ target_size = std::max (gArgs .GetArg (" -keypool" , DEFAULT_KEYPOOL_SIZE), (int64_t ) 1 );
1561
+ }
1562
+
1563
+ // Calculate the new range_end
1564
+ int32_t new_range_end = std::max (m_wallet_descriptor.next_index + (int32_t )target_size, m_wallet_descriptor.range_end );
1565
+
1566
+ // If the descriptor is not ranged, we actually just want to fill the first cache item
1567
+ if (!m_wallet_descriptor.descriptor ->IsRange ()) {
1568
+ new_range_end = 1 ;
1569
+ m_wallet_descriptor.range_end = 1 ;
1570
+ m_wallet_descriptor.range_start = 0 ;
1571
+ }
1572
+
1573
+ FlatSigningProvider provider;
1574
+ provider.keys = GetKeys ();
1575
+
1576
+ WalletBatch batch (m_storage.GetDatabase ());
1577
+ uint256 id = GetID ();
1578
+ for (int32_t i = m_max_cached_index + 1 ; i < new_range_end; ++i) {
1579
+ FlatSigningProvider out_keys;
1580
+ std::vector<CScript> scripts_temp;
1581
+ DescriptorCache temp_cache;
1582
+ // Maybe we have a cached xpub and we can expand from the cache first
1583
+ if (!m_wallet_descriptor.descriptor ->ExpandFromCache (i, m_wallet_descriptor.cache , scripts_temp, out_keys)) {
1584
+ if (!m_wallet_descriptor.descriptor ->Expand (i, provider, scripts_temp, out_keys, &temp_cache)) return false ;
1585
+ }
1586
+ // Add all of the scriptPubKeys to the scriptPubKey set
1587
+ for (const CScript& script : scripts_temp) {
1588
+ m_map_script_pub_keys[script] = i;
1589
+ }
1590
+ // Write the cache
1591
+ for (const auto & parent_xpub_pair : temp_cache.GetCachedParentExtPubKeys ()) {
1592
+ CExtPubKey xpub;
1593
+ if (m_wallet_descriptor.cache .GetCachedParentExtPubKey (parent_xpub_pair.first , xpub)) {
1594
+ if (xpub != parent_xpub_pair.second ) {
1595
+ throw std::runtime_error (std::string (__func__) + " : New cached parent xpub does not match already cached parent xpub" );
1596
+ }
1597
+ continue ;
1598
+ }
1599
+ if (!batch.WriteDescriptorParentCache (parent_xpub_pair.second , id, parent_xpub_pair.first )) {
1600
+ throw std::runtime_error (std::string (__func__) + " : writing cache item failed" );
1601
+ }
1602
+ m_wallet_descriptor.cache .CacheParentExtPubKey (parent_xpub_pair.first , parent_xpub_pair.second );
1603
+ }
1604
+ for (const auto & derived_xpub_map_pair : temp_cache.GetCachedDerivedExtPubKeys ()) {
1605
+ for (const auto & derived_xpub_pair : derived_xpub_map_pair.second ) {
1606
+ CExtPubKey xpub;
1607
+ if (m_wallet_descriptor.cache .GetCachedDerivedExtPubKey (derived_xpub_map_pair.first , derived_xpub_pair.first , xpub)) {
1608
+ if (xpub != derived_xpub_pair.second ) {
1609
+ throw std::runtime_error (std::string (__func__) + " : New cached derived xpub does not match already cached derived xpub" );
1610
+ }
1611
+ continue ;
1612
+ }
1613
+ if (!batch.WriteDescriptorDerivedCache (derived_xpub_pair.second , id, derived_xpub_map_pair.first , derived_xpub_pair.first )) {
1614
+ throw std::runtime_error (std::string (__func__) + " : writing cache item failed" );
1615
+ }
1616
+ m_wallet_descriptor.cache .CacheDerivedExtPubKey (derived_xpub_map_pair.first , derived_xpub_pair.first , derived_xpub_pair.second );
1617
+ }
1618
+ }
1619
+ m_max_cached_index++;
1620
+ }
1621
+ m_wallet_descriptor.range_end = new_range_end;
1622
+ batch.WriteDescriptor (GetID (), m_wallet_descriptor);
1623
+
1624
+ // By this point, the cache size should be the size of the entire range
1625
+ assert (m_wallet_descriptor.range_end - 1 == m_max_cached_index);
1626
+
1627
+ NotifyCanGetAddressesChanged ();
1628
+ return true ;
1539
1629
}
1540
1630
1541
1631
void DescriptorScriptPubKeyMan::MarkUnusedAddresses (const CScript& script)
@@ -1753,6 +1843,7 @@ void DescriptorScriptPubKeyMan::SetCache(const DescriptorCache& cache)
1753
1843
}
1754
1844
m_map_script_pub_keys[script] = i;
1755
1845
}
1846
+ m_max_cached_index++;
1756
1847
}
1757
1848
}
1758
1849
0 commit comments