From c57df9ca286aff90672044dc199014fba59bed11 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi <1591639+s1na@users.noreply.github.com> Date: Thu, 11 Nov 2021 15:04:06 +0100 Subject: [PATCH] core/rawdb: add slow path for getting legacy logs (#23879) * eth/tracers: add slow path for getting legacy logs * core/rawdb: fix test --- core/rawdb/accessors_chain.go | 24 ++++++++++++++++++++++-- core/rawdb/accessors_chain_test.go | 2 +- eth/api_backend.go | 2 +- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 7f26c3a42068..4028191b760c 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -669,7 +669,7 @@ func deriveLogFields(receipts []*receiptLogs, hash common.Hash, number uint64, t // ReadLogs retrieves the logs for all transactions in a block. The log fields // are populated with metadata. In case the receipts or the block body // are not found, a nil is returned. -func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log { +func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) [][]*types.Log { // Retrieve the flattened receipt slice data := ReadReceiptsRLP(db, hash, number) if len(data) == 0 { @@ -677,7 +677,12 @@ func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log { } receipts := []*receiptLogs{} if err := rlp.DecodeBytes(data, &receipts); err != nil { - log.Error("Invalid receipt array RLP", "hash", hash, "err", err) + // Receipts might be in the legacy format, try decoding that. + // TODO: to be removed after users migrated + if logs := readLegacyLogs(db, hash, number, config); logs != nil { + return logs + } + log.Error("Invalid receipt array RLP", "hash", "err", err) return nil } @@ -697,6 +702,21 @@ func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log { return logs } +// readLegacyLogs is a temporary workaround for when trying to read logs +// from a block which has its receipt stored in the legacy format. It'll +// be removed after users have migrated their freezer databases. +func readLegacyLogs(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) [][]*types.Log { + receipts := ReadReceipts(db, hash, number, config) + if receipts == nil { + return nil + } + logs := make([][]*types.Log, len(receipts)) + for i, receipt := range receipts { + logs[i] = receipt.Logs + } + return logs +} + // ReadBlock retrieves an entire block corresponding to the hash, assembling it // back from the stored header and body. If either the header or body could not // be retrieved nil is returned. diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 4b173c55eeb0..50b0d53902dd 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -744,7 +744,7 @@ func TestReadLogs(t *testing.T) { // Insert the receipt slice into the database and check presence WriteReceipts(db, hash, 0, receipts) - logs := ReadLogs(db, hash, 0) + logs := ReadLogs(db, hash, 0, params.TestChainConfig) if len(logs) == 0 { t.Fatalf("no logs returned") } diff --git a/eth/api_backend.go b/eth/api_backend.go index a0704876a387..6a19fb36ac79 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -187,7 +187,7 @@ func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*typ if number == nil { return nil, errors.New("failed to get block number from hash") } - logs := rawdb.ReadLogs(db, hash, *number) + logs := rawdb.ReadLogs(db, hash, *number, b.eth.blockchain.Config()) if logs == nil { return nil, errors.New("failed to get logs for block") }