Skip to content

Commit e270286

Browse files
Merge #7101: feat!: migrate additional indexes from synchronous to async operation
cc1dd3c fix: harden index migration and document timestampindex prune caveat (UdjinM6) 0695e97 refactor: move BlockDisconnected handling to BaseIndex (UdjinM6) c41584e refactor: move BlockUntilSyncedToCurrentChain from index queries to RPC callers (UdjinM6) 1ca7374 fix: harden BlockDisconnected sibling check and getaddressbalance height race (UdjinM6) 386acdf fix: add undo data size validation in AddressIndex::Rewind (UdjinM6) 5796588 fix: reverse transaction processing order in AddressIndex::Rewind (UdjinM6) 8f3f62b fix: add vtxundo size validation in SpentIndex::WriteBlock (UdjinM6) 97dcc6d fix: address review suggestions (UdjinM6) 331335e fix: add explicit vtxundo size validation and in-class initialization for m_block_height (UdjinM6) 98c3c1b fix: check index sync status before querying and show sync progress (UdjinM6) e84b1fa feat: add async indexes to getindexinfo RPC (UdjinM6) 5be629b refactor: apply clang-format (UdjinM6) fd1de98 refactor: address code review feedback (UdjinM6) 5fd7033 docs: add release notes (UdjinM6) 6e5f7ab fix: add missing include in `src/zmq/zmqpublishnotifier.cpp` (UdjinM6) fa60ccb feat: migrate old synchronous index data to new async index databases (UdjinM6) fa7be34 feat: add CompactRange template method to CDBWrapper (UdjinM6) 8ad06be test: update feature_addressindex for async behavior (UdjinM6) 18276a6 feat: migrate AddressIndex from synchronous to async operation (UdjinM6) 3ea9394 test: update feature_spentindex for async behavior (UdjinM6) 464cdf8 feat: migrate SpentIndex from synchronous to async operation (UdjinM6) 33d2fc5 test: update timestampindex functional test for async behavior (UdjinM6) f3fcb97 feat: migrate TimestampIndex from synchronous to async operation (UdjinM6) Pull request description: ## Issue being fixed or feature implemented Migrate three Dash-specific indexes (`AddressIndex`, `SpentIndex`, `TimestampIndex`) from synchronous operation in `CBlockTreeDB` to async operation using `BaseIndex` framework. When enabling an index for the first time, the node will build the index in the background while remaining fully operational. Progress can be monitored via the `getindexinfo` RPC. Existing nodes with indexes enabled will automatically migrate data from the old location (block index database) to new separate databases on first startup. This migration may take 20-40 minutes or longer depending on hardware specifications and index sizes. The node will log progress during migration. ## What was done? Architecture Improvements: - Indexes now derive from `BaseIndex`, enabling async catch-up during IBD - Each index has its own database under `indexes/{addressindex,spentindex,timestampindex}/` - No longer blocks validation during index updates - Can be enabled/disabled without `-reindex` Migration System: - Template-based `MigrateIndex<>()` function handles data migration - Threshold-based incremental compaction (256 MiB) to reclaim disk space - Iterator reset before compaction to allow LevelDB file deletion - Best block locator written to ensure index consistency ## How Has This Been Tested? Run tests. Run a testnet/mainnet node and confirm migration succeeds (backup old datadir cause otherwise you'd have to reindex to go back to develop/master binaries). ## Breaking Changes - `SpentIndex` and `AddressIndex` are incompatible with pruned nodes as they require access to undo data now - `TimestampIndex` can no longer be enabled on a datadir where pruning has already occurred. It still works when started together with `-prune` from a fresh sync or reindex (the index is built forward as blocks arrive), but enabling it on an existing pre-pruned datadir now fails at startup. The old synchronous implementation built forward from the current tip and accepted that case ## Checklist: - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ Top commit has no ACKs. Tree-SHA512: b0129ffdec086883c7a8a10fbeec891b6588523e567d1fc083da96eef53b2bf2c72d4249f0d8420174b03bc58652a9fa68ecdb3e55dc9160b0630dda0f282d7e
2 parents 28a9a08 + cc1dd3c commit e270286

47 files changed

Lines changed: 2029 additions & 1130 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

