Skip to content

Commit 6b0de79

Browse files
authored
core: move tx indexer to its own file (#28857)
This change moves all the transaction indexing functions to a separate txindexer.go file and defines a txIndexer structure as a refactoring.
1 parent 542c861 commit 6b0de79

File tree

6 files changed

+477
-498
lines changed

6 files changed

+477
-498
lines changed

core/blockchain.go

+7-171
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,6 @@ type txLookup struct {
192192
transaction *types.Transaction
193193
}
194194

195-
// TxIndexProgress is the struct describing the progress for transaction indexing.
196-
type TxIndexProgress struct {
197-
Indexed uint64 // number of blocks whose transactions are indexed
198-
Remaining uint64 // number of blocks whose transactions are not indexed yet
199-
}
200-
201-
// Done returns an indicator if the transaction indexing is finished.
202-
func (prog TxIndexProgress) Done() bool {
203-
return prog.Remaining == 0
204-
}
205-
206195
// BlockChain represents the canonical chain given a database with a genesis
207196
// block. The Blockchain manages chain imports, reverts, chain reorganisations.
208197
//
@@ -229,13 +218,7 @@ type BlockChain struct {
229218
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
230219
triedb *trie.Database // The database handler for maintaining trie nodes.
231220
stateCache state.Database // State database to reuse between imports (contains state cache)
232-
233-
// txLookupLimit is the maximum number of blocks from head whose tx indices
234-
// are reserved:
235-
// * 0: means no limit and regenerate any missing indexes
236-
// * N: means N block limit [HEAD-N+1, HEAD] and delete extra indexes
237-
// * nil: disable tx reindexer/deleter, but still index new blocks
238-
txLookupLimit uint64
221+
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
239222

240223
hc *HeaderChain
241224
rmLogsFeed event.Feed
@@ -270,9 +253,6 @@ type BlockChain struct {
270253
stopping atomic.Bool // false if chain is running, true when stopped
271254
procInterrupt atomic.Bool // interrupt signaler for block processing
272255

273-
txIndexRunning bool // flag if the background tx indexer is activated
274-
txIndexProgCh chan chan TxIndexProgress // chan for querying the progress of transaction indexing
275-
276256
engine consensus.Engine
277257
validator Validator // Block and state validator interface
278258
prefetcher Prefetcher
@@ -320,7 +300,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
320300
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
321301
txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit),
322302
futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks),
323-
txIndexProgCh: make(chan chan TxIndexProgress),
324303
engine: engine,
325304
vmConfig: vmConfig,
326305
}
@@ -485,13 +464,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
485464
}
486465
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
487466
}
488-
// Start tx indexer/unindexer if required.
467+
// Start tx indexer if it's enabled.
489468
if txLookupLimit != nil {
490-
bc.txLookupLimit = *txLookupLimit
491-
bc.txIndexRunning = true
492-
493-
bc.wg.Add(1)
494-
go bc.maintainTxIndex()
469+
bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
495470
}
496471
return bc, nil
497472
}
@@ -981,7 +956,10 @@ func (bc *BlockChain) stopWithoutSaving() {
981956
if !bc.stopping.CompareAndSwap(false, true) {
982957
return
983958
}
984-
959+
// Signal shutdown tx indexer.
960+
if bc.txIndexer != nil {
961+
bc.txIndexer.close()
962+
}
985963
// Unsubscribe all subscriptions registered from blockchain.
986964
bc.scope.Close()
987965

@@ -2403,148 +2381,6 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
24032381
return false
24042382
}
24052383

