Add a "tx output spender" index
Adds an outpoint -> txid index, which can be used to find which transactions spent a given output. We use a composite key with 2 parts (suggested by @romanz): hash(spent outpoint) and tx position, with an empty value. To find the spending tx for a given outpoint, we do a prefix search (prefix being the hash of the provided outpoint), and for all keys that match this prefix we load the tx at the position specified in the key and return it, along with the block hash, if does spend the provided outpoint. To handle reorgs we just erase the keys computed from the removed block. This index is extremely useful for Lightning and more generally for layer-2 protocols that rely on chains of unpublished transactions. If enabled, this index will be used by `gettxspendingprevout` when it does not find a spending transaction in the mempool.
This commit is contained in:
1 parent
2706758dc3
commit
3d82ec5bdd
18 files changed
+611
-105
No files matched your search
@@ -79,7 +79,7 @@ class InitTest(BitcoinTestFramework):
|
||||
if self.is_wallet_compiled():
|
||||
lines_to_terminate_after.append(b'Verifying wallet')
|
||||
|
||||
args = ['-txindex=1', '-blockfilterindex=1', '-coinstatsindex=1']
|
||||
args = ['-txindex=1', '-blockfilterindex=1', '-coinstatsindex=1', '-txospenderindex=1']
|
||||
for terminate_line in lines_to_terminate_after:
|
||||
self.log.info(f"Starting node and will terminate after line {terminate_line}")
|
||||
with node.busy_wait_for_debug_log([terminate_line]):
|
||||
@@ -133,6 +133,11 @@ class InitTest(BitcoinTestFramework):
|
||||
'error_message': 'LevelDB error: Corruption: CURRENT points to a non-existent file',
|
||||
'startup_args': ['-txindex=1'],
|
||||
},
|
||||
{
|
||||
'filepath_glob': 'indexes/txospenderindex/db/MANIFEST*',
|
||||
'error_message': 'LevelDB error: Corruption: CURRENT points to a non-existent file',
|
||||
'startup_args': ['-txospenderindex=1'],
|
||||
},
|
||||
# Removing these files does not result in a startup error:
|
||||
# 'indexes/blockfilter/basic/*.dat', 'indexes/blockfilter/basic/db/*.*', 'indexes/coinstatsindex/db/*.*',
|
||||
# 'indexes/txindex/*.log', 'indexes/txindex/CURRENT', 'indexes/txindex/LOCK'
|
||||
@@ -174,6 +179,11 @@ class InitTest(BitcoinTestFramework):
|
||||
'error_message': 'LevelDB error: Corruption',
|
||||
'startup_args': ['-txindex=1'],
|
||||
},
|
||||
{
|
||||
'filepath_glob': 'indexes/txospenderindex/db/*',
|
||||
'error_message': 'LevelDB error: Corruption',
|
||||
'startup_args': ['-txospenderindex=1'],
|
||||
},
|
||||
# Perturbing these files does not result in a startup error:
|
||||
# 'indexes/blockfilter/basic/*.dat', 'indexes/txindex/MANIFEST*', 'indexes/txindex/LOCK'
|
||||
]
|
||||
@@ -183,6 +193,7 @@ class InitTest(BitcoinTestFramework):
|
||||
err_fragment = round_info['error_message']
|
||||
startup_args = round_info['startup_args']
|
||||
target_files = list(node.chain_path.glob(file_patt))
|
||||
assert target_files, f"Failed to find expected files: {file_patt}"
|
||||
|
||||
for target_file in target_files:
|
||||
self.log.info(f"Deleting file to ensure failure {target_file}")
|
||||
@@ -209,6 +220,7 @@ class InitTest(BitcoinTestFramework):
|
||||
for dir in dirs:
|
||||
shutil.copytree(node.chain_path / dir, node.chain_path / f"{dir}_bak")
|
||||
target_files = list(node.chain_path.glob(file_patt))
|
||||
assert target_files, f"Failed to find expected files: {file_patt}"
|
||||
|
||||
for target_file in target_files:
|
||||
self.log.info(f"Perturbing file to ensure failure {target_file}")
|
||||
|
||||
Reference in new issue
Block a user