Skip to content

Commit

Permalink
core: move build version reading to its own package (#25806)
Browse files Browse the repository at this point in the history
This fixes the build with Go 1.17, which does not have BuildInfo.Settings yet.
  • Loading branch information
fjl authored Sep 19, 2022
1 parent 8e52015 commit 468d184
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 72 deletions.
27 changes: 27 additions & 0 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"io"
"math/big"
"runtime"
"sort"
"strings"
"sync"
Expand All @@ -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"
Expand Down Expand Up @@ -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.
Expand Down
28 changes: 28 additions & 0 deletions internal/version/vcs_fallback.go
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

//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
}
48 changes: 48 additions & 0 deletions internal/version/vcs_go1.18.go
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

//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
}
92 changes: 20 additions & 72 deletions core/badblock.go → internal/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <http://www.gnu.org/licenses/>.

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.
//
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 468d184

Please sign in to comment.