Files
prysm/cmd/prysmctl/db/span.go
Preston Van Loon 2fd6bd8150 Add golang.org/x/tools modernize static analyzer and fix violations (#15946)
* Ran gopls modernize to fix everything

go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...

* Override rules_go provided dependency for golang.org/x/tools to v0.38.0.

To update this, checked out rules_go, then ran `bazel run //go/tools/releaser -- upgrade-dep -mirror=false org_golang_x_tools` and copied the patches.

* Fix buildtag violations and ignore buildtag violations in external

* Introduce modernize analyzer package.

* Add modernize "any" analyzer.

* Fix violations of any analyzer

* Add modernize "appendclipped" analyzer.

* Fix violations of appendclipped

* Add modernize "bloop" analyzer.

* Add modernize "fmtappendf" analyzer.

* Add modernize "forvar" analyzer.

* Add modernize "mapsloop" analyzer.

* Add modernize "minmax" analyzer.

* Fix violations of minmax analyzer

* Add modernize "omitzero" analyzer.

* Add modernize "rangeint" analyzer.

* Fix violations of rangeint.

* Add modernize "reflecttypefor" analyzer.

* Fix violations of reflecttypefor analyzer.

* Add modernize "slicescontains" analyzer.

* Add modernize "slicessort" analyzer.

* Add modernize "slicesdelete" analyzer. This is disabled by default for now. See https://go.dev/issue/73686.

* Add modernize "stringscutprefix" analyzer.

* Add modernize "stringsbuilder" analyzer.

* Fix violations of stringsbuilder analyzer.

* Add modernize "stringsseq" analyzer.

* Add modernize "testingcontext" analyzer.

* Add modernize "waitgroup" analyzer.

* Changelog fragment

* gofmt

* gazelle

* Add modernize "newexpr" analyzer.

* Disable newexpr until go1.26

* Add more details in WORKSPACE on how to update the override

* @nalepae feedback on min()

* gofmt

* Fix violations of forvar
2025-11-14 01:27:22 +00:00

299 lines
9.1 KiB
Go

package db
import (
"fmt"
"github.com/OffchainLabs/prysm/v7/beacon-chain/slasher"
"github.com/OffchainLabs/prysm/v7/beacon-chain/slasher/types"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/pkg/errors"
"github.com/urfave/cli/v2"
)
const DefaultChunkKind = types.MinSpan
var (
f = struct {
Path string
ValidatorIndex uint64
Epoch uint64
ChunkKind string
ChunkSize uint64
ValidatorChunkSize uint64
HistoryLength uint64
IsDisplayAllValidatorsInChunk bool
IsDisplayAllEpochsInChunk bool
}{}
slasherDefaultParams = slasher.DefaultParams()
)
var spanCmd = &cli.Command{
Name: "slasher-span-display",
Usage: "visualise values in db span bucket",
Action: func(c *cli.Context) error {
if err := spanAction(c); err != nil {
return errors.Wrapf(err, "visualise values in db span bucket failed")
}
return nil
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "db-path-directory",
Usage: "path to directory containing slasher.db",
Destination: &f.Path,
Required: true,
},
&cli.Uint64Flag{
Name: "validator-index",
Usage: "filter by validator index",
Destination: &f.ValidatorIndex,
Required: true,
},
&cli.Uint64Flag{
Name: "epoch",
Usage: "filter by epoch",
Destination: &f.Epoch,
Required: true,
},
&cli.StringFlag{
Name: "chunk-kind",
Usage: "chunk kind to query (maxspan|minspan)",
Destination: &f.ChunkKind,
Value: DefaultChunkKind.String(),
DefaultText: DefaultChunkKind.String(),
},
&cli.Uint64Flag{
Name: "chunk-size",
Usage: "chunk size to query",
Destination: &f.ChunkSize,
DefaultText: fmt.Sprintf("%d", slasherDefaultParams.ChunkSize()),
},
&cli.Uint64Flag{
Name: "validator-chunk-size",
Usage: "validator chunk size to query",
Destination: &f.ValidatorChunkSize,
DefaultText: fmt.Sprintf("%d", slasherDefaultParams.ValidatorChunkSize()),
},
&cli.Uint64Flag{
Name: "history-length",
Usage: "history length to query",
Destination: &f.HistoryLength,
DefaultText: fmt.Sprintf("%d", slasherDefaultParams.HistoryLength()),
},
&cli.BoolFlag{
Name: "display-all-validators-in-chunk",
Usage: "display all validators in chunk",
Destination: &f.IsDisplayAllValidatorsInChunk,
},
&cli.BoolFlag{
Name: "display-all-epochs-in-chunk",
Usage: "display all epochs in chunk",
Destination: &f.IsDisplayAllEpochsInChunk,
},
},
}
func spanAction(cliCtx *cli.Context) error {
var (
chunk slasher.Chunker
validatorChunkIdx uint64
lastEpochForValidatorIndex primitives.Epoch
err error
)
// context
ctx := cliCtx.Context
// variables
chunkKind := getChunkKind()
params := getSlasherParams()
i := primitives.ValidatorIndex(f.ValidatorIndex)
epoch := primitives.Epoch(f.Epoch)
// display configuration
fmt.Printf("############################# SLASHER PARAMS ###############################\n")
fmt.Printf("# Chunk Size: %d\n", params.ChunkSize())
fmt.Printf("# Validator Chunk Size: %d\n", params.ValidatorChunkSize())
fmt.Printf("# History Length: %d\n", params.HistoryLength())
fmt.Printf("# DB: %s\n", f.Path)
fmt.Printf("# Chunk Kind: %s\n", chunkKind)
fmt.Printf("# Validator: %d\n", i)
fmt.Printf("# Epoch: %d\n", epoch)
fmt.Printf("############################################################################\n")
// fetch chunk in database
if lastEpochForValidatorIndex, _, validatorChunkIdx, chunk, err = slasher.GetChunkFromDatabase(
ctx,
f.Path,
slasher.GetChunkFromDatabaseFilters{
ChunkKind: chunkKind,
ValidatorIndex: i,
SourceEpoch: epoch,
IsDisplayAllValidatorsInChunk: f.IsDisplayAllValidatorsInChunk,
IsDisplayAllEpochsInChunk: f.IsDisplayAllEpochsInChunk,
},
params,
); err != nil {
return errors.Wrapf(err, "could not get chunk from database")
}
// fetch information related to chunk
fmt.Printf("\n################################ CHUNK #####################################\n")
firstValidator := params.ValidatorIndexesInChunk(validatorChunkIdx)[0]
firstEpoch := epoch - (epoch.Mod(params.ChunkSize()))
fmt.Printf("# First validator in chunk: %d\n", firstValidator)
fmt.Printf("# First epoch in chunk: %d\n\n", firstEpoch)
fmt.Printf("# Last epoch found in database for validator(%d): %d\n", i, lastEpochForValidatorIndex)
fmt.Printf("############################################################################\n\n")
// init table
tw := table.NewWriter()
minLowerBound := lastEpochForValidatorIndex.Sub(uint64(params.HistoryLength()))
if f.IsDisplayAllValidatorsInChunk {
if f.IsDisplayAllEpochsInChunk {
// display all validators and epochs in chunk
// headers
addEpochsHeader(tw, params.ChunkSize(), firstEpoch)
// rows
b := chunk.Chunk()
c := uint64(0)
for z := uint64(0); z < uint64(len(b)); z += params.ChunkSize() {
end := min(z+params.ChunkSize(), uint64(len(b)))
subChunk := b[z:end]
row := make(table.Row, params.ChunkSize()+1)
title := firstValidator + primitives.ValidatorIndex(c)
row[0] = title
for y, span := range subChunk {
row[y+1] = getSpanOrNonApplicable(firstEpoch, y, minLowerBound, lastEpochForValidatorIndex, span)
}
tw.AppendRow(row)
c++
}
} else {
// display all validators but only the requested epoch in chunk
indexEpochInChunk := epoch - firstEpoch
// headers
addEpochsHeader(tw, 1, firstEpoch)
// rows
b := chunk.Chunk()
c := uint64(0)
for z := uint64(0); z < uint64(len(b)); z += params.ChunkSize() {
end := min(z+params.ChunkSize(), uint64(len(b)))
subChunk := b[z:end]
row := make(table.Row, 2)
title := firstValidator + primitives.ValidatorIndex(c)
row[0] = title
row[1] = subChunk[indexEpochInChunk]
tw.AppendRow(row)
c++
}
}
} else {
if f.IsDisplayAllEpochsInChunk {
// display only the requested validator with all epochs in chunk
// headers
addEpochsHeader(tw, params.ChunkSize(), firstEpoch)
// rows
b := chunk.Chunk()
validatorFirstEpochIdx := uint64(i.Mod(params.ValidatorChunkSize())) * params.ChunkSize()
subChunk := b[validatorFirstEpochIdx : validatorFirstEpochIdx+params.ChunkSize()]
row := make(table.Row, params.ChunkSize()+1)
title := i
row[0] = title
for y, span := range subChunk {
row[y+1] = getSpanOrNonApplicable(firstEpoch, y, minLowerBound, lastEpochForValidatorIndex, span)
}
tw.AppendRow(row)
} else {
// display only the requested validator and epoch in chunk
// headers
addEpochsHeader(tw, 1, epoch)
// rows
b := chunk.Chunk()
validatorFirstEpochIdx := uint64(i.Mod(params.ValidatorChunkSize())) * params.ChunkSize()
subChunk := b[validatorFirstEpochIdx : validatorFirstEpochIdx+params.ChunkSize()]
row := make(table.Row, 2)
title := i
row[0] = title
indexEpochInChunk := epoch - firstEpoch
row[1] = subChunk[indexEpochInChunk]
tw.AppendRow(row)
}
}
// display table
displayTable(tw)
return nil
}
// getSpanOrNonApplicable checks if there's some epoch that are not correct in chunk due to the round robin
// nature of 2D chunking when an epoch gets overwritten by an epoch eg. (params.historyLength + next_epoch) > params.historyLength
// if we are out of the range, we display a n/a value otherwise the span value
func getSpanOrNonApplicable(firstEpoch primitives.Epoch, y int, minLowerBound primitives.Epoch, lastEpochForValidatorIndex primitives.Epoch, span uint16) string {
if firstEpoch.Add(uint64(y)) < minLowerBound || firstEpoch.Add(uint64(y)) > lastEpochForValidatorIndex {
return "-"
}
return fmt.Sprintf("%d", span)
}
func displayTable(tw table.Writer) {
tw.AppendSeparator()
fmt.Println(tw.Render())
}
func addEpochsHeader(tw table.Writer, nbEpoch uint64, firstEpoch primitives.Epoch) {
header := table.Row{"Validator / Epoch"}
for y := 0; uint64(y) < nbEpoch; y++ {
header = append(header, firstEpoch+primitives.Epoch(y))
}
tw.AppendHeader(header)
}
func getChunkKind() types.ChunkKind {
chunkKind := types.MinSpan
if f.ChunkKind == "maxspan" {
chunkKind = types.MaxSpan
}
return chunkKind
}
func getSlasherParams() *slasher.Parameters {
var (
chunkSize, validatorChunkSize uint64
historyLength primitives.Epoch
)
if f.ChunkSize != 0 && f.ChunkSize != slasherDefaultParams.ChunkSize() {
chunkSize = f.ChunkSize
} else {
chunkSize = slasherDefaultParams.ChunkSize()
}
if f.ValidatorChunkSize != 0 && f.ValidatorChunkSize != slasherDefaultParams.ValidatorChunkSize() {
validatorChunkSize = f.ValidatorChunkSize
} else {
validatorChunkSize = slasherDefaultParams.ValidatorChunkSize()
}
if f.HistoryLength != 0 && f.HistoryLength != uint64(slasherDefaultParams.HistoryLength()) {
historyLength = primitives.Epoch(f.HistoryLength)
} else {
historyLength = slasherDefaultParams.HistoryLength()
}
return slasher.NewParams(chunkSize, validatorChunkSize, historyLength)
}