diff --git a/core/blockchain.go b/core/blockchain.go index eec9c77212..fe127b5ea8 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -22,6 +22,7 @@ import ( "fmt" "io" "math/big" + "runtime" "sort" "strings" "sync" @@ -40,6 +41,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/internal/syncx" + "github.com/ethereum/go-ethereum/internal/version" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" @@ -2378,6 +2380,31 @@ func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, e log.Error(summarizeBadBlock(block, receipts, bc.Config(), err)) } +// summarizeBadBlock returns a string summarizing the bad block and other +// relevant information. +func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *params.ChainConfig, err error) string { + var receiptString string + for i, receipt := range receipts { + receiptString += fmt.Sprintf("\n %d: cumulative: %v gas: %v contract: %v status: %v tx: %v logs: %v bloom: %x state: %x", + i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(), + receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState) + } + version, vcs := version.Info() + platform := fmt.Sprintf("%s %s %s %s", version, runtime.Version(), runtime.GOARCH, runtime.GOOS) + if vcs != "" { + vcs = fmt.Sprintf("\nVCS: %s", vcs) + } + return fmt.Sprintf(` +########## BAD BLOCK ######### +Block: %v (%#x) +Error: %v +Platform: %v%v +Chain config: %#v +Receipts: %v +############################## +`, block.Number(), block.Hash(), err, platform, vcs, config, receiptString) +} + // InsertHeaderChain attempts to insert the given header chain in to the local // chain, possibly creating a reorg. If an error is returned, it will return the // index number of the failing header as well an error describing what went wrong. diff --git a/internal/version/vcs_fallback.go b/internal/version/vcs_fallback.go new file mode 100644 index 0000000000..6d7f32e735 --- /dev/null +++ b/internal/version/vcs_fallback.go @@ -0,0 +1,28 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +//go:build !go1.18 +// +build !go1.18 + +package version + +import "runtime/debug" + +// In Go versions before 1.18, VCS information is not available. + +func vcsInfo(info *debug.BuildInfo) (gitStatus, bool) { + return gitStatus{}, false +} diff --git a/internal/version/vcs_go1.18.go b/internal/version/vcs_go1.18.go new file mode 100644 index 0000000000..d5b9c97a16 --- /dev/null +++ b/internal/version/vcs_go1.18.go @@ -0,0 +1,48 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +//go:build go1.18 +// +build go1.18 + +package version + +import "runtime/debug" + +// In go 1.18 and beyond, the go tool embeds VCS information into the build. + +// vcsInfo returns VCS information of the build. +func vcsInfo(info *debug.BuildInfo) (s gitStatus, ok bool) { + for _, v := range info.Settings { + switch v.Key { + case "vcs.revision": + if len(v.Value) < 8 { + s.revision = v.Value + } else { + s.revision = v.Value[:8] + } + case "vcs.modified": + if v.Value == "true" { + s.modified = true + } + case "vcs.time": + s.time = v.Value + } + } + if s.revision != "" && s.time != "" { + ok = true + } + return +} diff --git a/core/badblock.go b/internal/version/version.go similarity index 61% rename from core/badblock.go rename to internal/version/version.go index a2fdfac714..e4b9ee4907 100644 --- a/core/badblock.go +++ b/internal/version/version.go @@ -14,70 +14,48 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package core +// Package version implements reading of build version information. +package version import ( "fmt" - "runtime" "runtime/debug" "strings" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" ) const ourPath = "github.com/ethereum/go-ethereum" // Path to our module -// summarizeBadBlock returns a string summarizing the bad block and other -// relevant information. -func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *params.ChainConfig, err error) string { - var receiptString string - for i, receipt := range receipts { - receiptString += fmt.Sprintf("\n %d: cumulative: %v gas: %v contract: %v status: %v tx: %v logs: %v bloom: %x state: %x", - i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(), - receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState) - } - version, vcs := runtimeInfo() - platform := fmt.Sprintf("%s %s %s %s", version, runtime.Version(), runtime.GOARCH, runtime.GOOS) - if vcs != "" { - vcs = fmt.Sprintf("\nVCS: %s", vcs) - } - return fmt.Sprintf(` -########## BAD BLOCK ######### -Block: %v (%#x) -Error: %v -Platform: %v%v -Chain config: %#v -Receipts: %v -############################## -`, block.Number(), block.Hash(), err, platform, vcs, config, receiptString) -} - // runtimeInfo returns build and platform information about the current binary. // // If the package that is currently executing is a prefixed by our go-ethereum // module path, it will print out commit and date VCS information. Otherwise, // it will assume it's imported by a third-party and will return the imported // version and whether it was replaced by another module. -func runtimeInfo() (string, string) { - var ( - version = params.VersionWithMeta - vcs = "" - buildInfo, ok = debug.ReadBuildInfo() - ) - if ok { - version = versionInfo(buildInfo) - if status, ok := vcsInfo(buildInfo); ok { - modified := "" - if status.modified { - modified = " (dirty)" - } - vcs = status.revision + "-" + status.time + modified +func Info() (version, vcs string) { + version = params.VersionWithMeta + buildInfo, ok := debug.ReadBuildInfo() + if !ok { + return version, "" + } + version = versionInfo(buildInfo) + if status, ok := vcsInfo(buildInfo); ok { + modified := "" + if status.modified { + modified = " (dirty)" } + vcs = status.revision + "-" + status.time + modified } return version, vcs } +type gitStatus struct { + revision string + time string + modified bool +} + // versionInfo returns version information for the currently executing // implementation. // @@ -113,36 +91,6 @@ func versionInfo(info *debug.BuildInfo) string { return version } -type status struct { - revision string - time string - modified bool -} - -// vcsInfo returns VCS information of the build. -func vcsInfo(info *debug.BuildInfo) (s status, ok bool) { - for _, v := range info.Settings { - switch v.Key { - case "vcs.revision": - if len(v.Value) < 8 { - s.revision = v.Value - } else { - s.revision = v.Value[:8] - } - case "vcs.modified": - if v.Value == "true" { - s.modified = true - } - case "vcs.time": - s.time = v.Value - } - } - if s.revision != "" && s.time != "" { - ok = true - } - return -} - // findModule returns the module at path. func findModule(info *debug.BuildInfo, path string) *debug.Module { if info.Path == ourPath {