fix: fall back to era files for block retrieval on pruned nodes

This commit is contained in:
jeevan-sid 2026-05-15 15:01:52 +05:30
parent 9c232a0101
commit b673e63a73
5 changed files with 58 additions and 2 deletions

View file

@ -422,3 +422,7 @@ func (f *chainFreezer) TruncateTail(items uint64) (uint64, error) {
func (f *chainFreezer) SyncAncient() error {
return f.ancients.SyncAncient()
}
func (f *chainFreezer) EraStore() *eradb.Store {
return f.eradb
}

View file

@ -32,6 +32,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb/eradb"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
@ -86,6 +87,27 @@ func (frdb *freezerdb) Freeze() error {
return nil
}
// Unwrapper allows retrieving the underlying database from a wrapper.
type Unwrapper interface {
Unwrap() ethdb.Database
}
// EraStore returns the eradb.Store from the database if available.
// Returns nil if the database does not have an era store (e.g. in-memory or no freezer).
func EraStore(db ethdb.Database) *eradb.Store {
for {
if frdb, ok := db.(*freezerdb); ok {
return frdb.EraStore()
}
if unwrapper, ok := db.(Unwrapper); ok {
db = unwrapper.Unwrap()
} else {
break
}
}
return nil
}
// nofreezedb is a database wrapper that disables freezer data retrievals.
type nofreezedb struct {
ethdb.KeyValueStore

View file

@ -26,6 +26,7 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/era"
"github.com/ethereum/go-ethereum/internal/era/execdb"
"github.com/ethereum/go-ethereum/internal/era/onedb"
@ -102,6 +103,21 @@ func (db *Store) Close() {
}
}
// GetBlockByNumber returns the block for a given block number.
func (db *Store) GetBlockByNumber(number uint64) (*types.Block, error) {
epoch := number / uint64(era.MaxSize)
entry := db.getEraByEpoch(epoch)
if entry.err != nil {
if errors.Is(entry.err, fs.ErrNotExist) {
return nil, nil
}
return nil, entry.err
}
defer db.doneWithFile(epoch, entry)
return entry.file.GetBlockByNumber(number)
}
// GetRawBody returns the raw body for a given block number.
func (db *Store) GetRawBody(number uint64) ([]byte, error) {
epoch := number / uint64(era.MaxSize)

View file

@ -156,10 +156,19 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
bn = b.HistoryPruningCutoff()
}
block := b.eth.blockchain.GetBlockByNumber(bn)
if block == nil && bn < b.HistoryPruningCutoff() {
if block != nil {
return block, nil
}
// Block not found in the local database, try the ERA store as a fallback.
if eraStore := rawdb.EraStore(b.eth.chainDb); eraStore != nil {
if eraBlock, err := eraStore.GetBlockByNumber(bn); err == nil && eraBlock != nil {
return eraBlock, nil
}
}
if bn < b.HistoryPruningCutoff() {
return nil, &history.PrunedHistoryError{}
}
return block, nil
return nil, nil
}
func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {

View file

@ -777,6 +777,11 @@ func (db *closeTrackingDB) Close() error {
return db.Database.Close()
}
// Unwrap returns the underlying database.
func (db *closeTrackingDB) Unwrap() ethdb.Database {
return db.Database
}
// wrapDatabase ensures the database will be auto-closed when Node is closed.
func (n *Node) wrapDatabase(db ethdb.Database) ethdb.Database {
wrapper := &closeTrackingDB{db, n}