Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f3fcb97
feat: migrate TimestampIndex from synchronous to async operation
UdjinM6 Jan 19, 2026
33d2fc5
test: update timestampindex functional test for async behavior
UdjinM6 Jan 19, 2026
464cdf8
feat: migrate SpentIndex from synchronous to async operation
UdjinM6 Jan 19, 2026
3ea9394
test: update feature_spentindex for async behavior
UdjinM6 Jan 19, 2026
18276a6
feat: migrate AddressIndex from synchronous to async operation
UdjinM6 Jan 19, 2026
8ad06be
test: update feature_addressindex for async behavior
UdjinM6 Jan 19, 2026
fa7be34
feat: add CompactRange template method to CDBWrapper
UdjinM6 Jan 19, 2026
fa60ccb
feat: migrate old synchronous index data to new async index databases
UdjinM6 Jan 19, 2026
6e5f7ab
fix: add missing include in `src/zmq/zmqpublishnotifier.cpp`
UdjinM6 Jan 19, 2026
5fd7033
docs: add release notes
UdjinM6 Jan 19, 2026
fd1de98
refactor: address code review feedback
UdjinM6 Jan 19, 2026
5be629b
refactor: apply clang-format
UdjinM6 Jan 19, 2026
e84b1fa
feat: add async indexes to getindexinfo RPC
UdjinM6 Jan 19, 2026
98c3c1b
fix: check index sync status before querying and show sync progress
UdjinM6 Jan 19, 2026
331335e
fix: add explicit vtxundo size validation and in-class initialization…
UdjinM6 Mar 12, 2026
97dcc6d
fix: address review suggestions
UdjinM6 Mar 27, 2026
8f3f62b
fix: add vtxundo size validation in SpentIndex::WriteBlock
UdjinM6 Mar 31, 2026
5796588
fix: reverse transaction processing order in AddressIndex::Rewind
UdjinM6 Mar 31, 2026
386acdf
fix: add undo data size validation in AddressIndex::Rewind
UdjinM6 Mar 31, 2026
1ca7374
fix: harden BlockDisconnected sibling check and getaddressbalance hei…
UdjinM6 Mar 31, 2026
c41584e
refactor: move BlockUntilSyncedToCurrentChain from index queries to R…
UdjinM6 Apr 1, 2026
0695e97
refactor: move BlockDisconnected handling to BaseIndex
UdjinM6 Apr 1, 2026
cc1dd3c
fix: harden index migration and document timestampindex prune caveat
UdjinM6 May 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 41 additions & 6 deletions test/functional/feature_spentindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from test_framework.script_util import (
keyhash_to_p2pkh_script,
)
from test_framework.test_node import ErrorMatch
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal

Expand Down Expand Up @@ -50,14 +49,12 @@ def setup_network(self):
self.import_deterministic_coinbase_privkeys()

def run_test(self):
self.log.info("Test that settings can be disabled without -reindex...")
self.log.info("Test that settings can be disabled and re-enabled...")
self.restart_node(1, ["-spentindex=0"])
self.connect_nodes(0, 1)
self.sync_all()
self.log.info("Test that settings can't be enabled without -reindex...")
self.stop_node(1)
self.nodes[1].assert_start_raises_init_error(["-spentindex"], "You need to rebuild the database using -reindex to enable -spentindex", match=ErrorMatch.PARTIAL_REGEX)
self.start_node(1, ["-spentindex", "-reindex"])
# SpentIndex is now async, so it can be enabled without -reindex
self.restart_node(1, ["-spentindex"])
self.connect_nodes(0, 1)
self.sync_all()

Expand Down Expand Up @@ -126,6 +123,14 @@ def run_test(self):
assert_equal(txVerbose3["vin"][0]["value"], Decimal(unspent[0]["amount"]) - tx_fee)
assert_equal(txVerbose3["vin"][0]["valueSat"], amount)

self.log.info("Testing getspentinfo with mempool data...")
# Check that getspentinfo returns mempool spend info for unconfirmed transactions
# The output from txid is now spent by txid2 (which is in mempool, not yet mined)
info_mempool = self.nodes[1].getspentinfo({"txid": txid, "index": 0})
assert_equal(info_mempool["txid"], txid2)
assert_equal(info_mempool["index"], 0)
assert_equal(info_mempool["height"], -1) # Height -1 indicates mempool transaction

# Check the database index
self.generate(self.nodes[0], 1)

Expand All @@ -134,6 +139,36 @@ def run_test(self):
assert_equal(txVerbose4["vin"][0]["value"], Decimal(unspent[0]["amount"]) - tx_fee)
assert_equal(txVerbose4["vin"][0]["valueSat"], amount)

self.log.info("Testing reorg handling...")
# Get the block hash containing txid
block_hash = self.nodes[1].getblockhash(106)

# Verify spent info exists before reorg
info_before = self.nodes[1].getspentinfo({"txid": unspent[0]["txid"], "index": unspent[0]["vout"]})
assert_equal(info_before["txid"], txid)

# Invalidate the block containing the spending transaction on all nodes
for node in self.nodes:
node.invalidateblock(block_hash)

# After invalidation, transactions go back to mempool
# getspentinfo should still find the spend in mempool with height -1
info_after_invalidate = self.nodes[1].getspentinfo({"txid": unspent[0]["txid"], "index": unspent[0]["vout"]})
Comment thread
knst marked this conversation as resolved.
assert_equal(info_after_invalidate["txid"], txid)
assert_equal(info_after_invalidate["index"], 0)
assert_equal(info_after_invalidate["height"], -1) # Now in mempool

# Reconsider the block on all nodes
for node in self.nodes:
node.reconsiderblock(block_hash)
self.sync_all()

# Verify spent info is back after reconsider
info_after = self.nodes[1].getspentinfo({"txid": unspent[0]["txid"], "index": unspent[0]["vout"]})
assert_equal(info_after["txid"], txid)
assert_equal(info_after["index"], 0)
assert_equal(info_after["height"], 106)

self.log.info("Passed")


Expand Down