return prunedHistoryError from GetLogs/FilterLogs if accessing pruned state. duplicate prunedHistoryError into eth/filters package. add HistoryCutoff method to eth backend

This commit is contained in:
Jared Wasinger 2025-03-12 17:38:45 +01:00 committed by Felix Lange
parent 1dcc65d429
commit 6da1903139
7 changed files with 31 additions and 0 deletions

View file

@ -251,11 +251,18 @@ func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockN
return nil, nil, errors.New("invalid arguments; neither block nor hash specified") return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
} }
func (b *EthAPIBackend) HistoryCutoff() uint64 {
return b.eth.blockchain.HistoryCutoff()
}
func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
return b.eth.blockchain.GetReceiptsByHash(hash), nil return b.eth.blockchain.GetReceiptsByHash(hash), nil
} }
func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
if number < b.eth.blockchain.HistoryCutoff() {
return nil, &prunedHistoryError{}
}
return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil
} }

View file

@ -342,6 +342,7 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
} }
var filter *Filter var filter *Filter
if crit.BlockHash != nil { if crit.BlockHash != nil {
// TODO: return pruned history error here where it would apply
// Block filter requested, construct a single-shot filter // Block filter requested, construct a single-shot filter
filter = api.sys.NewBlockFilter(*crit.BlockHash, crit.Addresses, crit.Topics) filter = api.sys.NewBlockFilter(*crit.BlockHash, crit.Addresses, crit.Topics)
} else { } else {
@ -357,6 +358,9 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
if begin > 0 && end > 0 && begin > end { if begin > 0 && end > 0 && begin > end {
return nil, errInvalidBlockRange return nil, errInvalidBlockRange
} }
if begin < int64(api.events.backend.HistoryCutoff()) {
return nil, &prunedHistoryError{}
}
// Construct the range filter // Construct the range filter
filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics) filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics)
} }

View file

@ -64,6 +64,7 @@ type Backend interface {
CurrentHeader() *types.Header CurrentHeader() *types.Header
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
HistoryCutoff() uint64
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription
@ -139,6 +140,11 @@ func (sys *FilterSystem) cachedGetBody(ctx context.Context, elem *logCacheElem,
return body, nil return body, nil
} }
type prunedHistoryError struct{}
func (e *prunedHistoryError) Error() string { return "Pruned history unavailable" }
func (e *prunedHistoryError) ErrorCode() int { return 4444 }
// Type determines the kind of filter and is used to put the filter in to // Type determines the kind of filter and is used to put the filter in to
// the correct bucket when added. // the correct bucket when added.
type Type byte type Type byte

View file

@ -181,7 +181,15 @@ func (b *testBackend) setPending(block *types.Block, receipts types.Receipts) {
b.pendingReceipts = receipts b.pendingReceipts = receipts
} }
<<<<<<< HEAD
func newTestFilterSystem(db ethdb.Database, cfg Config) (*testBackend, *FilterSystem) { func newTestFilterSystem(db ethdb.Database, cfg Config) (*testBackend, *FilterSystem) {
=======
func (b *testBackend) HistoryCutoff() uint64 {
return 0
}
func newTestFilterSystem(t testing.TB, db ethdb.Database, cfg Config) (*testBackend, *FilterSystem) {
>>>>>>> 7139f930b0 (return prunedHistoryError from GetLogs/FilterLogs if accessing pruned state. duplicate prunedHistoryError into eth/filters package. add HistoryCutoff method to eth backend)
backend := &testBackend{db: db} backend := &testBackend{db: db}
sys := NewFilterSystem(backend, cfg) sys := NewFilterSystem(backend, cfg)
return backend, sys return backend, sys

View file

@ -618,6 +618,9 @@ func (b testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscripti
func (b testBackend) NewMatcherBackend() filtermaps.MatcherBackend { func (b testBackend) NewMatcherBackend() filtermaps.MatcherBackend {
panic("implement me") panic("implement me")
} }
func (b testBackend) HistoryCutoff() uint64 { return b.chain.HistoryCutoff() }
func TestEstimateGas(t *testing.T) { func TestEstimateGas(t *testing.T) {
t.Parallel() t.Parallel()
// Initialize test accounts // Initialize test accounts

View file

@ -85,6 +85,7 @@ type Backend interface {
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
Engine() consensus.Engine Engine() consensus.Engine
HistoryCutoff() uint64
// This is copied from filters.Backend // This is copied from filters.Backend
// eth/filters needs to be initialized from this backend type, so methods needed by // eth/filters needs to be initialized from this backend type, so methods needed by

View file

@ -402,3 +402,5 @@ func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent)
func (b *backendMock) Engine() consensus.Engine { return nil } func (b *backendMock) Engine() consensus.Engine { return nil }
func (b *backendMock) NewMatcherBackend() filtermaps.MatcherBackend { return nil } func (b *backendMock) NewMatcherBackend() filtermaps.MatcherBackend { return nil }
func (b *backendMock) HistoryCutoff() uint64 { return b.HistoryCutoff() }