doc/release-notes-7101.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Indexes
2+
3+
### Async Index Migration (#7101)
4+
5+
`TimestampIndex`, `SpentIndex`, and `AddressIndex` have been migrated from synchronous to asynchronous operation, following the same pattern as `TxIndex` and other indexes using `BaseIndex` framework.
6+
7+
When enabling an index for the first time, the node will build the index in the background while remaining fully operational. Progress can be monitored via the `getindexinfo` RPC.
8+
9+
Existing nodes with indexes enabled will automatically migrate data from the old location (block index database) to new separate databases on first startup. This migration may take 20-40 minutes or longer depending on hardware specifications and index sizes. The node will log progress during migration.
10+
11+
Breaking changes:
12+
- `SpentIndex` and `AddressIndex` are incompatible with pruned nodes as they require access to undo data now
13+
- `TimestampIndex` can no longer be enabled on a datadir where pruning has already occurred. It still works when started together with `-prune` from a fresh sync or reindex (the index is built forward as blocks arrive), but enabling it on an existing pre-pruned datadir now fails at startup. The old synchronous implementation built forward from the current tip and accepted that case

src/Makefile.am

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,6 @@ BITCOIN_CORE_H = \
160160
active/dkgsessionhandler.h \
161161
active/masternode.h \
162162
addrdb.h \
163-
addressindex.h \
164-
spentindex.h \
165163
addrman.h \
166164
addrman_impl.h \
167165
attributes.h \
@@ -250,10 +248,17 @@ BITCOIN_CORE_H = \
250248
httprpc.h \
251249
httpserver.h \
252250
i2p.h \
251+
index/addressindex.h \
252+
index/addressindex_types.h \
253+
index/addressindex_util.h \
253254
index/base.h \
254255
index/blockfilterindex.h \
255256
index/coinstatsindex.h \
256257
index/disktxpos.h \
258+
index/spentindex.h \
259+
index/spentindex_types.h \
260+
index/timestampindex.h \
261+
index/timestampindex_types.h \
257262
index/txindex.h \
258263
indirectmap.h \
259264
init.h \
@@ -348,7 +353,6 @@ BITCOIN_CORE_H = \
348353
rpc/blockchain.h \
349354
rpc/client.h \
350355
rpc/evo_util.h \
351-
rpc/index_util.h \
352356
rpc/mempool.h \
353357
rpc/mining.h \
354358
rpc/protocol.h \
@@ -383,7 +387,6 @@ BITCOIN_CORE_H = \
383387
support/events.h \
384388
support/lockedpool.h \
385389
sync.h \
386-
timestampindex.h \
387390
threadsafety.h \
388391
timedata.h \
389392
torcontrol.h \
@@ -488,7 +491,6 @@ libbitcoin_node_a_SOURCES = \
488491
active/dkgsessionhandler.cpp \
489492
active/masternode.cpp \
490493
addrdb.cpp \
491-
addressindex.cpp \
492494
addrman.cpp \
493495
banman.cpp \
494496
batchedlogger.cpp \
@@ -534,9 +536,13 @@ libbitcoin_node_a_SOURCES = \
534536
httprpc.cpp \
535537
httpserver.cpp \
536538
i2p.cpp \
539+
index/addressindex.cpp \
540+
index/addressindex_util.cpp \
537541
index/base.cpp \
538542
index/blockfilterindex.cpp \
539543
index/coinstatsindex.cpp \
544+
index/spentindex.cpp \
545+
index/timestampindex.cpp \
540546
index/txindex.cpp \
541547
init.cpp \
542548
instantsend/db.cpp \
@@ -599,7 +605,6 @@ libbitcoin_node_a_SOURCES = \
599605
rpc/coinjoin.cpp \
600606
rpc/evo.cpp \
601607
rpc/fees.cpp \
602-
rpc/index_util.cpp \
603608
rpc/masternode.cpp \
604609
rpc/mempool.cpp \
605610
rpc/governance.cpp \

src/addressindex.cpp

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/core_write.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
#include <util/strencodings.h>
2020
#include <util/system.h>
2121

22-
#include <addressindex.h>
23-
#include <spentindex.h>
22+
#include <index/spentindex.h>
2423

2524
#include <evo/assetlocktx.h>
2625
#include <evo/cbtx.h>

src/dbwrapper.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,22 @@ class CDBWrapper
392392
{
393393
pdb->CompactRange(nullptr, nullptr);
394394
}
395+
396+
/**
397+
* Compact a specific range of keys in the database.
398+
*/
399+
template<typename K>
400+
void CompactRange(const K& key_begin, const K& key_end) const
401+
{
402+
CDataStream ssKey1(SER_DISK, CLIENT_VERSION), ssKey2(SER_DISK, CLIENT_VERSION);
403+
ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
404+
ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
405+
ssKey1 << key_begin;
406+
ssKey2 << key_end;
407+
leveldb::Slice slKey1(CharCast(ssKey1.data()), ssKey1.size());
408+
leveldb::Slice slKey2(CharCast(ssKey2.data()), ssKey2.size());
409+
pdb->CompactRange(&slKey1, &slKey2);
410+
}
395411
};
396412

397413
template<typename CDBTransaction>

0 commit comments

Comments
 (0)