cmd/geth, core/rawdb: include tx index delta in prune history cleared total

rjl493456442 pointed out that the cleared figure logged at the end of
`geth db prune-history` only counted the body/receipt flat-file delta
via prunableFreezerSize() and silently dropped the tx-index work done
just before TruncateTail. Anyone reading the log line saw a number
that under-reported the actual on-disk savings.

PruneTransactionIndex now returns the logical bytes deleted (sum of
key + value lengths for each removed entry) by accumulating during the
existing DeleteAllTxLookupEntries iteration. cmd/geth folds that into
the StorageSize total before logging. The figure is uncompacted — the
KV store doesn't expose per-prefix on-disk usage without a full
compaction sweep — but it's the only signal available without changing
the prune sequence, and it matches the granularity rjl asked for.

Existing rawdb test (TestPruneTransactionIndex) is unchanged; Go's
untyped-discard semantics keep it compiling against the new signature.
This commit is contained in:
ozpool 2026-05-15 16:36:04 +05:30
parent 5984bde7c4
commit b3c07dc7b9
2 changed files with 13 additions and 3 deletions

View file

@ -776,7 +776,7 @@ func pruneHistory(ctx *cli.Context) error {
log.Info("Starting history pruning", "head", currentHeader.Number, "target", targetBlock, "targetHash", targetBlockHash.Hex())
start := time.Now()
sizeBefore := prunableFreezerSize(chaindb)
rawdb.PruneTransactionIndex(chaindb, targetBlock)
txIndexBytes := rawdb.PruneTransactionIndex(chaindb, targetBlock)
if _, err := chaindb.TruncateTail(targetBlock); err != nil {
return fmt.Errorf("failed to truncate ancient data: %v", err)
}
@ -785,6 +785,10 @@ func pruneHistory(ctx *cli.Context) error {
if sizeBefore > sizeAfter {
cleared = common.StorageSize(sizeBefore - sizeAfter)
}
// Include the tx index entries pruned from the KV store; without this the
// reported figure only covers the body/receipt freezer delta and ignores
// the index work above.
cleared += common.StorageSize(txIndexBytes)
log.Info("History pruning completed", "tail", targetBlock, "elapsed", common.PrettyDuration(time.Since(start)), "cleared", cleared)
// TODO(s1na): what if there is a crash between the two prune operations?

View file

@ -377,8 +377,11 @@ func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, in
unindexTransactions(db, from, to, interrupt, hook, false)
}
// PruneTransactionIndex removes all tx index entries below a certain block number.
func PruneTransactionIndex(db ethdb.Database, pruneBlock uint64) {
// PruneTransactionIndex removes all tx index entries below a certain block number
// and returns the approximate number of bytes freed (sum of key + value lengths
// for each deleted entry). The figure is logical (uncompacted) but is the only
// per-prefix size signal the KV store exposes without forcing a full compaction.
func PruneTransactionIndex(db ethdb.Database, pruneBlock uint64) (removedBytes uint64) {
tail := ReadTxIndexTail(db)
if tail == nil || *tail > pruneBlock {
return // no index, or index ends above pruneBlock
@ -386,6 +389,7 @@ func PruneTransactionIndex(db ethdb.Database, pruneBlock uint64) {
// There are blocks below pruneBlock in the index. Iterate the entire index to remove
// their entries. Note if this fails, the index is messed up, but tail still points to
// the old tail.
keyLen := uint64(len(txLookupPrefix) + common.HashLength)
var count, removed int
DeleteAllTxLookupEntries(db, func(txhash common.Hash, v []byte) bool {
count++
@ -399,11 +403,13 @@ func PruneTransactionIndex(db ethdb.Database, pruneBlock uint64) {
bn := decodeNumber(v)
if bn < pruneBlock {
removed++
removedBytes += keyLen + uint64(len(v))
return true
}
return false
})
WriteTxIndexTail(db, pruneBlock)
return
}
func decodeNumber(b []byte) uint64 {