mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 21:08:10 -05:00
#### This PR sets the foundation for the new logging features. --- The goal of this big PR is the following: 1. Adding a log.go file to every package: [_commit_](54f6396d4c) - Writing a bash script that adds the log.go file to every package that imports logrus, except the excluded packages, configured at the top of the bash script. - the log.go file creates a log variable and sets a field called `package` to the full path of that package. - I have tried to fix every error/problem that came from mass generation of this file. (duplicate declarations, different prefix names, etc...) - some packages had the log.go file from before, and had some helper functions in there as well. I've moved all of them to a `log_helpers.go` file within each package. 2. Create a CI rule which verifies that: [_commit_](b799c3a0ef) - every package which imports logrus, also has a log.go file, except the excluded packages. - the `package` field of each log.go variable, has the correct path. (to detect when we move a package or change it's name) - I pushed a commit with a manually changed log.go file to trigger the ci check failure and it worked. 3. Alter the logging system to read the prefix from this `package` field for every log while outputing: [_commit_](b0c7f1146c) - some packages have/want/need a different log prefix than their package name (like `kv`). This can be solved by keeping a map of package paths to prefix names somewhere. --- **Some notes:** - Please review everything carefully. - I created the `prefixReplacement` map and populated the data that I deemed necessary. Please check it and complain if something doesn't make sense or is missing. I attached at the bottom, the list of all the packages that used to use a different name than their package name as their prefix. - I have chosen to mark some packages to be excluded from this whole process. They will either not log anything, or log without a prefix, or log using their previously defined prefix. See the list of exclusions in the bottom. - I fixed all the tests that failed because of this change. These were failing because they were expecting the old prefix to be in the generated logs. I have changed those to expect the new `package` field instead. This might not be a great solution. Ideally we might want to remove this from the tests so they only test for relevant fields in the logs. but this is a problem for another day. - Please run the node with this config, and mention if you see something weird in the logs. (use different verbosities) - The CI workflow uses a script that basically runs the `hack/gen-logs.sh` and checks that the git diff is zero. that script is `hack/check-logs.sh`. This means that if one runs this script locally, it will not actually _check_ anything, rather than just regenerate the log.go files and fix any mistake. This might be confusing. Please suggest solutions if you think it's a problem. --- **A list of packages that used a different prefix than their package names for their logs:** - beacon-chain/cache/depositsnapshot/ package depositsnapshot, prefix "cache" - beacon-chain/core/transition/log.go — package transition, prefix "state" - beacon-chain/db/kv/log.go — package kv, prefix "db" - beacon-chain/db/slasherkv/log.go — package slasherkv, prefix "slasherdb" - beacon-chain/db/pruner/pruner.go — package pruner, prefix "db-pruner" - beacon-chain/light-client/log.go — package light_client, prefix "light-client" - beacon-chain/operations/attestations/log.go — package attestations, prefix "pool/attestations" - beacon-chain/operations/slashings/log.go — package slashings, prefix "pool/slashings" - beacon-chain/rpc/core/log.go — package core, prefix "rpc/core" - beacon-chain/rpc/eth/beacon/log.go — package beacon, prefix "rpc/beaconv1" - beacon-chain/rpc/eth/validator/log.go — package validator, prefix "beacon-api" - beacon-chain/rpc/prysm/v1alpha1/beacon/log.go — package beacon, prefix "rpc" - beacon-chain/rpc/prysm/v1alpha1/validator/log.go — package validator, prefix "rpc/validator" - beacon-chain/state/stategen/log.go — package stategen, prefix "state-gen" - beacon-chain/sync/checkpoint/log.go — package checkpoint, prefix "checkpoint-sync" - beacon-chain/sync/initial-sync/log.go — package initialsync, prefix "initial-sync" - cmd/prysmctl/p2p/log.go — package p2p, prefix "prysmctl-p2p" - config/features/log.go -- package features, prefix "flags" - io/file/log.go — package file, prefix "fileutil" - proto/prysm/v1alpha1/log.go — package eth, prefix "protobuf" - validator/client/beacon-api/log.go — package beacon_api, prefix "beacon-api" - validator/db/kv/log.go — package kv, prefix "db" - validator/db/filesystem/db.go — package filesystem, prefix "db" - validator/keymanager/derived/log.go — package derived, prefix "derived-keymanager" - validator/keymanager/local/log.go — package local, prefix "local-keymanager" - validator/keymanager/remote-web3signer/log.go — package remote_web3signer, prefix "remote-keymanager" - validator/keymanager/remote-web3signer/internal/log.go — package internal, prefix "remote-web3signer- internal" - beacon-chain/forkchoice/doubly... prefix is "forkchoice-doublylinkedtree" **List of excluded directories (their subdirectories are also excluded):** ``` EXCLUDED_PATH_PREFIXES=( "testing" "validator/client/testutil" "beacon-chain/p2p/testing" "beacon-chain/rpc/eth/config" "beacon-chain/rpc/prysm/v1alpha1/debug" "tools" "runtime" "monitoring" "io" "cmd" ".well-known" "changelog" "hack" "specrefs" "third_party" "bazel-out" "bazel-bin" "bazel-prysm" "bazel-testlogs" "build" ".github" ".jj" ".idea" ".vscode" ) ```
255 lines
8.0 KiB
Go
255 lines
8.0 KiB
Go
// Package helpers contains helper functions outlined in the Ethereum Beacon Chain spec, such as
|
|
// computing committees, randao, rewards/penalties, and more.
|
|
package helpers
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/cache"
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/time"
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
|
"github.com/OffchainLabs/prysm/v7/config/params"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
|
"github.com/OffchainLabs/prysm/v7/crypto/hash"
|
|
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
|
"github.com/OffchainLabs/prysm/v7/time/slots"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var (
|
|
syncCommitteeCache = cache.NewSyncCommittee()
|
|
)
|
|
|
|
// CurrentPeriodPositions returns committee indices of the current period sync committee for input validators.
|
|
func CurrentPeriodPositions(st state.BeaconState, indices []primitives.ValidatorIndex) ([][]primitives.CommitteeIndex, error) {
|
|
root, err := SyncPeriodBoundaryRoot(st)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pos, err := syncCommitteeCache.CurrentPeriodPositions(root, indices)
|
|
if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) {
|
|
committee, err := st.CurrentSyncCommittee()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Fill in the cache on miss.
|
|
go func() {
|
|
if err := syncCommitteeCache.UpdatePositionsInCommittee(root, st); err != nil {
|
|
log.WithError(err).Error("Could not fill sync committee cache on miss")
|
|
}
|
|
}()
|
|
|
|
pos = make([][]primitives.CommitteeIndex, len(indices))
|
|
for i, idx := range indices {
|
|
pubkey := st.PubkeyAtIndex(idx)
|
|
pos[i] = findSubCommitteeIndices(pubkey[:], committee.Pubkeys)
|
|
}
|
|
return pos, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return pos, nil
|
|
}
|
|
|
|
// IsCurrentPeriodSyncCommittee returns true if the input validator index belongs in the current period sync committee
|
|
// along with the sync committee root.
|
|
// 1. Checks if the public key exists in the sync committee cache
|
|
// 2. If 1 fails, checks if the public key exists in the input current sync committee object
|
|
func IsCurrentPeriodSyncCommittee(st state.BeaconState, valIdx primitives.ValidatorIndex) (bool, error) {
|
|
root, err := SyncPeriodBoundaryRoot(st)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
indices, err := syncCommitteeCache.CurrentPeriodIndexPosition(root, valIdx)
|
|
if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) {
|
|
val, err := st.ValidatorAtIndex(valIdx)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
committee, err := st.CurrentSyncCommittee()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// Fill in the cache on miss.
|
|
go func() {
|
|
if err := syncCommitteeCache.UpdatePositionsInCommittee(root, st); err != nil {
|
|
log.WithError(err).Error("Could not fill sync committee cache on miss")
|
|
}
|
|
}()
|
|
|
|
return len(findSubCommitteeIndices(val.PublicKey, committee.Pubkeys)) > 0, nil
|
|
}
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return len(indices) > 0, nil
|
|
}
|
|
|
|
// IsNextPeriodSyncCommittee returns true if the input validator index belongs in the next period sync committee
|
|
// along with the sync period boundary root.
|
|
// 1. Checks if the public key exists in the sync committee cache
|
|
// 2. If 1 fails, checks if the public key exists in the input next sync committee object
|
|
func IsNextPeriodSyncCommittee(
|
|
st state.BeaconState, valIdx primitives.ValidatorIndex,
|
|
) (bool, error) {
|
|
root, err := SyncPeriodBoundaryRoot(st)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
indices, err := syncCommitteeCache.NextPeriodIndexPosition(root, valIdx)
|
|
if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) {
|
|
val, err := st.ValidatorAtIndexReadOnly(valIdx)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
pk := val.PublicKey()
|
|
committee, err := st.NextSyncCommittee()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return len(findSubCommitteeIndices(pk[:], committee.Pubkeys)) > 0, nil
|
|
}
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return len(indices) > 0, nil
|
|
}
|
|
|
|
// CurrentPeriodSyncSubcommitteeIndices returns the subcommittee indices of the
|
|
// current period sync committee for input validator.
|
|
func CurrentPeriodSyncSubcommitteeIndices(
|
|
st state.BeaconState, valIdx primitives.ValidatorIndex,
|
|
) ([]primitives.CommitteeIndex, error) {
|
|
root, err := SyncPeriodBoundaryRoot(st)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
indices, err := syncCommitteeCache.CurrentPeriodIndexPosition(root, valIdx)
|
|
if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) {
|
|
val, err := st.ValidatorAtIndexReadOnly(valIdx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pk := val.PublicKey()
|
|
committee, err := st.CurrentSyncCommittee()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Fill in the cache on miss.
|
|
go func() {
|
|
if err := syncCommitteeCache.UpdatePositionsInCommittee(root, st); err != nil {
|
|
log.WithError(err).Error("Could not fill sync committee cache on miss")
|
|
}
|
|
}()
|
|
|
|
return findSubCommitteeIndices(pk[:], committee.Pubkeys), nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return indices, nil
|
|
}
|
|
|
|
// NextPeriodSyncSubcommitteeIndices returns the subcommittee indices of the next period sync committee for input validator.
|
|
func NextPeriodSyncSubcommitteeIndices(
|
|
st state.BeaconState, valIdx primitives.ValidatorIndex,
|
|
) ([]primitives.CommitteeIndex, error) {
|
|
root, err := SyncPeriodBoundaryRoot(st)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
indices, err := syncCommitteeCache.NextPeriodIndexPosition(root, valIdx)
|
|
if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) {
|
|
val, err := st.ValidatorAtIndexReadOnly(valIdx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pk := val.PublicKey()
|
|
committee, err := st.NextSyncCommittee()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return findSubCommitteeIndices(pk[:], committee.Pubkeys), nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return indices, nil
|
|
}
|
|
|
|
// UpdateSyncCommitteeCache updates sync committee cache.
|
|
// It uses `state`'s latest block header root as key. To avoid misuse, it disallows
|
|
// block header with state root zeroed out.
|
|
func UpdateSyncCommitteeCache(st state.BeaconState) error {
|
|
nextSlot := st.Slot() + 1
|
|
if nextSlot%params.BeaconConfig().SlotsPerEpoch != 0 {
|
|
return errors.New("not at the end of the epoch to update cache")
|
|
}
|
|
if slots.ToEpoch(nextSlot)%params.BeaconConfig().EpochsPerSyncCommitteePeriod != 0 {
|
|
return errors.New("not at sync committee period boundary to update cache")
|
|
}
|
|
|
|
header := st.LatestBlockHeader()
|
|
if bytes.Equal(header.StateRoot, params.BeaconConfig().ZeroHash[:]) {
|
|
return errors.New("zero hash state root can't be used to update cache")
|
|
}
|
|
|
|
prevBlockRoot, err := header.HashTreeRoot()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return syncCommitteeCache.UpdatePositionsInCommittee(combineRootAndSlot(prevBlockRoot[:], uint64(header.Slot)), st)
|
|
}
|
|
|
|
// Loop through `pubKeys` for matching `pubKey` and get the indices where it matches.
|
|
func findSubCommitteeIndices(pubKey []byte, pubKeys [][]byte) []primitives.CommitteeIndex {
|
|
var indices []primitives.CommitteeIndex
|
|
for i, k := range pubKeys {
|
|
if bytes.Equal(k, pubKey) {
|
|
indices = append(indices, primitives.CommitteeIndex(i))
|
|
}
|
|
}
|
|
return indices
|
|
}
|
|
|
|
// SyncPeriodBoundaryRoot computes the current sync period boundary root by calculating sync period start epoch
|
|
// and calling `BlockRoot`.
|
|
// It uses the boundary slot - 1 for block root. (Ex: SlotsPerEpoch * EpochsPerSyncCommitteePeriod - 1)
|
|
func SyncPeriodBoundaryRoot(st state.ReadOnlyBeaconState) ([32]byte, error) {
|
|
// Can't call `BlockRoot` until the first slot.
|
|
if st.Slot() == params.BeaconConfig().GenesisSlot {
|
|
return params.BeaconConfig().ZeroHash, nil
|
|
}
|
|
|
|
startEpoch, err := slots.SyncCommitteePeriodStartEpoch(time.CurrentEpoch(st))
|
|
if err != nil {
|
|
return [32]byte{}, err
|
|
}
|
|
startEpochSlot, err := slots.EpochStart(startEpoch)
|
|
if err != nil {
|
|
return [32]byte{}, err
|
|
}
|
|
|
|
// Prevent underflow
|
|
if startEpochSlot >= 1 {
|
|
startEpochSlot--
|
|
}
|
|
|
|
root, err := BlockRootAtSlot(st, startEpochSlot)
|
|
if err != nil {
|
|
return [32]byte{}, err
|
|
}
|
|
return combineRootAndSlot(root, uint64(startEpochSlot)), nil
|
|
}
|
|
|
|
func combineRootAndSlot(root []byte, slot uint64) [32]byte {
|
|
slotBytes := bytesutil.Uint64ToBytesLittleEndian(slot)
|
|
keyHash := hash.Hash(append(root, slotBytes...))
|
|
return keyHash
|
|
}
|