From d5a0d6256e0b03744d276203c4cac903f20c2b7b Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 1 Apr 2025 12:11:16 +0200 Subject: [PATCH] eth, eth/filters: try accessing db before returning error 4444 --- eth/api_backend.go | 39 +++++++++++++++++++----------------- eth/ethconfig/historymode.go | 6 ++++++ eth/filters/api.go | 4 ++-- eth/filters/filter.go | 4 ++-- eth/filters/filter_system.go | 4 ++-- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/eth/api_backend.go b/eth/api_backend.go index 8e2af684d1..3143129a94 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/ethdb" @@ -42,12 +43,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) -// ErrorPrunedHistory is returned when the requested history is pruned. -type ErrorPrunedHistory struct{} - -func (e *ErrorPrunedHistory) Error() string { return "Pruned history unavailable" } -func (e *ErrorPrunedHistory) ErrorCode() int { return 4444 } - // EthAPIBackend implements ethapi.Backend and tracers.Backend for full nodes type EthAPIBackend struct { extRPCEnabled bool @@ -159,10 +154,13 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe if number == rpc.EarliestBlockNumber { bn = b.eth.blockchain.HistoryPruningCutoff() } - if bn < b.eth.blockchain.HistoryPruningCutoff() { - return nil, &ErrorPrunedHistory{} + + // bn is the resolved number. + block := b.eth.blockchain.GetBlockByNumber(bn) + if block == nil && bn < b.eth.blockchain.HistoryPruningCutoff() { + return nil, ðconfig.PrunedHistoryError{} } - return b.eth.blockchain.GetBlockByNumber(bn), nil + return nil, nil } func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { @@ -170,10 +168,11 @@ func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ if number == nil { return nil, nil } - if *number < b.eth.blockchain.HistoryPruningCutoff() { - return nil, &ErrorPrunedHistory{} + block := b.eth.blockchain.GetBlock(hash, *number) + if block == nil && *number < b.eth.blockchain.HistoryPruningCutoff() { + return nil, ðconfig.PrunedHistoryError{} } - return b.eth.blockchain.GetBlock(hash, *number), nil + return nil, nil } // GetBody returns body of a block. It does not resolve special block numbers. @@ -181,10 +180,14 @@ func (b *EthAPIBackend) GetBody(ctx context.Context, hash common.Hash, number rp if number < 0 || hash == (common.Hash{}) { return nil, errors.New("invalid arguments; expect hash and no special block numbers") } - if body := b.eth.blockchain.GetBody(hash); body != nil { - return body, nil + body := b.eth.blockchain.GetBody(hash) + if body == nil { + if uint64(number) < b.eth.blockchain.HistoryPruningCutoff() { + return nil, ðconfig.PrunedHistoryError{} + } + return nil, errors.New("block body not found") } - return nil, errors.New("block body not found") + return body, nil } func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { @@ -199,11 +202,11 @@ func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash r if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { return nil, errors.New("hash is not currently canonical") } - if header.Number.Uint64() < b.eth.blockchain.HistoryPruningCutoff() { - return nil, &ErrorPrunedHistory{} - } block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64()) if block == nil { + if header.Number.Uint64() < b.eth.blockchain.HistoryPruningCutoff() { + return nil, ðconfig.PrunedHistoryError{} + } return nil, errors.New("header found, but block body is missing") } return block, nil diff --git a/eth/ethconfig/historymode.go b/eth/ethconfig/historymode.go index c3661004e8..a595d72feb 100644 --- a/eth/ethconfig/historymode.go +++ b/eth/ethconfig/historymode.go @@ -90,3 +90,9 @@ var HistoryPrunePoints = map[common.Hash]*HistoryPrunePoint{ BlockHash: common.HexToHash("0x229f6b18ca1552f1d5146deceb5387333f40dc6275aebee3f2c5c4ece07d02db"), }, } + +// PrunedHistoryError is returned when the requested history is pruned. +type PrunedHistoryError struct{} + +func (e *PrunedHistoryError) Error() string { return "pruned history unavailable" } +func (e *PrunedHistoryError) ErrorCode() int { return 4444 } diff --git a/eth/filters/api.go b/eth/filters/api.go index c2f700ace8..6593cbef27 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -29,7 +29,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/rpc" ) @@ -360,7 +360,7 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type return nil, errInvalidBlockRange } if begin > 0 && begin < int64(api.events.backend.HistoryPruningCutoff()) { - return nil, ð.ErrorPrunedHistory{} + return nil, ðconfig.PrunedHistoryError{} } // Construct the range filter filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics) diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 9cd885b127..e44b37d047 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -27,7 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/filtermaps" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" ) @@ -88,7 +88,7 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) { return nil, errors.New("unknown block") } if header.Number.Uint64() < f.sys.backend.HistoryPruningCutoff() { - return nil, ð.ErrorPrunedHistory{} + return nil, ðconfig.PrunedHistoryError{} } return f.blockLogs(ctx, header) } diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go index c8edec5351..aca3c03ad6 100644 --- a/eth/filters/filter_system.go +++ b/eth/filters/filter_system.go @@ -31,7 +31,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/filtermaps" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" @@ -311,7 +311,7 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ } // Queries beyond the pruning cutoff are not supported. if uint64(from) < es.backend.HistoryPruningCutoff() { - return nil, ð.ErrorPrunedHistory{} + return nil, ðconfig.PrunedHistoryError{} } // only interested in new mined logs