From 8abbbf236e445de2c4ed1b35b0aae9ac54a4adc7 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Fri, 7 Jan 2022 16:03:25 +0100 Subject: [PATCH] cmd/geth: check for legacy receipts on node startup --- cmd/geth/config.go | 12 +++++++++- cmd/geth/dbcmd.go | 60 +++++++++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 7a642edd0e41b..965e991ae120c 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -161,7 +161,17 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { if ctx.GlobalIsSet(utils.OverrideTerminalTotalDifficulty.Name) { cfg.Eth.OverrideTerminalTotalDifficulty = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideTerminalTotalDifficulty.Name)) } - backend, _ := utils.RegisterEthService(stack, &cfg.Eth, ctx.GlobalBool(utils.CatalystFlag.Name)) + backend, eth := utils.RegisterEthService(stack, &cfg.Eth, ctx.GlobalBool(utils.CatalystFlag.Name)) + // Warn users to migrate if they have a legacy freezer format. + if eth != nil { + isLegacy, _, err := dbHasLegacyReceipts(eth.ChainDb()) + if err != nil { + utils.Fatalf("Failed to check db for legacy receipts: %v", err) + } + if isLegacy { + log.Warn("Database has receipts with a legacy format. Please run `geth db freezer-migrate`.") + } + } // Configure GraphQL if requested if ctx.GlobalIsSet(utils.GraphQLEnabledFlag.Name) { diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index e986679abc41d..1abf3298f9203 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -720,28 +720,7 @@ func freezerMigrate(ctx *cli.Context) error { return nil } - // Find first block with non-empty receipt - firstIdx := uint64(0) - emptyRLPList := []byte{192} - for i := uint64(0); i < numAncients; i++ { - r, err := db.Ancient("receipts", i) - if err != nil { - return err - } - if len(r) == 0 { - continue - } - if !bytes.Equal(r, emptyRLPList) { - firstIdx = i - break - } - } - // Is first non-empty receipt legacy? - first, err := db.Ancient("receipts", firstIdx) - if err != nil { - return err - } - isFirstLegacy, err := types.IsLegacyStoredReceipts(first) + isFirstLegacy, firstIdx, err := dbHasLegacyReceipts(db) if err != nil { return err } @@ -762,3 +741,40 @@ func freezerMigrate(ctx *cli.Context) error { return nil } + +// dbHasLegacyReceipts checks freezer entries for legacy receipts. It stops at the first +// non-empty receipt and checks its format. The index of this first non-empty element is +// the second return parameter. +func dbHasLegacyReceipts(db ethdb.Database) (isLegacy bool, firstIdx uint64, err error) { + // Check first block for legacy receipt format + numAncients, err := db.Ancients() + if err != nil { + return + } + if numAncients < 1 { + return + } + // Find first block with non-empty receipt + emptyRLPList := []byte{192} + var blob []byte + for i := uint64(0); i < numAncients; i++ { + blob, err = db.Ancient("receipts", i) + if err != nil { + return + } + if len(blob) == 0 { + continue + } + if !bytes.Equal(blob, emptyRLPList) { + firstIdx = i + break + } + } + // Is first non-empty receipt legacy? + first, err := db.Ancient("receipts", firstIdx) + if err != nil { + return false, 0, err + } + isLegacy, err = types.IsLegacyStoredReceipts(first) + return +}