Skip to content

Commit 8e52015

Browse files
lightclientfjl
andauthored
core: more compact bad block report (#25714)
This shortens the chain config summary in bad block reports, and adds go-ethereum version information as well. Co-authored-by: Felix Lange <[email protected]>
1 parent ada603f commit 8e52015

File tree

4 files changed

+162
-22
lines changed

4 files changed

+162
-22
lines changed

core/badblock.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright 2022 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package core
18+
19+
import (
20+
"fmt"
21+
"runtime"
22+
"runtime/debug"
23+
"strings"
24+
25+
"github.com/ethereum/go-ethereum/core/types"
26+
"github.com/ethereum/go-ethereum/params"
27+
)
28+
29+
const ourPath = "github.com/ethereum/go-ethereum" // Path to our module
30+
31+
// summarizeBadBlock returns a string summarizing the bad block and other
32+
// relevant information.
33+
func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *params.ChainConfig, err error) string {
34+
var receiptString string
35+
for i, receipt := range receipts {
36+
receiptString += fmt.Sprintf("\n %d: cumulative: %v gas: %v contract: %v status: %v tx: %v logs: %v bloom: %x state: %x",
37+
i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(),
38+
receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState)
39+
}
40+
version, vcs := runtimeInfo()
41+
platform := fmt.Sprintf("%s %s %s %s", version, runtime.Version(), runtime.GOARCH, runtime.GOOS)
42+
if vcs != "" {
43+
vcs = fmt.Sprintf("\nVCS: %s", vcs)
44+
}
45+
return fmt.Sprintf(`
46+
########## BAD BLOCK #########
47+
Block: %v (%#x)
48+
Error: %v
49+
Platform: %v%v
50+
Chain config: %#v
51+
Receipts: %v
52+
##############################
53+
`, block.Number(), block.Hash(), err, platform, vcs, config, receiptString)
54+
}
55+
56+
// runtimeInfo returns build and platform information about the current binary.
57+
//
58+
// If the package that is currently executing is a prefixed by our go-ethereum
59+
// module path, it will print out commit and date VCS information. Otherwise,
60+
// it will assume it's imported by a third-party and will return the imported
61+
// version and whether it was replaced by another module.
62+
func runtimeInfo() (string, string) {
63+
var (
64+
version = params.VersionWithMeta
65+
vcs = ""
66+
buildInfo, ok = debug.ReadBuildInfo()
67+
)
68+
if ok {
69+
version = versionInfo(buildInfo)
70+
if status, ok := vcsInfo(buildInfo); ok {
71+
modified := ""
72+
if status.modified {
73+
modified = " (dirty)"
74+
}
75+
vcs = status.revision + "-" + status.time + modified
76+
}
77+
}
78+
return version, vcs
79+
}
80+
81+
// versionInfo returns version information for the currently executing
82+
// implementation.
83+
//
84+
// Depending on how the code is instansiated, it returns different amounts of
85+
// information. If it is unable to determine which module is related to our
86+
// package it falls back to the hardcoded values in the params package.
87+
func versionInfo(info *debug.BuildInfo) string {
88+
// If the main package is from our repo, prefix version with "geth".
89+
if strings.HasPrefix(info.Path, ourPath) {
90+
return fmt.Sprintf("geth %s", info.Main.Version)
91+
}
92+
// Not our main package, so explicitly print out the module path and
93+
// version.
94+
var version string
95+
if info.Main.Path != "" && info.Main.Version != "" {
96+
// These can be empty when invoked with "go run".
97+
version = fmt.Sprintf("%s@%s ", info.Main.Path, info.Main.Version)
98+
}
99+
mod := findModule(info, ourPath)
100+
if mod == nil {
101+
// If our module path wasn't imported, it's unclear which
102+
// version of our code they are running. Fallback to hardcoded
103+
// version.
104+
return version + fmt.Sprintf("geth %s", params.VersionWithMeta)
105+
}
106+
// Our package is a dependency for the main module. Return path and
107+
// version data for both.
108+
version += fmt.Sprintf("%s@%s", mod.Path, mod.Version)
109+
if mod.Replace != nil {
110+
// If our package was replaced by something else, also note that.
111+
version += fmt.Sprintf(" (replaced by %s@%s)", mod.Replace.Path, mod.Replace.Version)
112+
}
113+
return version
114+
}
115+
116+
type status struct {
117+
revision string
118+
time string
119+
modified bool
120+
}
121+
122+
// vcsInfo returns VCS information of the build.
123+
func vcsInfo(info *debug.BuildInfo) (s status, ok bool) {
124+
for _, v := range info.Settings {
125+
switch v.Key {
126+
case "vcs.revision":
127+
if len(v.Value) < 8 {
128+
s.revision = v.Value
129+
} else {
130+
s.revision = v.Value[:8]
131+
}
132+
case "vcs.modified":
133+
if v.Value == "true" {
134+
s.modified = true
135+
}
136+
case "vcs.time":
137+
s.time = v.Value
138+
}
139+
}
140+
if s.revision != "" && s.time != "" {
141+
ok = true
142+
}
143+
return
144+
}
145+
146+
// findModule returns the module at path.
147+
func findModule(info *debug.BuildInfo, path string) *debug.Module {
148+
if info.Path == ourPath {
149+
return &info.Main
150+
}
151+
for _, mod := range info.Deps {
152+
if mod.Path == path {
153+
return mod
154+
}
155+
}
156+
return nil
157+
}

core/blockchain.go

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
239239
}
240240
log.Info("")
241241
log.Info(strings.Repeat("-", 153))
242-
for _, line := range strings.Split(chainConfig.String(), "\n") {
242+
for _, line := range strings.Split(chainConfig.Description(), "\n") {
243243
log.Info(line)
244244
}
245245
log.Info(strings.Repeat("-", 153))
@@ -2375,24 +2375,7 @@ func (bc *BlockChain) maintainTxIndex(ancients uint64) {
23752375
// reportBlock logs a bad block error.
23762376
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
23772377
rawdb.WriteBadBlock(bc.db, block)
2378-
2379-
var receiptString string
2380-
for i, receipt := range receipts {
2381-
receiptString += fmt.Sprintf("\t %d: cumulative: %v gas: %v contract: %v status: %v tx: %v logs: %v bloom: %x state: %x\n",
2382-
i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(),
2383-
receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState)
2384-
}
2385-
log.Error(fmt.Sprintf(`
2386-
########## BAD BLOCK #########
2387-
Chain config: %v
2388-
2389-
Number: %v
2390-
Hash: %#x
2391-
%v
2392-
2393-
Error: %v
2394-
##############################
2395-
`, bc.chainConfig, block.Number(), block.Hash(), receiptString, err))
2378+
log.Error(summarizeBadBlock(block, receipts, bc.Config(), err))
23962379
}
23972380

23982381
// InsertHeaderChain attempts to insert the given header chain in to the local

les/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
105105
}
106106
log.Info("")
107107
log.Info(strings.Repeat("-", 153))
108-
for _, line := range strings.Split(chainConfig.String(), "\n") {
108+
for _, line := range strings.Split(chainConfig.Description(), "\n") {
109109
log.Info(line)
110110
}
111111
log.Info(strings.Repeat("-", 153))

params/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,8 @@ func (c *CliqueConfig) String() string {
407407
return "clique"
408408
}
409409

410-
// String implements the fmt.Stringer interface.
411-
func (c *ChainConfig) String() string {
410+
// Description returns a human-readable description of ChainConfig.
411+
func (c *ChainConfig) Description() string {
412412
var banner string
413413

414414
// Create some basinc network config output

0 commit comments

Comments
 (0)