2406-
// indexBlocks reindexes or unindexes transactions depending on user configuration
2407-
func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
2408-
defer func() { close(done) }()
2409-
2410-
// If head is 0, it means the chain is just initialized and no blocks are
2411-
// inserted, so don't need to index anything.
2412-
if head == 0 {
2413-
return
2414-
}
2415-
// The tail flag is not existent, it means the node is just initialized
2416-
// and all blocks in the chain (part of them may from ancient store) are
2417-
// not indexed yet, index the chain according to the configuration then.
2418-
if tail == nil {
2419-
from := uint64(0)
2420-
if bc.txLookupLimit != 0 && head >= bc.txLookupLimit {
2421-
from = head - bc.txLookupLimit + 1
2422-
}
2423-
rawdb.IndexTransactions(bc.db, from, head+1, bc.quit, true)
2424-
return
2425-
}
2426-
// The tail flag is existent (which means indexes in [tail, head] should be
2427-
// present), while the whole chain are requested for indexing.
2428-
if bc.txLookupLimit == 0 || head < bc.txLookupLimit {
2429-
if *tail > 0 {
2430-
// It can happen when chain is rewound to a historical point which
2431-
// is even lower than the indexes tail, recap the indexing target
2432-
// to new head to avoid reading non-existent block bodies.
2433-
end := *tail
2434-
if end > head+1 {
2435-
end = head + 1
2436-
}
2437-
rawdb.IndexTransactions(bc.db, 0, end, bc.quit, true)
2438-
}
2439-
return
2440-
}
2441-
// The tail flag is existent, adjust the index range according to configuration
2442-
// and latest head.
2443-
if head-bc.txLookupLimit+1 < *tail {
2444-
// Reindex a part of missing indices and rewind index tail to HEAD-limit
2445-
rawdb.IndexTransactions(bc.db, head-bc.txLookupLimit+1, *tail, bc.quit, true)
2446-
} else {
2447-
// Unindex a part of stale indices and forward index tail to HEAD-limit
2448-
rawdb.UnindexTransactions(bc.db, *tail, head-bc.txLookupLimit+1, bc.quit, false)
2449-
}
2450-
}
2451-
2452-
// reportTxIndexProgress returns the tx indexing progress.
2453-
func (bc *BlockChain) reportTxIndexProgress(head uint64) TxIndexProgress {
2454-
var (
2455-
remaining uint64
2456-
tail = rawdb.ReadTxIndexTail(bc.db)
2457-
)
2458-
total := bc.txLookupLimit
2459-
if bc.txLookupLimit == 0 {
2460-
total = head + 1 // genesis included
2461-
}
2462-
var indexed uint64
2463-
if tail != nil {
2464-
indexed = head - *tail + 1
2465-
}
2466-
// The value of indexed might be larger than total if some blocks need
2467-
// to be unindexed, avoiding a negative remaining.
2468-
if indexed < total {
2469-
remaining = total - indexed
2470-
}
2471-
return TxIndexProgress{
2472-
Indexed: indexed,
2473-
Remaining: remaining,
2474-
}
2475-
}
2476-
2477-
// TxIndexProgress retrieves the tx indexing progress, or an error if the
2478-
// background tx indexer is not activated or already stopped.
2479-
func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
2480-
if !bc.txIndexRunning {
2481-
return TxIndexProgress{}, errors.New("tx indexer is not activated")
2482-
}
2483-
ch := make(chan TxIndexProgress, 1)
2484-
select {
2485-
case bc.txIndexProgCh <- ch:
2486-
return <-ch, nil
2487-
case <-bc.quit:
2488-
return TxIndexProgress{}, errors.New("blockchain is closed")
2489-
}
2490-
}
2491-
2492-
// maintainTxIndex is responsible for the construction and deletion of the
2493-
// transaction index.
2494-
//
2495-
// User can use flag `txlookuplimit` to specify a "recentness" block, below
2496-
// which ancient tx indices get deleted. If `txlookuplimit` is 0, it means
2497-
// all tx indices will be reserved.
2498-
//
2499-
// The user can adjust the txlookuplimit value for each launch after sync,
2500-
// Geth will automatically construct the missing indices or delete the extra
2501-
// indices.
2502-
func (bc *BlockChain) maintainTxIndex() {
2503-
defer bc.wg.Done()
2504-
2505-
// Listening to chain events and manipulate the transaction indexes.
2506-
var (
2507-
done chan struct{} // Non-nil if background unindexing or reindexing routine is active.
2508-
lastHead uint64 // The latest announced chain head (whose tx indexes are assumed created)
2509-
headCh = make(chan ChainHeadEvent, 1) // Buffered to avoid locking up the event feed
2510-
)
2511-
sub := bc.SubscribeChainHeadEvent(headCh)
2512-
if sub == nil {
2513-
return
2514-
}
2515-
defer sub.Unsubscribe()
2516-
log.Info("Initialized transaction indexer", "limit", bc.TxLookupLimit())
2517-
2518-
// Launch the initial processing if chain is not empty (head != genesis).
2519-
// This step is useful in these scenarios that chain has no progress and
2520-
// indexer is never triggered.
2521-
if head := rawdb.ReadHeadBlock(bc.db); head != nil && head.Number().Uint64() != 0 {
2522-
done = make(chan struct{})
2523-
lastHead = head.Number().Uint64()
2524-
go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.NumberU64(), done)
2525-
}
2526-
for {
2527-
select {
2528-
case head := <-headCh:
2529-
if done == nil {
2530-
done = make(chan struct{})
2531-
go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.Block.NumberU64(), done)
2532-
}
2533-
lastHead = head.Block.NumberU64()
2534-
case <-done:
2535-
done = nil
2536-
case ch := <-bc.txIndexProgCh:
2537-
ch <- bc.reportTxIndexProgress(lastHead)
2538-
case <-bc.quit:
2539-
if done != nil {
2540-
log.Info("Waiting background transaction indexer to exit")
2541-
<-done
2542-
}
2543-
return
2544-
}
2545-
}
2546-
}
2547-
25482384
// reportBlock logs a bad block error.
25492385
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
25502386
rawdb.WriteBadBlock(bc.db, block)

core/blockchain_reader.go

+6-10
Original file line numberDiff line numberDiff line change
@@ -397,16 +397,12 @@ func (bc *BlockChain) GetVMConfig() *vm.Config {
397397
return &bc.vmConfig
398398
}
399399

400-
// SetTxLookupLimit is responsible for updating the txlookup limit to the
401-
// original one stored in db if the new mismatches with the old one.
402-
func (bc *BlockChain) SetTxLookupLimit(limit uint64) {
403-
bc.txLookupLimit = limit
404-
}
405-
406-
// TxLookupLimit retrieves the txlookup limit used by blockchain to prune
407-
// stale transaction indices.
408-
func (bc *BlockChain) TxLookupLimit() uint64 {
409-
return bc.txLookupLimit
400+
// TxIndexProgress returns the transaction indexing progress.
401+
func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
402+
if bc.txIndexer == nil {
403+
return TxIndexProgress{}, errors.New("tx indexer is not enabled")
404+
}
405+
return bc.txIndexer.txIndexProgress()
410406
}
411407

412408
// TrieDB retrieves the low level trie database used for data storage.

0 commit comments

Comments
 (0)