@@ -23,6 +23,8 @@ use parking_lot::{Mutex, RwLock};
2323
2424use crate :: Config ;
2525
26+ type TxIndexHandle = Arc < Mutex < Box < dyn bitcoin_rs_index:: IndexerLike > > > ;
27+
2628/// Errors produced when applying a block to the node state.
2729#[ derive( Debug , thiserror:: Error ) ]
2830pub enum ApplyError {
@@ -165,13 +167,48 @@ impl fmt::Display for CompiledStorageFeatures {
165167 }
166168}
167169
170+ fn open_tx_index ( config : & Config ) -> Result < TxIndexHandle > {
171+ let txindex_dir = config. data_dir . join ( "txindex" ) ;
172+ std:: fs:: create_dir_all ( & txindex_dir)
173+ . with_context ( || format ! ( "create txindex_dir {}" , txindex_dir. display( ) ) ) ?;
174+ let tx_index: Box < dyn bitcoin_rs_index:: IndexerLike > = match config. storage_backend . as_str ( ) {
175+ #[ cfg( feature = "rocksdb" ) ]
176+ "rocksdb" => {
177+ let store =
178+ bitcoin_rs_storage:: RocksDbStore :: open ( & txindex_dir) . map_err ( anyhow:: Error :: new) ?;
179+ Box :: new ( bitcoin_rs_index:: Indexer :: new ( Arc :: new ( store) ) )
180+ }
181+ #[ cfg( feature = "fjall" ) ]
182+ "fjall" => {
183+ let store =
184+ bitcoin_rs_storage:: FjallStore :: open ( & txindex_dir) . map_err ( anyhow:: Error :: new) ?;
185+ Box :: new ( bitcoin_rs_index:: Indexer :: new ( Arc :: new ( store) ) )
186+ }
187+ #[ cfg( feature = "redb" ) ]
188+ "redb" => {
189+ let store =
190+ bitcoin_rs_storage:: RedbStore :: open ( & txindex_dir) . map_err ( anyhow:: Error :: new) ?;
191+ Box :: new ( bitcoin_rs_index:: Indexer :: new ( Arc :: new ( store) ) )
192+ }
193+ #[ cfg( feature = "mdbx" ) ]
194+ "mdbx" => {
195+ let store =
196+ bitcoin_rs_storage:: MdbxStore :: open ( & txindex_dir) . map_err ( anyhow:: Error :: new) ?;
197+ Box :: new ( bitcoin_rs_index:: Indexer :: new ( Arc :: new ( store) ) )
198+ }
199+ other => bail ! ( "unsupported storage backend for txindex: {other}" ) ,
200+ } ;
201+ Ok ( Arc :: new ( Mutex :: new ( tx_index) ) )
202+ }
203+
168204/// Aggregate handle to a running node.
169205pub struct NodeState {
170206 config : Config ,
171207 data_dir : PathBuf ,
172208 storage : NodeStorage ,
173209 utxo : Arc < UtxoSet > ,
174210 coin_stats : Arc < bitcoin_rs_coinstats:: CoinStatsListener > ,
211+ tx_index : TxIndexHandle ,
175212 mempool : Arc < RwLock < Mempool > > ,
176213 chain_tip : Arc < ArcSwapOption < TipSnapshot > > ,
177214 applied_tip : Arc < ArcSwapOption < TipSnapshot > > ,
@@ -203,6 +240,7 @@ impl NodeState {
203240 std:: fs:: create_dir_all ( & config. data_dir )
204241 . with_context ( || format ! ( "create data_dir {}" , config. data_dir. display( ) ) ) ?;
205242 let storage = NodeStorage :: open ( & config) ?;
243+ let tx_index = open_tx_index ( & config) ?;
206244 let mut utxo_set = bitcoin_rs_utxo:: UtxoSet :: new ( ) ;
207245 let coin_stats_listener = bitcoin_rs_coinstats:: CoinStatsListener :: new (
208246 bitcoin_rs_coinstats:: CoinStats :: default ( ) ,
@@ -234,6 +272,7 @@ impl NodeState {
234272 block_tree : Arc :: clone ( & block_tree) ,
235273 utxo : Arc :: clone ( & utxo) ,
236274 coin_stats : Arc :: clone ( & coin_stats) ,
275+ tx_index : Arc :: clone ( & tx_index) ,
237276 mempool : Arc :: clone ( & mempool) ,
238277 blocks : Arc :: clone ( & blocks) ,
239278 transactions : Arc :: clone ( & transactions) ,
@@ -255,6 +294,7 @@ impl NodeState {
255294 storage,
256295 utxo,
257296 coin_stats,
297+ tx_index,
258298 mempool,
259299 chain_tip,
260300 applied_tip,
@@ -304,6 +344,12 @@ impl NodeState {
304344 Arc :: clone ( & self . coin_stats )
305345 }
306346
347+ /// Returns the shared block indexer handle.
348+ #[ must_use]
349+ pub fn tx_index ( & self ) -> Arc < Mutex < Box < dyn bitcoin_rs_index:: IndexerLike > > > {
350+ Arc :: clone ( & self . tx_index )
351+ }
352+
307353 /// Returns the shared mempool handle.
308354 #[ must_use]
309355 pub fn mempool ( & self ) -> Arc < RwLock < Mempool > > {
@@ -451,6 +497,7 @@ impl NodeState {
451497 block_tree : Arc :: clone ( & self . block_tree ) ,
452498 utxo : Arc :: clone ( & self . utxo ) ,
453499 coin_stats : Arc :: clone ( & self . coin_stats ) ,
500+ tx_index : Arc :: clone ( & self . tx_index ) ,
454501 mempool : Arc :: clone ( & self . mempool ) ,
455502 blocks : Arc :: clone ( & self . blocks ) ,
456503 transactions : Arc :: clone ( & self . transactions ) ,
@@ -538,6 +585,19 @@ mod tests {
538585 Ok ( ( ) )
539586 }
540587
588+ #[ test]
589+ fn open_constructs_tx_index ( ) -> anyhow:: Result < ( ) > {
590+ let dir = tempfile:: tempdir ( ) ?;
591+ let mut config = crate :: Config :: default_for_network ( crate :: Network :: Regtest ) ;
592+ config. data_dir = dir. path ( ) . join ( "node" ) ;
593+ config. p2p_listen . clear ( ) ;
594+ let state = NodeState :: open ( config) ?;
595+ let a = state. tx_index ( ) ;
596+ let b = state. tx_index ( ) ;
597+ assert ! ( Arc :: ptr_eq( & a, & b) , "tx_index handle stable across calls" ) ;
598+ Ok ( ( ) )
599+ }
600+
541601 #[ test]
542602 fn open_constructs_block_sync_orchestrator ( ) -> anyhow:: Result < ( ) > {
543603 let dir = tempfile:: tempdir ( ) ?;
0 commit comments