diff --git a/.github/workflows/check-logs.yml b/.github/workflows/check-logs.yml new file mode 100644 index 0000000000..adb1c99977 --- /dev/null +++ b/.github/workflows/check-logs.yml @@ -0,0 +1,23 @@ +name: Check log.go files +on: [ pull_request ] + +jobs: + check-logs: + runs-on: ubuntu-4 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go 1.25.1 + uses: actions/setup-go@v5 + with: + go-version: '1.25.1' + + - name: Install ripgrep + run: sudo apt-get install -y ripgrep + + - name: Check log.go files + run: ./hack/check-logs.sh diff --git a/BUILD.bazel b/BUILD.bazel index fa57a8afb8..75a2795fa8 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -193,7 +193,7 @@ nogo( "//tools/analyzers/featureconfig:go_default_library", "//tools/analyzers/gocognit:go_default_library", "//tools/analyzers/ineffassign:go_default_library", - "//tools/analyzers/httperror:go_default_library", + "//tools/analyzers/httpwriter:go_default_library", "//tools/analyzers/interfacechecker:go_default_library", "//tools/analyzers/logcapitalization:go_default_library", "//tools/analyzers/logruswitherror:go_default_library", diff --git a/api/apiutil/BUILD.bazel b/api/apiutil/BUILD.bazel index 8cb1cb1fcb..520fa32db6 100644 --- a/api/apiutil/BUILD.bazel +++ b/api/apiutil/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "common.go", "header.go", + "log.go", ], importpath = "github.com/OffchainLabs/prysm/v7/api/apiutil", visibility = ["//visibility:public"], diff --git a/api/apiutil/header.go b/api/apiutil/header.go index 37fdf988e0..54f8204354 100644 --- a/api/apiutil/header.go +++ b/api/apiutil/header.go @@ -5,8 +5,6 @@ import ( "sort" "strconv" "strings" - - log "github.com/sirupsen/logrus" ) type mediaRange struct { diff --git a/api/apiutil/log.go b/api/apiutil/log.go new file mode 100644 index 0000000000..39ad8aec5d --- /dev/null +++ b/api/apiutil/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package apiutil + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "api/apiutil") diff --git a/api/client/beacon/log.go b/api/client/beacon/log.go index b566d20bb5..66cf5aa2b8 100644 --- a/api/client/beacon/log.go +++ b/api/client/beacon/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package beacon import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "beacon") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "api/client/beacon") diff --git a/api/client/builder/BUILD.bazel b/api/client/builder/BUILD.bazel index ef6d736a37..3bdfa953e4 100644 --- a/api/client/builder/BUILD.bazel +++ b/api/client/builder/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "bid.go", "client.go", "errors.go", + "log.go", "types.go", ], importpath = "github.com/OffchainLabs/prysm/v7/api/client/builder", @@ -63,6 +64,5 @@ go_test( "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", ], ) diff --git a/api/client/builder/client.go b/api/client/builder/client.go index 6139a95629..78e2807a9e 100644 --- a/api/client/builder/client.go +++ b/api/client/builder/client.go @@ -25,7 +25,7 @@ import ( ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v7/runtime/version" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) @@ -70,7 +70,7 @@ type requestLogger struct{} func (*requestLogger) observe(r *http.Request) (e error) { b := bytes.NewBuffer(nil) if r.Body == nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "bodyBase64": "(nil value)", "url": r.URL.String(), }).Info("Builder http request") @@ -87,7 +87,7 @@ func (*requestLogger) observe(r *http.Request) (e error) { return err } r.Body = io.NopCloser(b) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "bodyBase64": string(body), "url": r.URL.String(), }).Info("Builder http request") diff --git a/api/client/builder/client_test.go b/api/client/builder/client_test.go index 6ca43f7e66..263c0159ca 100644 --- a/api/client/builder/client_test.go +++ b/api/client/builder/client_test.go @@ -23,7 +23,6 @@ import ( "github.com/OffchainLabs/prysm/v7/testing/assert" "github.com/OffchainLabs/prysm/v7/testing/require" "github.com/OffchainLabs/prysm/v7/testing/util" - log "github.com/sirupsen/logrus" ) type roundtrip func(*http.Request) (*http.Response, error) diff --git a/api/client/builder/log.go b/api/client/builder/log.go new file mode 100644 index 0000000000..e8dbb135c3 --- /dev/null +++ b/api/client/builder/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package builder + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "api/client/builder") diff --git a/api/client/event/BUILD.bazel b/api/client/event/BUILD.bazel index 31f7ebbf38..d68ab6e2b4 100644 --- a/api/client/event/BUILD.bazel +++ b/api/client/event/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "event_stream.go", + "log.go", "utils.go", ], importpath = "github.com/OffchainLabs/prysm/v7/api/client/event", @@ -23,8 +24,5 @@ go_test( "utils_test.go", ], embed = [":go_default_library"], - deps = [ - "//testing/require:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", - ], + deps = ["//testing/require:go_default_library"], ) diff --git a/api/client/event/event_stream.go b/api/client/event/event_stream.go index 3244225883..3d8992e4b0 100644 --- a/api/client/event/event_stream.go +++ b/api/client/event/event_stream.go @@ -10,7 +10,6 @@ import ( "github.com/OffchainLabs/prysm/v7/api" "github.com/OffchainLabs/prysm/v7/api/client" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) const ( diff --git a/api/client/event/event_stream_test.go b/api/client/event/event_stream_test.go index b366ad3671..76e2b94a3b 100644 --- a/api/client/event/event_stream_test.go +++ b/api/client/event/event_stream_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/OffchainLabs/prysm/v7/testing/require" - log "github.com/sirupsen/logrus" ) func TestNewEventStream(t *testing.T) { diff --git a/api/client/event/log.go b/api/client/event/log.go new file mode 100644 index 0000000000..39c40d0ac8 --- /dev/null +++ b/api/client/event/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package event + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "api/client/event") diff --git a/api/grpc/BUILD.bazel b/api/grpc/BUILD.bazel index bf45352f90..16b0e63a6f 100644 --- a/api/grpc/BUILD.bazel +++ b/api/grpc/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "grpcutils.go", + "log.go", "parameters.go", ], importpath = "github.com/OffchainLabs/prysm/v7/api/grpc", diff --git a/api/grpc/grpcutils.go b/api/grpc/grpcutils.go index 54ac97958c..2f710a2ac0 100644 --- a/api/grpc/grpcutils.go +++ b/api/grpc/grpcutils.go @@ -32,7 +32,7 @@ func LogRequests( ) start := time.Now() err := invoker(ctx, method, req, reply, cc, opts...) - logrus.WithField("backend", header["x-backend"]). + log.WithField("backend", header["x-backend"]). WithField("method", method).WithField("duration", time.Since(start)). Debug("gRPC request finished.") return err @@ -58,7 +58,7 @@ func LogStream( grpc.Header(&header), ) strm, err := streamer(ctx, sd, conn, method, opts...) - logrus.WithField("backend", header["x-backend"]). + log.WithField("backend", header["x-backend"]). WithField("method", method). Debug("gRPC stream started.") return strm, err @@ -71,7 +71,7 @@ func AppendHeaders(parent context.Context, headers []string) context.Context { if h != "" { keyValue := strings.Split(h, "=") if len(keyValue) < 2 { - logrus.Warnf("Incorrect gRPC header flag format. Skipping %v", keyValue[0]) + log.Warnf("Incorrect gRPC header flag format. Skipping %v", keyValue[0]) continue } parent = metadata.AppendToOutgoingContext(parent, keyValue[0], strings.Join(keyValue[1:], "=")) // nolint:fatcontext diff --git a/api/grpc/log.go b/api/grpc/log.go new file mode 100644 index 0000000000..3957b1de2f --- /dev/null +++ b/api/grpc/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package grpc + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "api/grpc") diff --git a/api/server/httprest/log.go b/api/server/httprest/log.go index 6208a403ea..3a12e72bc0 100644 --- a/api/server/httprest/log.go +++ b/api/server/httprest/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package httprest import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "httprest") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "api/server/httprest") diff --git a/api/server/middleware/BUILD.bazel b/api/server/middleware/BUILD.bazel index d234346fea..d39a4b7859 100644 --- a/api/server/middleware/BUILD.bazel +++ b/api/server/middleware/BUILD.bazel @@ -3,6 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "log.go", "middleware.go", "util.go", ], @@ -27,6 +28,5 @@ go_test( "//api:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", ], ) diff --git a/api/server/middleware/log.go b/api/server/middleware/log.go new file mode 100644 index 0000000000..a397be65d1 --- /dev/null +++ b/api/server/middleware/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package middleware + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "api/server/middleware") diff --git a/api/server/middleware/middleware.go b/api/server/middleware/middleware.go index 412db44697..33c38448b3 100644 --- a/api/server/middleware/middleware.go +++ b/api/server/middleware/middleware.go @@ -9,7 +9,6 @@ import ( "github.com/OffchainLabs/prysm/v7/api" "github.com/OffchainLabs/prysm/v7/api/apiutil" "github.com/rs/cors" - log "github.com/sirupsen/logrus" ) type Middleware func(http.Handler) http.Handler diff --git a/api/server/middleware/middleware_test.go b/api/server/middleware/middleware_test.go index c5bacce686..67dcef283b 100644 --- a/api/server/middleware/middleware_test.go +++ b/api/server/middleware/middleware_test.go @@ -10,7 +10,6 @@ import ( "github.com/OffchainLabs/prysm/v7/api" "github.com/OffchainLabs/prysm/v7/testing/require" - log "github.com/sirupsen/logrus" ) // frozenHeaderRecorder allows asserting that response headers were not modified diff --git a/async/BUILD.bazel b/async/BUILD.bazel index e1ff1fb811..230763251a 100644 --- a/async/BUILD.bazel +++ b/async/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "debounce.go", "every.go", + "log.go", "multilock.go", "scatter.go", ], diff --git a/async/every.go b/async/every.go index 4173235b8c..3d56e483b0 100644 --- a/async/every.go +++ b/async/every.go @@ -6,8 +6,6 @@ import ( "reflect" "runtime" "time" - - log "github.com/sirupsen/logrus" ) // RunEvery runs the provided command periodically. diff --git a/async/log.go b/async/log.go new file mode 100644 index 0000000000..333182ca30 --- /dev/null +++ b/async/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package async + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "async") diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index 7f89e64c27..1eb74a8934 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "head_sync_committee_info.go", "init_sync_process_block.go", "log.go", + "log_helpers.go", "merge_ascii_art.go", "metrics.go", "options.go", diff --git a/beacon-chain/blockchain/execution_engine.go b/beacon-chain/blockchain/execution_engine.go index 459d09d2d0..beff80ccca 100644 --- a/beacon-chain/blockchain/execution_engine.go +++ b/beacon-chain/blockchain/execution_engine.go @@ -323,14 +323,17 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, var ok bool e := slots.ToEpoch(slot) stateEpoch := slots.ToEpoch(st.Slot()) - if e == stateEpoch { + fuluAndNextEpoch := st.Version() >= version.Fulu && e == stateEpoch+1 + if e == stateEpoch || fuluAndNextEpoch { val, ok = s.trackedProposer(st, slot) if !ok { return emptyAttri } } - st = st.Copy() if slot > st.Slot() { + // At this point either we know we are proposing on a future slot or we need to still compute the + // right proposer index pre-Fulu, either way we need to copy the state to process it. + st = st.Copy() var err error st, err = transition.ProcessSlotsUsingNextSlotCache(ctx, st, headRoot, slot) if err != nil { @@ -338,7 +341,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, return emptyAttri } } - if e > stateEpoch { + if e > stateEpoch && !fuluAndNextEpoch { emptyAttri := payloadattribute.EmptyWithVersion(st.Version()) val, ok = s.trackedProposer(st, slot) if !ok { diff --git a/beacon-chain/blockchain/execution_engine_test.go b/beacon-chain/blockchain/execution_engine_test.go index 3df1118463..e7eda0532c 100644 --- a/beacon-chain/blockchain/execution_engine_test.go +++ b/beacon-chain/blockchain/execution_engine_test.go @@ -1053,40 +1053,3 @@ func TestKZGCommitmentToVersionedHashes(t *testing.T) { require.Equal(t, vhs[0].String(), vh0) require.Equal(t, vhs[1].String(), vh1) } - -func TestComputePayloadAttribute(t *testing.T) { - service, tr := minimalTestService(t, WithPayloadIDCache(cache.NewPayloadIDCache())) - ctx := tr.ctx - - st, _ := util.DeterministicGenesisStateBellatrix(t, 1) - - service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0}) - // Cache hit, advance state, no fee recipient - slot := primitives.Slot(1) - service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{}) - blk := util.NewBeaconBlockBellatrix() - signed, err := consensusblocks.NewSignedBeaconBlock(blk) - require.NoError(t, err) - roblock, err := consensusblocks.NewROBlockWithRoot(signed, [32]byte{'a'}) - require.NoError(t, err) - cfg := &postBlockProcessConfig{ - ctx: ctx, - roblock: roblock, - } - fcu := &fcuConfig{ - headState: st, - proposingSlot: slot, - headRoot: [32]byte{}, - } - require.NoError(t, service.computePayloadAttributes(cfg, fcu)) - require.Equal(t, false, fcu.attributes.IsEmpty()) - require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(fcu.attributes.SuggestedFeeRecipient()).String()) - - // Cache hit, advance state, has fee recipient - suggestedAddr := common.HexToAddress("123") - service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0}) - service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{}) - require.NoError(t, service.computePayloadAttributes(cfg, fcu)) - require.Equal(t, false, fcu.attributes.IsEmpty()) - require.Equal(t, suggestedAddr, common.BytesToAddress(fcu.attributes.SuggestedFeeRecipient())) -} diff --git a/beacon-chain/blockchain/forkchoice_update_execution.go b/beacon-chain/blockchain/forkchoice_update_execution.go index 79d9132e74..57b07019b8 100644 --- a/beacon-chain/blockchain/forkchoice_update_execution.go +++ b/beacon-chain/blockchain/forkchoice_update_execution.go @@ -12,6 +12,7 @@ import ( payloadattribute "github.com/OffchainLabs/prysm/v7/consensus-types/payload-attribute" "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" "github.com/OffchainLabs/prysm/v7/monitoring/tracing/trace" + "github.com/OffchainLabs/prysm/v7/runtime/version" "github.com/OffchainLabs/prysm/v7/time/slots" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -53,58 +54,53 @@ type fcuConfig struct { } // sendFCU handles the logic to notify the engine of a forckhoice update -// for the first time when processing an incoming block during regular sync. It -// always updates the shuffling caches and handles epoch transitions when the -// incoming block is late, preparing payload attributes in this case while it -// only sends a message with empty attributes for early blocks. -func (s *Service) sendFCU(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error { - if !s.isNewHead(cfg.headRoot) { - return nil +// when processing an incoming block during regular sync. It +// always updates the shuffling caches and handles epoch transitions . +func (s *Service) sendFCU(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) { + if cfg.postState.Version() < version.Fulu { + // update the caches to compute the right proposer index + // this function is called under a forkchoice lock which we need to release. + s.ForkChoicer().Unlock() + s.updateCachesPostBlockProcessing(cfg) + s.ForkChoicer().Lock() } + if err := s.getFCUArgs(cfg, fcuArgs); err != nil { + log.WithError(err).Error("Could not get forkchoice update argument") + return + } + // If head has not been updated and attributes are nil, we can skip the FCU. + if !s.isNewHead(cfg.headRoot) && (fcuArgs.attributes == nil || fcuArgs.attributes.IsEmpty()) { + return + } + // If we are proposing and we aim to reorg the block, we have already sent FCU with attributes on lateBlockTasks if fcuArgs.attributes != nil && !fcuArgs.attributes.IsEmpty() && s.shouldOverrideFCU(cfg.headRoot, s.CurrentSlot()+1) { - return nil + return + } + if s.inRegularSync() { + go s.forkchoiceUpdateWithExecution(cfg.ctx, fcuArgs) } - return s.forkchoiceUpdateWithExecution(cfg.ctx, fcuArgs) -} -// sendFCUWithAttributes computes the payload attributes and sends an FCU message -// to the engine if needed -func (s *Service) sendFCUWithAttributes(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) { - slotCtx, cancel := context.WithTimeout(context.Background(), slotDeadline) - defer cancel() - cfg.ctx = slotCtx - s.cfg.ForkChoiceStore.RLock() - defer s.cfg.ForkChoiceStore.RUnlock() - if err := s.computePayloadAttributes(cfg, fcuArgs); err != nil { - log.WithError(err).Error("Could not compute payload attributes") - return - } - if fcuArgs.attributes.IsEmpty() { - return - } - if _, err := s.notifyForkchoiceUpdate(cfg.ctx, fcuArgs); err != nil { - log.WithError(err).Error("Could not update forkchoice with payload attributes for proposal") + if s.isNewHead(fcuArgs.headRoot) { + if err := s.saveHead(cfg.ctx, fcuArgs.headRoot, fcuArgs.headBlock, fcuArgs.headState); err != nil { + log.WithError(err).Error("Could not save head") + } + s.pruneAttsFromPool(s.ctx, fcuArgs.headState, fcuArgs.headBlock) } } -// fockchoiceUpdateWithExecution is a wrapper around notifyForkchoiceUpdate. It decides whether a new call to FCU should be made. -func (s *Service) forkchoiceUpdateWithExecution(ctx context.Context, args *fcuConfig) error { +// fockchoiceUpdateWithExecution is a wrapper around notifyForkchoiceUpdate. It gets a forkchoice lock and calls the engine. +// The caller of this function should NOT have a lock in forkchoice store. +func (s *Service) forkchoiceUpdateWithExecution(ctx context.Context, args *fcuConfig) { _, span := trace.StartSpan(ctx, "beacon-chain.blockchain.forkchoiceUpdateWithExecution") defer span.End() // Note: Use the service context here to avoid the parent context being ended during a forkchoice update. ctx = trace.NewContext(s.ctx, span) + s.ForkChoicer().Lock() + defer s.ForkChoicer().Unlock() _, err := s.notifyForkchoiceUpdate(ctx, args) if err != nil { - return errors.Wrap(err, "could not notify forkchoice update") + log.WithError(err).Error("Could not notify forkchoice update") } - - if err := s.saveHead(ctx, args.headRoot, args.headBlock, args.headState); err != nil { - log.WithError(err).Error("Could not save head") - } - - // Only need to prune attestations from pool if the head has changed. - s.pruneAttsFromPool(s.ctx, args.headState, args.headBlock) - return nil } // shouldOverrideFCU checks whether the incoming block is still subject to being diff --git a/beacon-chain/blockchain/forkchoice_update_execution_test.go b/beacon-chain/blockchain/forkchoice_update_execution_test.go index 2f7746147d..b08d307157 100644 --- a/beacon-chain/blockchain/forkchoice_update_execution_test.go +++ b/beacon-chain/blockchain/forkchoice_update_execution_test.go @@ -97,7 +97,7 @@ func TestService_forkchoiceUpdateWithExecution_exceptionalCases(t *testing.T) { headBlock: wsb, proposingSlot: service.CurrentSlot() + 1, } - require.NoError(t, service.forkchoiceUpdateWithExecution(ctx, args)) + service.forkchoiceUpdateWithExecution(ctx, args) payloadID, has := service.cfg.PayloadIDCache.PayloadID(2, [32]byte{2}) require.Equal(t, true, has) @@ -151,7 +151,7 @@ func TestService_forkchoiceUpdateWithExecution_SameHeadRootNewProposer(t *testin headRoot: r, proposingSlot: service.CurrentSlot() + 1, } - require.NoError(t, service.forkchoiceUpdateWithExecution(ctx, args)) + service.forkchoiceUpdateWithExecution(ctx, args) } func TestShouldOverrideFCU(t *testing.T) { diff --git a/beacon-chain/blockchain/log.go b/beacon-chain/blockchain/log.go index 8e768a5f25..ebd57f783e 100644 --- a/beacon-chain/blockchain/log.go +++ b/beacon-chain/blockchain/log.go @@ -1,164 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package blockchain -import ( - "encoding/hex" - "fmt" - "time" +import "github.com/sirupsen/logrus" - "github.com/OffchainLabs/prysm/v7/beacon-chain/core/blocks" - "github.com/OffchainLabs/prysm/v7/config/params" - consensus_types "github.com/OffchainLabs/prysm/v7/consensus-types" - "github.com/OffchainLabs/prysm/v7/consensus-types/interfaces" - "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" - ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" - "github.com/OffchainLabs/prysm/v7/runtime/version" - prysmTime "github.com/OffchainLabs/prysm/v7/time" - "github.com/OffchainLabs/prysm/v7/time/slots" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -var log = logrus.WithField("prefix", "blockchain") - -// logs state transition related data every slot. -func logStateTransitionData(b interfaces.ReadOnlyBeaconBlock) error { - log := log.WithField("slot", b.Slot()) - if len(b.Body().Attestations()) > 0 { - log = log.WithField("attestations", len(b.Body().Attestations())) - } - if len(b.Body().AttesterSlashings()) > 0 { - log = log.WithField("attesterSlashings", len(b.Body().AttesterSlashings())) - } - if len(b.Body().ProposerSlashings()) > 0 { - log = log.WithField("proposerSlashings", len(b.Body().ProposerSlashings())) - } - if len(b.Body().VoluntaryExits()) > 0 { - log = log.WithField("voluntaryExits", len(b.Body().VoluntaryExits())) - } - if b.Version() >= version.Altair { - agg, err := b.Body().SyncAggregate() - if err != nil { - return err - } - log = log.WithField("syncBitsCount", agg.SyncCommitteeBits.Count()) - } - if b.Version() >= version.Bellatrix { - p, err := b.Body().Execution() - if err != nil { - return err - } - log = log.WithField("payloadHash", fmt.Sprintf("%#x", bytesutil.Trunc(p.BlockHash()))) - txs, err := p.Transactions() - switch { - case errors.Is(err, consensus_types.ErrUnsupportedField): - case err != nil: - return err - default: - log = log.WithField("txCount", len(txs)) - txsPerSlotCount.Set(float64(len(txs))) - } - } - if b.Version() >= version.Deneb { - kzgs, err := b.Body().BlobKzgCommitments() - if err != nil { - log.WithError(err).Error("Failed to get blob KZG commitments") - } else if len(kzgs) > 0 { - log = log.WithField("kzgCommitmentCount", len(kzgs)) - } - } - if b.Version() >= version.Electra { - eReqs, err := b.Body().ExecutionRequests() - if err != nil { - log.WithError(err).Error("Failed to get execution requests") - } else { - if len(eReqs.Deposits) > 0 { - log = log.WithField("depositRequestCount", len(eReqs.Deposits)) - } - if len(eReqs.Consolidations) > 0 { - log = log.WithField("consolidationRequestCount", len(eReqs.Consolidations)) - } - if len(eReqs.Withdrawals) > 0 { - log = log.WithField("withdrawalRequestCount", len(eReqs.Withdrawals)) - } - } - } - log.Info("Finished applying state transition") - return nil -} - -func logBlockSyncStatus(block interfaces.ReadOnlyBeaconBlock, blockRoot [32]byte, justified, finalized *ethpb.Checkpoint, receivedTime time.Time, genesis time.Time, daWaitedTime time.Duration) error { - startTime, err := slots.StartTime(genesis, block.Slot()) - if err != nil { - return err - } - level := log.Logger.GetLevel() - if level >= logrus.DebugLevel { - parentRoot := block.ParentRoot() - lf := logrus.Fields{ - "slot": block.Slot(), - "slotInEpoch": block.Slot() % params.BeaconConfig().SlotsPerEpoch, - "block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]), - "epoch": slots.ToEpoch(block.Slot()), - "justifiedEpoch": justified.Epoch, - "justifiedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(justified.Root)[:8]), - "finalizedEpoch": finalized.Epoch, - "finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]), - "parentRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(parentRoot[:])[:8]), - "version": version.String(block.Version()), - "sinceSlotStartTime": prysmTime.Now().Sub(startTime), - "chainServiceProcessedTime": prysmTime.Now().Sub(receivedTime) - daWaitedTime, - "dataAvailabilityWaitedTime": daWaitedTime, - } - log.WithFields(lf).Debug("Synced new block") - } else { - log.WithFields(logrus.Fields{ - "slot": block.Slot(), - "block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]), - "finalizedEpoch": finalized.Epoch, - "finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]), - "epoch": slots.ToEpoch(block.Slot()), - }).Info("Synced new block") - } - return nil -} - -// logs payload related data every slot. -func logPayload(block interfaces.ReadOnlyBeaconBlock) error { - isExecutionBlk, err := blocks.IsExecutionBlock(block.Body()) - if err != nil { - return errors.Wrap(err, "could not determine if block is execution block") - } - if !isExecutionBlk { - return nil - } - payload, err := block.Body().Execution() - if err != nil { - return err - } - if payload.GasLimit() == 0 { - return errors.New("gas limit should not be 0") - } - gasUtilized := float64(payload.GasUsed()) / float64(payload.GasLimit()) - fields := logrus.Fields{ - "blockHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash())), - "parentHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.ParentHash())), - "blockNumber": payload.BlockNumber(), - "gasUtilized": fmt.Sprintf("%.2f", gasUtilized), - } - if block.Version() >= version.Capella { - withdrawals, err := payload.Withdrawals() - if err != nil { - return errors.Wrap(err, "could not get withdrawals") - } - fields["withdrawals"] = len(withdrawals) - changes, err := block.Body().BLSToExecutionChanges() - if err != nil { - return errors.Wrap(err, "could not get BLSToExecutionChanges") - } - if len(changes) > 0 { - fields["blsToExecutionChanges"] = len(changes) - } - } - log.WithFields(fields).Debug("Synced new payload") - return nil -} +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/blockchain") diff --git a/beacon-chain/blockchain/log_helpers.go b/beacon-chain/blockchain/log_helpers.go new file mode 100644 index 0000000000..83d5238a50 --- /dev/null +++ b/beacon-chain/blockchain/log_helpers.go @@ -0,0 +1,162 @@ +package blockchain + +import ( + "encoding/hex" + "fmt" + "time" + + "github.com/OffchainLabs/prysm/v7/beacon-chain/core/blocks" + "github.com/OffchainLabs/prysm/v7/config/params" + consensus_types "github.com/OffchainLabs/prysm/v7/consensus-types" + "github.com/OffchainLabs/prysm/v7/consensus-types/interfaces" + "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" + ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" + "github.com/OffchainLabs/prysm/v7/runtime/version" + prysmTime "github.com/OffchainLabs/prysm/v7/time" + "github.com/OffchainLabs/prysm/v7/time/slots" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// logs state transition related data every slot. +func logStateTransitionData(b interfaces.ReadOnlyBeaconBlock) error { + log := log.WithField("slot", b.Slot()) + if len(b.Body().Attestations()) > 0 { + log = log.WithField("attestations", len(b.Body().Attestations())) + } + if len(b.Body().AttesterSlashings()) > 0 { + log = log.WithField("attesterSlashings", len(b.Body().AttesterSlashings())) + } + if len(b.Body().ProposerSlashings()) > 0 { + log = log.WithField("proposerSlashings", len(b.Body().ProposerSlashings())) + } + if len(b.Body().VoluntaryExits()) > 0 { + log = log.WithField("voluntaryExits", len(b.Body().VoluntaryExits())) + } + if b.Version() >= version.Altair { + agg, err := b.Body().SyncAggregate() + if err != nil { + return err + } + log = log.WithField("syncBitsCount", agg.SyncCommitteeBits.Count()) + } + if b.Version() >= version.Bellatrix { + p, err := b.Body().Execution() + if err != nil { + return err + } + log = log.WithField("payloadHash", fmt.Sprintf("%#x", bytesutil.Trunc(p.BlockHash()))) + txs, err := p.Transactions() + switch { + case errors.Is(err, consensus_types.ErrUnsupportedField): + case err != nil: + return err + default: + log = log.WithField("txCount", len(txs)) + txsPerSlotCount.Set(float64(len(txs))) + } + } + if b.Version() >= version.Deneb { + kzgs, err := b.Body().BlobKzgCommitments() + if err != nil { + log.WithError(err).Error("Failed to get blob KZG commitments") + } else if len(kzgs) > 0 { + log = log.WithField("kzgCommitmentCount", len(kzgs)) + } + } + if b.Version() >= version.Electra { + eReqs, err := b.Body().ExecutionRequests() + if err != nil { + log.WithError(err).Error("Failed to get execution requests") + } else { + if len(eReqs.Deposits) > 0 { + log = log.WithField("depositRequestCount", len(eReqs.Deposits)) + } + if len(eReqs.Consolidations) > 0 { + log = log.WithField("consolidationRequestCount", len(eReqs.Consolidations)) + } + if len(eReqs.Withdrawals) > 0 { + log = log.WithField("withdrawalRequestCount", len(eReqs.Withdrawals)) + } + } + } + log.Info("Finished applying state transition") + return nil +} + +func logBlockSyncStatus(block interfaces.ReadOnlyBeaconBlock, blockRoot [32]byte, justified, finalized *ethpb.Checkpoint, receivedTime time.Time, genesis time.Time, daWaitedTime time.Duration) error { + startTime, err := slots.StartTime(genesis, block.Slot()) + if err != nil { + return err + } + level := log.Logger.GetLevel() + if level >= logrus.DebugLevel { + parentRoot := block.ParentRoot() + lf := logrus.Fields{ + "slot": block.Slot(), + "slotInEpoch": block.Slot() % params.BeaconConfig().SlotsPerEpoch, + "block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]), + "epoch": slots.ToEpoch(block.Slot()), + "justifiedEpoch": justified.Epoch, + "justifiedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(justified.Root)[:8]), + "finalizedEpoch": finalized.Epoch, + "finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]), + "parentRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(parentRoot[:])[:8]), + "version": version.String(block.Version()), + "sinceSlotStartTime": prysmTime.Now().Sub(startTime), + "chainServiceProcessedTime": prysmTime.Now().Sub(receivedTime) - daWaitedTime, + "dataAvailabilityWaitedTime": daWaitedTime, + } + log.WithFields(lf).Debug("Synced new block") + } else { + log.WithFields(logrus.Fields{ + "slot": block.Slot(), + "block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]), + "finalizedEpoch": finalized.Epoch, + "finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]), + "epoch": slots.ToEpoch(block.Slot()), + }).Info("Synced new block") + } + return nil +} + +// logs payload related data every slot. +func logPayload(block interfaces.ReadOnlyBeaconBlock) error { + isExecutionBlk, err := blocks.IsExecutionBlock(block.Body()) + if err != nil { + return errors.Wrap(err, "could not determine if block is execution block") + } + if !isExecutionBlk { + return nil + } + payload, err := block.Body().Execution() + if err != nil { + return err + } + if payload.GasLimit() == 0 { + return errors.New("gas limit should not be 0") + } + gasUtilized := float64(payload.GasUsed()) / float64(payload.GasLimit()) + fields := logrus.Fields{ + "blockHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash())), + "parentHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.ParentHash())), + "blockNumber": payload.BlockNumber(), + "gasUtilized": fmt.Sprintf("%.2f", gasUtilized), + } + if block.Version() >= version.Capella { + withdrawals, err := payload.Withdrawals() + if err != nil { + return errors.Wrap(err, "could not get withdrawals") + } + fields["withdrawals"] = len(withdrawals) + changes, err := block.Body().BLSToExecutionChanges() + if err != nil { + return errors.Wrap(err, "could not get BLSToExecutionChanges") + } + if len(changes) > 0 { + fields["blsToExecutionChanges"] = len(changes) + } + } + log.WithFields(fields).Debug("Synced new payload") + return nil +} diff --git a/beacon-chain/blockchain/log_test.go b/beacon-chain/blockchain/log_test.go index 5f64aaa78a..03917944f7 100644 --- a/beacon-chain/blockchain/log_test.go +++ b/beacon-chain/blockchain/log_test.go @@ -34,7 +34,7 @@ func Test_logStateTransitionData(t *testing.T) { require.NoError(t, err) return wb }, - want: "\"Finished applying state transition\" prefix=blockchain slot=0", + want: "\"Finished applying state transition\" package=beacon-chain/blockchain slot=0", }, {name: "has attestation", b: func() interfaces.ReadOnlyBeaconBlock { @@ -42,7 +42,7 @@ func Test_logStateTransitionData(t *testing.T) { require.NoError(t, err) return wb }, - want: "\"Finished applying state transition\" attestations=1 prefix=blockchain slot=0", + want: "\"Finished applying state transition\" attestations=1 package=beacon-chain/blockchain slot=0", }, {name: "has deposit", b: func() interfaces.ReadOnlyBeaconBlock { @@ -53,7 +53,7 @@ func Test_logStateTransitionData(t *testing.T) { require.NoError(t, err) return wb }, - want: "\"Finished applying state transition\" attestations=1 prefix=blockchain slot=0", + want: "\"Finished applying state transition\" attestations=1 package=beacon-chain/blockchain slot=0", }, {name: "has attester slashing", b: func() interfaces.ReadOnlyBeaconBlock { @@ -62,7 +62,7 @@ func Test_logStateTransitionData(t *testing.T) { require.NoError(t, err) return wb }, - want: "\"Finished applying state transition\" attesterSlashings=1 prefix=blockchain slot=0", + want: "\"Finished applying state transition\" attesterSlashings=1 package=beacon-chain/blockchain slot=0", }, {name: "has proposer slashing", b: func() interfaces.ReadOnlyBeaconBlock { @@ -71,7 +71,7 @@ func Test_logStateTransitionData(t *testing.T) { require.NoError(t, err) return wb }, - want: "\"Finished applying state transition\" prefix=blockchain proposerSlashings=1 slot=0", + want: "\"Finished applying state transition\" package=beacon-chain/blockchain proposerSlashings=1 slot=0", }, {name: "has exit", b: func() interfaces.ReadOnlyBeaconBlock { @@ -80,7 +80,7 @@ func Test_logStateTransitionData(t *testing.T) { require.NoError(t, err) return wb }, - want: "\"Finished applying state transition\" prefix=blockchain slot=0 voluntaryExits=1", + want: "\"Finished applying state transition\" package=beacon-chain/blockchain slot=0 voluntaryExits=1", }, {name: "has everything", b: func() interfaces.ReadOnlyBeaconBlock { @@ -93,11 +93,11 @@ func Test_logStateTransitionData(t *testing.T) { require.NoError(t, err) return wb }, - want: "\"Finished applying state transition\" attestations=1 attesterSlashings=1 prefix=blockchain proposerSlashings=1 slot=0 voluntaryExits=1", + want: "\"Finished applying state transition\" attestations=1 attesterSlashings=1 package=beacon-chain/blockchain proposerSlashings=1 slot=0 voluntaryExits=1", }, {name: "has payload", b: func() interfaces.ReadOnlyBeaconBlock { return wrappedPayloadBlk }, - want: "\"Finished applying state transition\" payloadHash=0x010203 prefix=blockchain slot=0 syncBitsCount=0 txCount=2", + want: "\"Finished applying state transition\" package=beacon-chain/blockchain payloadHash=0x010203 slot=0 syncBitsCount=0 txCount=2", }, } for _, tt := range tests { diff --git a/beacon-chain/blockchain/process_attestation_helpers.go b/beacon-chain/blockchain/process_attestation_helpers.go index 24185cc8db..ec9e86602c 100644 --- a/beacon-chain/blockchain/process_attestation_helpers.go +++ b/beacon-chain/blockchain/process_attestation_helpers.go @@ -22,7 +22,7 @@ import ( // The caller of this function must have a lock on forkchoice. func (s *Service) getRecentPreState(ctx context.Context, c *ethpb.Checkpoint) state.ReadOnlyBeaconState { headEpoch := slots.ToEpoch(s.HeadSlot()) - if c.Epoch < headEpoch || c.Epoch == 0 { + if c.Epoch+1 < headEpoch || c.Epoch == 0 { return nil } // Only use head state if the head state is compatible with the target checkpoint. @@ -30,11 +30,13 @@ func (s *Service) getRecentPreState(ctx context.Context, c *ethpb.Checkpoint) st if err != nil { return nil } - headDependent, err := s.cfg.ForkChoiceStore.DependentRootForEpoch([32]byte(headRoot), c.Epoch-1) + // headEpoch - 1 equals c.Epoch if c is from the previous epoch and equals c.Epoch - 1 if c is from the current epoch. + // We don't use the smaller c.Epoch - 1 because forkchoice would not have the data to answer that. + headDependent, err := s.cfg.ForkChoiceStore.DependentRootForEpoch([32]byte(headRoot), headEpoch-1) if err != nil { return nil } - targetDependent, err := s.cfg.ForkChoiceStore.DependentRootForEpoch([32]byte(c.Root), c.Epoch-1) + targetDependent, err := s.cfg.ForkChoiceStore.DependentRootForEpoch([32]byte(c.Root), headEpoch-1) if err != nil { return nil } @@ -43,7 +45,7 @@ func (s *Service) getRecentPreState(ctx context.Context, c *ethpb.Checkpoint) st } // If the head state alone is enough, we can return it directly read only. - if c.Epoch == headEpoch { + if c.Epoch <= headEpoch { st, err := s.HeadStateReadOnly(ctx) if err != nil { return nil diff --git a/beacon-chain/blockchain/process_attestation_test.go b/beacon-chain/blockchain/process_attestation_test.go index 8874de9700..1a3b7e0f52 100644 --- a/beacon-chain/blockchain/process_attestation_test.go +++ b/beacon-chain/blockchain/process_attestation_test.go @@ -170,12 +170,13 @@ func TestService_GetRecentPreState(t *testing.T) { err = s.SetFinalizedCheckpoint(cp0) require.NoError(t, err) - st, root, err := prepareForkchoiceState(ctx, 31, [32]byte(ckRoot), [32]byte{}, [32]byte{'R'}, cp0, cp0) + st, blk, err := prepareForkchoiceState(ctx, 31, [32]byte(ckRoot), [32]byte{}, [32]byte{'R'}, cp0, cp0) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, root)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blk)) service.head = &head{ root: [32]byte(ckRoot), state: s, + block: blk, slot: 31, } require.NotNil(t, service.getRecentPreState(ctx, ðpb.Checkpoint{Epoch: 1, Root: ckRoot})) @@ -197,12 +198,13 @@ func TestService_GetRecentPreState_Old_Checkpoint(t *testing.T) { err = s.SetFinalizedCheckpoint(cp0) require.NoError(t, err) - st, root, err := prepareForkchoiceState(ctx, 33, [32]byte(ckRoot), [32]byte{}, [32]byte{'R'}, cp0, cp0) + st, blk, err := prepareForkchoiceState(ctx, 33, [32]byte(ckRoot), [32]byte{}, [32]byte{'R'}, cp0, cp0) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, root)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blk)) service.head = &head{ root: [32]byte(ckRoot), state: s, + block: blk, slot: 33, } require.IsNil(t, service.getRecentPreState(ctx, ðpb.Checkpoint{})) @@ -227,6 +229,7 @@ func TestService_GetRecentPreState_Same_DependentRoots(t *testing.T) { require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blk)) st, blk, err = prepareForkchoiceState(ctx, 64, [32]byte{'T'}, blk.Root(), [32]byte{}, cp0, cp0) require.NoError(t, err) + headBlock := blk require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blk)) st, blk, err = prepareForkchoiceState(ctx, 33, [32]byte{'U'}, [32]byte(ckRoot), [32]byte{}, cp0, cp0) require.NoError(t, err) @@ -235,8 +238,9 @@ func TestService_GetRecentPreState_Same_DependentRoots(t *testing.T) { service.head = &head{ root: [32]byte{'T'}, - state: s, + block: headBlock, slot: 64, + state: s, } require.NotNil(t, service.getRecentPreState(ctx, ðpb.Checkpoint{Epoch: 2, Root: cpRoot[:]})) } @@ -263,6 +267,7 @@ func TestService_GetRecentPreState_Different_DependentRoots(t *testing.T) { require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blk)) st, blk, err = prepareForkchoiceState(ctx, 64, [32]byte{'U'}, blk.Root(), [32]byte{}, cp0, cp0) require.NoError(t, err) + headBlock := blk require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blk)) st, blk, err = prepareForkchoiceState(ctx, 33, [32]byte{'V'}, [32]byte(ckRoot), [32]byte{}, cp0, cp0) require.NoError(t, err) @@ -270,7 +275,8 @@ func TestService_GetRecentPreState_Different_DependentRoots(t *testing.T) { cpRoot := blk.Root() service.head = &head{ - root: [32]byte{'T'}, + root: [32]byte{'U'}, + block: headBlock, state: s, slot: 64, } @@ -287,12 +293,13 @@ func TestService_GetRecentPreState_Different(t *testing.T) { err = s.SetFinalizedCheckpoint(cp0) require.NoError(t, err) - st, root, err := prepareForkchoiceState(ctx, 33, [32]byte(ckRoot), [32]byte{}, [32]byte{'R'}, cp0, cp0) + st, blk, err := prepareForkchoiceState(ctx, 33, [32]byte(ckRoot), [32]byte{}, [32]byte{'R'}, cp0, cp0) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, root)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blk)) service.head = &head{ root: [32]byte(ckRoot), state: s, + block: blk, slot: 33, } require.IsNil(t, service.getRecentPreState(ctx, ðpb.Checkpoint{})) diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index a15563ad21..dd840548dd 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -66,9 +66,6 @@ func (s *Service) postBlockProcess(cfg *postBlockProcessConfig) error { startTime := time.Now() fcuArgs := &fcuConfig{} - if s.inRegularSync() { - defer s.handleSecondFCUCall(cfg, fcuArgs) - } if features.Get().EnableLightClient && slots.ToEpoch(s.CurrentSlot()) >= params.BeaconConfig().AltairForkEpoch { defer s.processLightClientUpdates(cfg) } @@ -105,14 +102,17 @@ func (s *Service) postBlockProcess(cfg *postBlockProcessConfig) error { s.logNonCanonicalBlockReceived(cfg.roblock.Root(), cfg.headRoot) return nil } - if err := s.getFCUArgs(cfg, fcuArgs); err != nil { - log.WithError(err).Error("Could not get forkchoice update argument") - return nil - } - if err := s.sendFCU(cfg, fcuArgs); err != nil { - return errors.Wrap(err, "could not send FCU to engine") - } + s.sendFCU(cfg, fcuArgs) + // Pre-Fulu the caches are updated when computing the payload attributes + if cfg.postState.Version() >= version.Fulu { + go func() { + ctx, cancel := context.WithTimeout(s.ctx, slotDeadline) + defer cancel() + cfg.ctx = ctx + s.updateCachesPostBlockProcessing(cfg) + }() + } return nil } @@ -295,14 +295,6 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []consensusblocks.ROBlo return errors.Wrap(err, "could not set optimistic block to valid") } } - arg := &fcuConfig{ - headState: preState, - headRoot: lastBR, - headBlock: lastB, - } - if _, err := s.notifyForkchoiceUpdate(ctx, arg); err != nil { - return err - } return s.saveHeadNoDB(ctx, lastB, lastBR, preState, !isValidPayload) } @@ -330,6 +322,7 @@ func (s *Service) areSidecarsAvailable(ctx context.Context, avs das.Availability return nil } +// the caller of this function must not hold a lock in forkchoice store. func (s *Service) updateEpochBoundaryCaches(ctx context.Context, st state.BeaconState) error { e := coreTime.CurrentEpoch(st) if err := helpers.UpdateCommitteeCache(ctx, st, e); err != nil { @@ -359,7 +352,9 @@ func (s *Service) updateEpochBoundaryCaches(ctx context.Context, st state.Beacon if e > 0 { e = e - 1 } + s.ForkChoicer().RLock() target, err := s.cfg.ForkChoiceStore.TargetRootForEpoch(r, e) + s.ForkChoicer().RUnlock() if err != nil { log.WithError(err).Error("Could not update proposer index state-root map") return nil @@ -372,7 +367,7 @@ func (s *Service) updateEpochBoundaryCaches(ctx context.Context, st state.Beacon } // Epoch boundary tasks: it copies the headState and updates the epoch boundary -// caches. +// caches. The caller of this function must not hold a lock in forkchoice store. func (s *Service) handleEpochBoundary(ctx context.Context, slot primitives.Slot, headState state.BeaconState, blockRoot []byte) error { ctx, span := trace.StartSpan(ctx, "blockChain.handleEpochBoundary") defer span.End() @@ -912,8 +907,6 @@ func (s *Service) lateBlockTasks(ctx context.Context) { if currentSlot == s.HeadSlot() { return } - s.cfg.ForkChoiceStore.RLock() - defer s.cfg.ForkChoiceStore.RUnlock() // return early if we are in init sync if !s.inRegularSync() { return @@ -926,14 +919,32 @@ func (s *Service) lateBlockTasks(ctx context.Context) { if lastState == nil { lastRoot, lastState = headRoot[:], headState } - // Copy all the field tries in our cached state in the event of late - // blocks. - lastState.CopyAllTries() - if err := transition.UpdateNextSlotCache(ctx, lastRoot, lastState); err != nil { - log.WithError(err).Debug("Could not update next slot state cache") - } - if err := s.handleEpochBoundary(ctx, currentSlot, headState, headRoot[:]); err != nil { - log.WithError(err).Error("Could not update epoch boundary caches") + // Before Fulu we need to process the next slot to find out if we are proposing. + if lastState.Version() < version.Fulu { + // Copy all the field tries in our cached state in the event of late + // blocks. + lastState.CopyAllTries() + if err := transition.UpdateNextSlotCache(ctx, lastRoot, lastState); err != nil { + log.WithError(err).Debug("Could not update next slot state cache") + } + if err := s.handleEpochBoundary(ctx, currentSlot, headState, headRoot[:]); err != nil { + log.WithError(err).Error("Could not update epoch boundary caches") + } + } else { + // After Fulu, we can update the caches asynchronously after sending FCU to the engine + defer func() { + go func() { + ctx, cancel := context.WithTimeout(s.ctx, slotDeadline) + defer cancel() + lastState.CopyAllTries() + if err := transition.UpdateNextSlotCache(ctx, lastRoot, lastState); err != nil { + log.WithError(err).Debug("Could not update next slot state cache") + } + if err := s.handleEpochBoundary(ctx, currentSlot, headState, headRoot[:]); err != nil { + log.WithError(err).Error("Could not update epoch boundary caches") + } + }() + }() } // return early if we already started building a block for the current // head root @@ -963,6 +974,8 @@ func (s *Service) lateBlockTasks(ctx context.Context) { headBlock: headBlock, attributes: attribute, } + s.cfg.ForkChoiceStore.Lock() + defer s.cfg.ForkChoiceStore.Unlock() _, err = s.notifyForkchoiceUpdate(ctx, fcuArgs) if err != nil { log.WithError(err).Debug("could not perform late block tasks: failed to update forkchoice with engine") diff --git a/beacon-chain/blockchain/process_block_helpers.go b/beacon-chain/blockchain/process_block_helpers.go index df7790752a..3f60e78e3f 100644 --- a/beacon-chain/blockchain/process_block_helpers.go +++ b/beacon-chain/blockchain/process_block_helpers.go @@ -42,14 +42,8 @@ func (s *Service) getFCUArgs(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) er if err := s.getFCUArgsEarlyBlock(cfg, fcuArgs); err != nil { return err } - if !s.inRegularSync() { - return nil - } - slot := cfg.roblock.Block().Slot() - if slots.WithinVotingWindow(s.genesisTime, slot) { - return nil - } - return s.computePayloadAttributes(cfg, fcuArgs) + fcuArgs.attributes = s.getPayloadAttribute(cfg.ctx, fcuArgs.headState, fcuArgs.proposingSlot, cfg.headRoot[:]) + return nil } func (s *Service) getFCUArgsEarlyBlock(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error { @@ -173,26 +167,19 @@ func (s *Service) processLightClientUpdates(cfg *postBlockProcessConfig) { // updateCachesPostBlockProcessing updates the next slot cache and handles the epoch // boundary in order to compute the right proposer indices after processing -// state transition. This function is called on late blocks while still locked, -// before sending FCU to the engine. -func (s *Service) updateCachesPostBlockProcessing(cfg *postBlockProcessConfig) error { +// state transition. The caller of this function must not hold a lock in forkchoice store. +func (s *Service) updateCachesPostBlockProcessing(cfg *postBlockProcessConfig) { slot := cfg.postState.Slot() root := cfg.roblock.Root() if err := transition.UpdateNextSlotCache(cfg.ctx, root[:], cfg.postState); err != nil { - return errors.Wrap(err, "could not update next slot state cache") + log.WithError(err).Error("Could not update next slot state cache") + return } if !slots.IsEpochEnd(slot) { - return nil + return } - return s.handleEpochBoundary(cfg.ctx, slot, cfg.postState, root[:]) -} - -// handleSecondFCUCall handles a second call to FCU when syncing a new block. -// This is useful when proposing in the next block and we want to defer the -// computation of the next slot shuffling. -func (s *Service) handleSecondFCUCall(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) { - if (fcuArgs.attributes == nil || fcuArgs.attributes.IsEmpty()) && cfg.headRoot == cfg.roblock.Root() { - go s.sendFCUWithAttributes(cfg, fcuArgs) + if err := s.handleEpochBoundary(cfg.ctx, slot, cfg.postState, root[:]); err != nil { + log.WithError(err).Error("Could not handle epoch boundary") } } @@ -202,20 +189,6 @@ func reportProcessingTime(startTime time.Time) { onBlockProcessingTime.Observe(float64(time.Since(startTime).Milliseconds())) } -// computePayloadAttributes modifies the passed FCU arguments to -// contain the right payload attributes with the tracked proposer. It gets -// called on blocks that arrive after the attestation voting window, or in a -// background routine after syncing early blocks. -func (s *Service) computePayloadAttributes(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error { - if cfg.roblock.Root() == cfg.headRoot { - if err := s.updateCachesPostBlockProcessing(cfg); err != nil { - return err - } - } - fcuArgs.attributes = s.getPayloadAttribute(cfg.ctx, fcuArgs.headState, fcuArgs.proposingSlot, cfg.headRoot[:]) - return nil -} - // getBlockPreState returns the pre state of an incoming block. It uses the parent root of the block // to retrieve the state in DB. It verifies the pre state's validity and the incoming block // is in the correct time window. diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index cc2d9d9c74..7ef16025f9 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -738,7 +738,9 @@ func TestOnBlock_CanFinalize_WithOnTick(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, r, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, service.updateJustificationOnBlock(ctx, preState, postState, currStoreJustifiedEpoch)) _, err = service.updateFinalizationOnBlock(ctx, preState, postState, currStoreFinalizedEpoch) require.NoError(t, err) @@ -788,7 +790,9 @@ func TestOnBlock_CanFinalize(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, r, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, service.updateJustificationOnBlock(ctx, preState, postState, currStoreJustifiedEpoch)) _, err = service.updateFinalizationOnBlock(ctx, preState, postState, currStoreFinalizedEpoch) require.NoError(t, err) @@ -816,25 +820,9 @@ func TestOnBlock_NilBlock(t *testing.T) { service, tr := minimalTestService(t) signed := &consensusblocks.SignedBeaconBlock{} roblock := consensusblocks.ROBlock{ReadOnlySignedBeaconBlock: signed} + service.cfg.ForkChoiceStore.Lock() err := service.postBlockProcess(&postBlockProcessConfig{tr.ctx, roblock, [32]byte{}, nil, true}) - require.Equal(t, true, IsInvalidBlock(err)) -} - -func TestOnBlock_InvalidSignature(t *testing.T) { - service, tr := minimalTestService(t) - ctx := tr.ctx - - gs, keys := util.DeterministicGenesisState(t, 32) - require.NoError(t, service.saveGenesisData(ctx, gs)) - - blk, err := util.GenerateFullBlock(gs, keys, util.DefaultBlockGenConfig(), 1) - require.NoError(t, err) - blk.Signature = []byte{'a'} // Mutate the signature. - wsb, err := consensusblocks.NewSignedBeaconBlock(blk) - require.NoError(t, err) - preState, err := service.getBlockPreState(ctx, wsb.Block()) - require.NoError(t, err) - _, err = service.validateStateTransition(ctx, preState, wsb) + service.cfg.ForkChoiceStore.Unlock() require.Equal(t, true, IsInvalidBlock(err)) } @@ -866,7 +854,9 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, r, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() testState, err = service.cfg.StateGen.StateByRoot(ctx, r) require.NoError(t, err) } @@ -1339,7 +1329,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { lock.Lock() roblock, err := consensusblocks.NewROBlockWithRoot(wsb1, r1) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) + service.cfg.ForkChoiceStore.Unlock() lock.Unlock() wg.Done() }() @@ -1351,7 +1343,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { lock.Lock() roblock, err := consensusblocks.NewROBlockWithRoot(wsb2, r2) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) + service.cfg.ForkChoiceStore.Unlock() lock.Unlock() wg.Done() }() @@ -1363,7 +1357,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { lock.Lock() roblock, err := consensusblocks.NewROBlockWithRoot(wsb3, r3) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) + service.cfg.ForkChoiceStore.Unlock() lock.Unlock() wg.Done() }() @@ -1375,7 +1371,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { lock.Lock() roblock, err := consensusblocks.NewROBlockWithRoot(wsb4, r4) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) + service.cfg.ForkChoiceStore.Unlock() lock.Unlock() wg.Done() }() @@ -1400,197 +1398,6 @@ func Test_verifyBlkFinalizedSlot_invalidBlock(t *testing.T) { require.Equal(t, true, IsInvalidBlock(err)) } -// See the description in #10777 and #10782 for the full setup -// We sync optimistically a chain of blocks. Block 17 is the last block in Epoch -// 2. Block 18 justifies block 12 (the first in Epoch 2) and Block 19 returns -// INVALID from FCU, with LVH block 17. No head is viable. We check -// that the node is optimistic and that we can actually import a block on top of -// 17 and recover. -func TestStore_NoViableHead_FCU(t *testing.T) { - params.SetupTestConfigCleanup(t) - config := params.BeaconConfig() - config.SlotsPerEpoch = 6 - config.AltairForkEpoch = 1 - config.BellatrixForkEpoch = 2 - params.OverrideBeaconConfig(config) - - mockEngine := &mockExecution.EngineClient{ErrNewPayload: execution.ErrAcceptedSyncingPayloadStatus, ErrForkchoiceUpdated: execution.ErrAcceptedSyncingPayloadStatus} - service, tr := minimalTestService(t, WithExecutionEngineCaller(mockEngine)) - ctx := tr.ctx - - st, keys := util.DeterministicGenesisState(t, 64) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err, "Could not hash genesis state") - - require.NoError(t, service.saveGenesisData(ctx, st)) - - genesis := blocks.NewGenesisBlock(stateRoot[:]) - wsb, err := consensusblocks.NewSignedBeaconBlock(genesis) - require.NoError(t, err) - require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wsb), "Could not save genesis block") - - parentRoot, err := genesis.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st, parentRoot), "Could not save genesis state") - require.NoError(t, service.cfg.BeaconDB.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - for i := 1; i < 6; i++ { - driftGenesisTime(service, primitives.Slot(i), 0) - st, err := service.HeadState(ctx) - require.NoError(t, err) - b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i)) - require.NoError(t, err) - wsb, err := consensusblocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - root, err := b.Block.HashTreeRoot() - require.NoError(t, err) - - preState, err := service.getBlockPreState(ctx, wsb.Block()) - require.NoError(t, err) - postState, err := service.validateStateTransition(ctx, preState, wsb) - require.NoError(t, err) - require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) - require.NoError(t, err) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) - } - - for i := 6; i < 12; i++ { - driftGenesisTime(service, primitives.Slot(i), 0) - st, err := service.HeadState(ctx) - require.NoError(t, err) - b, err := util.GenerateFullBlockAltair(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i)) - require.NoError(t, err) - wsb, err := consensusblocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - root, err := b.Block.HashTreeRoot() - require.NoError(t, err) - preState, err := service.getBlockPreState(ctx, wsb.Block()) - require.NoError(t, err) - postState, err := service.validateStateTransition(ctx, preState, wsb) - require.NoError(t, err) - require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) - require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) - } - - for i := 12; i < 18; i++ { - driftGenesisTime(service, primitives.Slot(i), 0) - st, err := service.HeadState(ctx) - require.NoError(t, err) - b, err := util.GenerateFullBlockBellatrix(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i)) - require.NoError(t, err) - wsb, err := consensusblocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - root, err := b.Block.HashTreeRoot() - require.NoError(t, err) - preState, err := service.getBlockPreState(ctx, wsb.Block()) - require.NoError(t, err) - postState, err := service.validateStateTransition(ctx, preState, wsb) - require.NoError(t, err) - require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) - require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) - } - // Check that we haven't justified the second epoch yet - jc := service.cfg.ForkChoiceStore.JustifiedCheckpoint() - require.Equal(t, primitives.Epoch(0), jc.Epoch) - - // import a block that justifies the second epoch - driftGenesisTime(service, 18, 0) - validHeadState, err := service.HeadState(ctx) - require.NoError(t, err) - b, err := util.GenerateFullBlockBellatrix(validHeadState, keys, util.DefaultBlockGenConfig(), 18) - require.NoError(t, err) - wsb, err = consensusblocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - firstInvalidRoot, err := b.Block.HashTreeRoot() - require.NoError(t, err) - preState, err := service.getBlockPreState(ctx, wsb.Block()) - require.NoError(t, err) - postState, err := service.validateStateTransition(ctx, preState, wsb) - require.NoError(t, err) - require.NoError(t, service.savePostStateInfo(ctx, firstInvalidRoot, wsb, postState)) - roblock, err := consensusblocks.NewROBlockWithRoot(wsb, firstInvalidRoot) - require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) - jc = service.cfg.ForkChoiceStore.JustifiedCheckpoint() - require.Equal(t, primitives.Epoch(2), jc.Epoch) - - sjc := validHeadState.CurrentJustifiedCheckpoint() - require.Equal(t, primitives.Epoch(0), sjc.Epoch) - lvh := b.Block.Body.ExecutionPayload.ParentHash - // check our head - require.Equal(t, firstInvalidRoot, service.cfg.ForkChoiceStore.CachedHeadRoot()) - - // import another block to find out that it was invalid - mockEngine = &mockExecution.EngineClient{ErrNewPayload: execution.ErrAcceptedSyncingPayloadStatus, ErrForkchoiceUpdated: execution.ErrInvalidPayloadStatus, ForkChoiceUpdatedResp: lvh} - service.cfg.ExecutionEngineCaller = mockEngine - driftGenesisTime(service, 19, 0) - st, err = service.HeadState(ctx) - require.NoError(t, err) - b, err = util.GenerateFullBlockBellatrix(st, keys, util.DefaultBlockGenConfig(), 19) - require.NoError(t, err) - wsb, err = consensusblocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - root, err := b.Block.HashTreeRoot() - require.NoError(t, err) - preState, err = service.getBlockPreState(ctx, wsb.Block()) - require.NoError(t, err) - postState, err = service.validateStateTransition(ctx, preState, wsb) - require.NoError(t, err) - require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) - require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.ErrorContains(t, "received an INVALID payload from execution engine", err) - // Check that forkchoice's head is the last invalid block imported. The - // store's headroot is the previous head (since the invalid block did - // not finish importing) one and that the node is optimistic - require.Equal(t, root, service.cfg.ForkChoiceStore.CachedHeadRoot()) - headRoot, err := service.HeadRoot(ctx) - require.NoError(t, err) - require.Equal(t, firstInvalidRoot, bytesutil.ToBytes32(headRoot)) - optimistic, err := service.IsOptimistic(ctx) - require.NoError(t, err) - require.Equal(t, true, optimistic) - - // import another block based on the last valid head state - mockEngine = &mockExecution.EngineClient{} - service.cfg.ExecutionEngineCaller = mockEngine - driftGenesisTime(service, 20, 0) - b, err = util.GenerateFullBlockBellatrix(validHeadState, keys, &util.BlockGenConfig{}, 20) - require.NoError(t, err) - wsb, err = consensusblocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - root, err = b.Block.HashTreeRoot() - require.NoError(t, err) - - preState, err = service.getBlockPreState(ctx, wsb.Block()) - require.NoError(t, err) - postState, err = service.validateStateTransition(ctx, preState, wsb) - require.NoError(t, err) - require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) - require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) - require.NoError(t, err) - // Check the newly imported block is head, it justified the right - // checkpoint and the node is no longer optimistic - require.Equal(t, root, service.cfg.ForkChoiceStore.CachedHeadRoot()) - sjc = service.CurrentJustifiedCheckpt() - require.Equal(t, jc.Epoch, sjc.Epoch) - require.Equal(t, jc.Root, bytesutil.ToBytes32(sjc.Root)) - optimistic, err = service.IsOptimistic(ctx) - require.NoError(t, err) - require.Equal(t, false, optimistic) -} - // See the description in #10777 and #10782 for the full setup // We sync optimistically a chain of blocks. Block 17 is the last block in Epoch // 2. Block 18 justifies block 12 (the first in Epoch 2) and Block 19 returns @@ -1642,7 +1449,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } for i := 6; i < 12; i++ { @@ -1662,8 +1471,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } for i := 12; i < 18; i++ { @@ -1684,8 +1494,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } // Check that we haven't justified the second epoch yet jc := service.cfg.ForkChoiceStore.JustifiedCheckpoint() @@ -1708,7 +1519,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, firstInvalidRoot, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, firstInvalidRoot) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, err) jc = service.cfg.ForkChoiceStore.JustifiedCheckpoint() require.Equal(t, primitives.Epoch(2), jc.Epoch) @@ -1718,6 +1531,10 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { lvh := b.Block.Body.ExecutionPayload.ParentHash // check our head require.Equal(t, firstInvalidRoot, service.cfg.ForkChoiceStore.CachedHeadRoot()) + isBlock18OptimisticAfterImport, err := service.IsOptimisticForRoot(ctx, firstInvalidRoot) + require.NoError(t, err) + require.Equal(t, true, isBlock18OptimisticAfterImport) + time.Sleep(20 * time.Millisecond) // wait for async forkchoice update to be processed // import another block to find out that it was invalid mockEngine = &mockExecution.EngineClient{ErrNewPayload: execution.ErrInvalidPayloadStatus, NewPayloadResp: lvh} @@ -1768,7 +1585,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, err) // Check the newly imported block is head, it justified the right // checkpoint and the node is no longer optimistic @@ -1835,7 +1654,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } for i := 6; i < 12; i++ { @@ -1856,8 +1677,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } // import the merge block @@ -1877,7 +1699,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, lastValidRoot, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, lastValidRoot) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, err) // save the post state and the payload Hash of this block since it will // be the LVH @@ -1906,8 +1730,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, invalidRoots[i-13], wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, invalidRoots[i-13]) require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } // Check that we have justified the second epoch jc := service.cfg.ForkChoiceStore.JustifiedCheckpoint() @@ -1975,7 +1800,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) + service.cfg.ForkChoiceStore.Unlock() // Check that the head is still INVALID and the node is still optimistic require.Equal(t, invalidHeadRoot, service.cfg.ForkChoiceStore.CachedHeadRoot()) optimistic, err = service.IsOptimistic(ctx) @@ -2000,7 +1827,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, err) st, err = service.cfg.StateGen.StateByRoot(ctx, root) require.NoError(t, err) @@ -2028,7 +1857,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, err) require.Equal(t, root, service.cfg.ForkChoiceStore.CachedHeadRoot()) sjc = service.CurrentJustifiedCheckpt() @@ -2072,7 +1903,6 @@ func TestNoViableHead_Reboot(t *testing.T) { require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, genesisRoot), "Could not save genesis state") for i := 1; i < 6; i++ { - t.Log(i) driftGenesisTime(service, primitives.Slot(i), 0) st, err := service.HeadState(ctx) require.NoError(t, err) @@ -2089,7 +1919,9 @@ func TestNoViableHead_Reboot(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } for i := 6; i < 12; i++ { @@ -2109,8 +1941,9 @@ func TestNoViableHead_Reboot(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) - require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() } // import the merge block @@ -2130,7 +1963,9 @@ func TestNoViableHead_Reboot(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, lastValidRoot, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, lastValidRoot) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, err) // save the post state and the payload Hash of this block since it will // be the LVH @@ -2161,7 +1996,9 @@ func TestNoViableHead_Reboot(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() require.NoError(t, service.updateJustificationOnBlock(ctx, preState, postState, currStoreJustifiedEpoch)) _, err = service.updateFinalizationOnBlock(ctx, preState, postState, currStoreFinalizedEpoch) require.NoError(t, err) @@ -2282,7 +2119,9 @@ func TestOnBlock_HandleBlockAttestations(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() st, err = service.HeadState(ctx) require.NoError(t, err) @@ -2348,7 +2187,9 @@ func TestOnBlock_HandleBlockAttestations(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() st, err = service.HeadState(ctx) require.NoError(t, err) @@ -2631,7 +2472,10 @@ func TestRollbackBlock(t *testing.T) { require.NoError(t, err) // Rollback block insertion into db and caches. - require.ErrorContains(t, fmt.Sprintf("could not insert block %d to fork choice store", roblock.Block().Slot()), service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Lock() + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) + service.cfg.ForkChoiceStore.Unlock() + require.ErrorContains(t, fmt.Sprintf("could not insert block %d to fork choice store", roblock.Block().Slot()), err) // The block should no longer exist. require.Equal(t, false, service.cfg.BeaconDB.HasBlock(ctx, root)) @@ -2732,7 +2576,9 @@ func TestRollbackBlock_ContextDeadline(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() b, err = util.GenerateFullBlock(postState, keys, util.DefaultBlockGenConfig(), 34) require.NoError(t, err) @@ -2766,7 +2612,10 @@ func TestRollbackBlock_ContextDeadline(t *testing.T) { require.NoError(t, postState.SetFinalizedCheckpoint(cj)) // Rollback block insertion into db and caches. - require.ErrorContains(t, "context canceled", service.postBlockProcess(&postBlockProcessConfig{cancCtx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Lock() + err = service.postBlockProcess(&postBlockProcessConfig{cancCtx, roblock, [32]byte{}, postState, false}) + service.cfg.ForkChoiceStore.Unlock() + require.ErrorContains(t, "context canceled", err) // The block should no longer exist. require.Equal(t, false, service.cfg.BeaconDB.HasBlock(ctx, root)) @@ -3262,7 +3111,9 @@ func Test_postBlockProcess_EventSending(t *testing.T) { } // Execute postBlockProcess + service.cfg.ForkChoiceStore.Lock() err = service.postBlockProcess(cfg) + service.cfg.ForkChoiceStore.Unlock() // Check error expectation if tt.expectError { diff --git a/beacon-chain/blockchain/receive_attestation.go b/beacon-chain/blockchain/receive_attestation.go index e0d2f9abef..aba81ba87a 100644 --- a/beacon-chain/blockchain/receive_attestation.go +++ b/beacon-chain/blockchain/receive_attestation.go @@ -156,13 +156,15 @@ func (s *Service) UpdateHead(ctx context.Context, proposingSlot primitives.Slot) } if s.inRegularSync() { fcuArgs.attributes = s.getPayloadAttribute(ctx, headState, proposingSlot, newHeadRoot[:]) + if fcuArgs.attributes != nil && s.shouldOverrideFCU(newHeadRoot, proposingSlot) { + return + } + go s.forkchoiceUpdateWithExecution(s.ctx, fcuArgs) } - if fcuArgs.attributes != nil && s.shouldOverrideFCU(newHeadRoot, proposingSlot) { - return - } - if err := s.forkchoiceUpdateWithExecution(s.ctx, fcuArgs); err != nil { - log.WithError(err).Error("Could not update forkchoice") + if err := s.saveHead(s.ctx, fcuArgs.headRoot, fcuArgs.headBlock, fcuArgs.headState); err != nil { + log.WithError(err).Error("Could not save head") } + s.pruneAttsFromPool(s.ctx, fcuArgs.headState, fcuArgs.headBlock) } // This processes fork choice attestations from the pool to account for validator votes and fork choice. diff --git a/beacon-chain/blockchain/receive_attestation_test.go b/beacon-chain/blockchain/receive_attestation_test.go index 98a5afd8af..c4afb45ed2 100644 --- a/beacon-chain/blockchain/receive_attestation_test.go +++ b/beacon-chain/blockchain/receive_attestation_test.go @@ -117,7 +117,9 @@ func TestService_ProcessAttestationsAndUpdateHead(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, tRoot, wsb, postState)) roblock, err := blocks.NewROBlockWithRoot(wsb, tRoot) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() copied, err = service.cfg.StateGen.StateByRoot(ctx, tRoot) require.NoError(t, err) require.Equal(t, 2, fcs.NodeCount()) @@ -177,7 +179,9 @@ func TestService_UpdateHead_NoAtts(t *testing.T) { require.NoError(t, service.savePostStateInfo(ctx, tRoot, wsb, postState)) roblock, err := blocks.NewROBlockWithRoot(wsb, tRoot) require.NoError(t, err) + service.cfg.ForkChoiceStore.Lock() require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + service.cfg.ForkChoiceStore.Unlock() require.Equal(t, 2, fcs.NodeCount()) require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wsb)) require.Equal(t, tRoot, service.head.root) diff --git a/beacon-chain/blockchain/testing/BUILD.bazel b/beacon-chain/blockchain/testing/BUILD.bazel index e47969f03f..c40bd118b6 100644 --- a/beacon-chain/blockchain/testing/BUILD.bazel +++ b/beacon-chain/blockchain/testing/BUILD.bazel @@ -3,7 +3,10 @@ load("@prysm//tools/go:def.bzl", "go_library") go_library( name = "go_default_library", testonly = True, - srcs = ["mock.go"], + srcs = [ + "log.go", + "mock.go", + ], importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/blockchain/testing", visibility = [ "//beacon-chain:__subpackages__", diff --git a/beacon-chain/blockchain/testing/log.go b/beacon-chain/blockchain/testing/log.go new file mode 100644 index 0000000000..aed45a8dec --- /dev/null +++ b/beacon-chain/blockchain/testing/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package testing + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/blockchain/testing") diff --git a/beacon-chain/blockchain/testing/mock.go b/beacon-chain/blockchain/testing/mock.go index 896d043ef7..b8ee4165ca 100644 --- a/beacon-chain/blockchain/testing/mock.go +++ b/beacon-chain/blockchain/testing/mock.go @@ -30,7 +30,6 @@ import ( enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1" ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) var ErrNilState = errors.New("nil state") @@ -267,7 +266,7 @@ func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block interf if err := s.DB.SaveBlock(ctx, block); err != nil { return err } - logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block().Slot()) + log.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block().Slot()) } s.Root = signingRoot[:] s.Block = block @@ -296,7 +295,7 @@ func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []blocks.ROBl if err := s.DB.SaveBlock(ctx, b); err != nil { return err } - logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, b.Block().Slot()) + log.Infof("Saved block with root: %#x at slot %d", signingRoot, b.Block().Slot()) } s.Root = signingRoot[:] s.Block = b @@ -328,7 +327,7 @@ func (s *ChainService) ReceiveBlock(ctx context.Context, block interfaces.ReadOn if err := s.DB.SaveBlock(ctx, block); err != nil { return err } - logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block().Slot()) + log.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block().Slot()) } s.Root = signingRoot[:] s.Block = block @@ -585,11 +584,11 @@ func (s *ChainService) UpdateHead(ctx context.Context, slot primitives.Slot) { ojc := ðpb.Checkpoint{} st, root, err := prepareForkchoiceState(ctx, slot, bytesutil.ToBytes32(s.Root), [32]byte{}, [32]byte{}, ojc, ojc) if err != nil { - logrus.WithError(err).Error("Could not update head") + log.WithError(err).Error("Could not update head") } err = s.ForkChoiceStore.InsertNode(ctx, st, root) if err != nil { - logrus.WithError(err).Error("Could not insert node to forkchoice") + log.WithError(err).Error("Could not insert node to forkchoice") } } diff --git a/beacon-chain/builder/log.go b/beacon-chain/builder/log.go index 5c4cab050f..7cf167fd99 100644 --- a/beacon-chain/builder/log.go +++ b/beacon-chain/builder/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package builder import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "builder") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/builder") diff --git a/beacon-chain/cache/BUILD.bazel b/beacon-chain/cache/BUILD.bazel index a6eb511615..05be25d211 100644 --- a/beacon-chain/cache/BUILD.bazel +++ b/beacon-chain/cache/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "doc.go", "error.go", "interfaces.go", + "log.go", "payload_id.go", "proposer_indices.go", "proposer_indices_disabled.go", # keep diff --git a/beacon-chain/cache/attestation.go b/beacon-chain/cache/attestation.go index 17f2ef3c61..eb19d56d54 100644 --- a/beacon-chain/cache/attestation.go +++ b/beacon-chain/cache/attestation.go @@ -9,7 +9,6 @@ import ( ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1/attestation" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) type attGroup struct { diff --git a/beacon-chain/cache/committee.go b/beacon-chain/cache/committee.go index 3f0430833c..396ebb1e61 100644 --- a/beacon-chain/cache/committee.go +++ b/beacon-chain/cache/committee.go @@ -17,7 +17,6 @@ import ( lru "github.com/hashicorp/golang-lru" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - log "github.com/sirupsen/logrus" ) const ( diff --git a/beacon-chain/cache/depositsnapshot/BUILD.bazel b/beacon-chain/cache/depositsnapshot/BUILD.bazel index 964a7c5b82..81b50b4085 100644 --- a/beacon-chain/cache/depositsnapshot/BUILD.bazel +++ b/beacon-chain/cache/depositsnapshot/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "deposit_pruner.go", "deposit_tree.go", "deposit_tree_snapshot.go", + "log.go", "merkle_tree.go", ], importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/cache/depositsnapshot", diff --git a/beacon-chain/cache/depositsnapshot/deposit_inserter.go b/beacon-chain/cache/depositsnapshot/deposit_inserter.go index 17703edf56..7f36e03cf2 100644 --- a/beacon-chain/cache/depositsnapshot/deposit_inserter.go +++ b/beacon-chain/cache/depositsnapshot/deposit_inserter.go @@ -20,7 +20,6 @@ var ( Name: "beacondb_all_deposits_eip4881", Help: "The number of total deposits in memory", }) - log = logrus.WithField("prefix", "cache") ) // InsertDeposit into the database. If deposit or block number are nil diff --git a/beacon-chain/cache/depositsnapshot/log.go b/beacon-chain/cache/depositsnapshot/log.go new file mode 100644 index 0000000000..11d1b8bf88 --- /dev/null +++ b/beacon-chain/cache/depositsnapshot/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package depositsnapshot + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/cache/depositsnapshot") diff --git a/beacon-chain/cache/log.go b/beacon-chain/cache/log.go new file mode 100644 index 0000000000..c8e6f06ae5 --- /dev/null +++ b/beacon-chain/cache/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package cache + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/cache") diff --git a/beacon-chain/cache/sync_committee.go b/beacon-chain/cache/sync_committee.go index 4ba9f5730e..aff9a80f85 100644 --- a/beacon-chain/cache/sync_committee.go +++ b/beacon-chain/cache/sync_committee.go @@ -11,7 +11,6 @@ import ( "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - log "github.com/sirupsen/logrus" "k8s.io/client-go/tools/cache" ) diff --git a/beacon-chain/cache/tracked_validators.go b/beacon-chain/cache/tracked_validators.go index 06a63a98ec..33c84a8fa4 100644 --- a/beacon-chain/cache/tracked_validators.go +++ b/beacon-chain/cache/tracked_validators.go @@ -9,7 +9,6 @@ import ( "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/sirupsen/logrus" ) const ( @@ -67,7 +66,7 @@ func (t *TrackedValidatorsCache) Validator(index primitives.ValidatorIndex) (Tra val, ok := item.(TrackedValidator) if !ok { - logrus.Errorf("Failed to cast tracked validator from cache, got unexpected item type %T", item) + log.Errorf("Failed to cast tracked validator from cache, got unexpected item type %T", item) return TrackedValidator{}, false } @@ -113,7 +112,7 @@ func (t *TrackedValidatorsCache) Indices() map[primitives.ValidatorIndex]bool { for cacheKey := range items { index, err := fromCacheKey(cacheKey) if err != nil { - logrus.WithError(err).Error("Failed to get validator index from cache key") + log.WithError(err).Error("Failed to get validator index from cache key") continue } diff --git a/beacon-chain/core/altair/BUILD.bazel b/beacon-chain/core/altair/BUILD.bazel index 5b87a7efa0..86cfe9f05f 100644 --- a/beacon-chain/core/altair/BUILD.bazel +++ b/beacon-chain/core/altair/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "deposit.go", "epoch_precompute.go", "epoch_spec.go", + "log.go", "reward.go", "sync_committee.go", "transition.go", diff --git a/beacon-chain/core/altair/epoch_spec.go b/beacon-chain/core/altair/epoch_spec.go index 352e36f41f..03cd06b43a 100644 --- a/beacon-chain/core/altair/epoch_spec.go +++ b/beacon-chain/core/altair/epoch_spec.go @@ -7,7 +7,6 @@ import ( "github.com/OffchainLabs/prysm/v7/beacon-chain/core/time" "github.com/OffchainLabs/prysm/v7/beacon-chain/state" "github.com/OffchainLabs/prysm/v7/config/params" - log "github.com/sirupsen/logrus" ) // ProcessSyncCommitteeUpdates processes sync client committee updates for the beacon state. diff --git a/beacon-chain/core/altair/log.go b/beacon-chain/core/altair/log.go new file mode 100644 index 0000000000..4e15309977 --- /dev/null +++ b/beacon-chain/core/altair/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package altair + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/core/altair") diff --git a/beacon-chain/core/blocks/header_test.go b/beacon-chain/core/blocks/header_test.go index cf4480bcf6..2e345d1dac 100644 --- a/beacon-chain/core/blocks/header_test.go +++ b/beacon-chain/core/blocks/header_test.go @@ -290,52 +290,3 @@ func TestProcessBlockHeader_OK(t *testing.T) { } assert.Equal(t, true, proto.Equal(nsh, expected), "Expected %v, received %v", expected, nsh) } - -func TestBlockSignatureSet_OK(t *testing.T) { - validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) - for i := range validators { - validators[i] = ðpb.Validator{ - PublicKey: make([]byte, 32), - WithdrawalCredentials: make([]byte, 32), - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - Slashed: true, - } - } - - state, err := util.NewBeaconState() - require.NoError(t, err) - require.NoError(t, state.SetValidators(validators)) - require.NoError(t, state.SetSlot(10)) - require.NoError(t, state.SetLatestBlockHeader(util.HydrateBeaconHeader(ðpb.BeaconBlockHeader{ - Slot: 9, - ProposerIndex: 0, - }))) - - latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot() - require.NoError(t, err) - - currentEpoch := time.CurrentEpoch(state) - priv, err := bls.RandKey() - require.NoError(t, err) - pID, err := helpers.BeaconProposerIndex(t.Context(), state) - require.NoError(t, err) - block := util.NewBeaconBlock() - block.Block.Slot = 10 - block.Block.ProposerIndex = pID - block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96) - block.Block.ParentRoot = latestBlockSignedRoot[:] - block.Signature, err = signing.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv) - require.NoError(t, err) - proposerIdx, err := helpers.BeaconProposerIndex(t.Context(), state) - require.NoError(t, err) - validators[proposerIdx].Slashed = false - validators[proposerIdx].PublicKey = priv.PublicKey().Marshal() - err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx]) - require.NoError(t, err) - set, err := blocks.BlockSignatureBatch(state, block.Block.ProposerIndex, block.Signature, block.Block.HashTreeRoot) - require.NoError(t, err) - - verified, err := set.Verify() - require.NoError(t, err) - assert.Equal(t, true, verified, "Block signature set returned a set which was unable to be verified") -} diff --git a/beacon-chain/core/blocks/log.go b/beacon-chain/core/blocks/log.go index 07260da51c..230801f058 100644 --- a/beacon-chain/core/blocks/log.go +++ b/beacon-chain/core/blocks/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package blocks import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "blocks") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/core/blocks") diff --git a/beacon-chain/core/blocks/signature.go b/beacon-chain/core/blocks/signature.go index b6d6c83349..856bd63ff6 100644 --- a/beacon-chain/core/blocks/signature.go +++ b/beacon-chain/core/blocks/signature.go @@ -122,24 +122,6 @@ func VerifyBlockSignatureUsingCurrentFork(beaconState state.ReadOnlyBeaconState, return nil } -// BlockSignatureBatch retrieves the block signature batch from the provided block and its corresponding state. -func BlockSignatureBatch(beaconState state.ReadOnlyBeaconState, - proposerIndex primitives.ValidatorIndex, - sig []byte, - rootFunc func() ([32]byte, error)) (*bls.SignatureBatch, error) { - currentEpoch := slots.ToEpoch(beaconState.Slot()) - domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorsRoot()) - if err != nil { - return nil, err - } - proposer, err := beaconState.ValidatorAtIndex(proposerIndex) - if err != nil { - return nil, err - } - proposerPubKey := proposer.PublicKey - return signing.BlockSignatureBatch(proposerPubKey, sig, domain, rootFunc) -} - // RandaoSignatureBatch retrieves the relevant randao specific signature batch object // from a block and its corresponding state. func RandaoSignatureBatch( diff --git a/beacon-chain/core/electra/BUILD.bazel b/beacon-chain/core/electra/BUILD.bazel index 0086f060eb..7829e8c68a 100644 --- a/beacon-chain/core/electra/BUILD.bazel +++ b/beacon-chain/core/electra/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "deposits.go", "effective_balance_updates.go", "error.go", + "log.go", "registry_updates.go", "transition.go", "transition_no_verify_sig.go", diff --git a/beacon-chain/core/electra/consolidations.go b/beacon-chain/core/electra/consolidations.go index 603f271e29..537eda730f 100644 --- a/beacon-chain/core/electra/consolidations.go +++ b/beacon-chain/core/electra/consolidations.go @@ -17,7 +17,6 @@ import ( "github.com/OffchainLabs/prysm/v7/time/slots" "github.com/ethereum/go-ethereum/common/math" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) // ProcessPendingConsolidations implements the spec definition below. This method makes mutating @@ -278,12 +277,12 @@ func ProcessConsolidationRequests(ctx context.Context, st state.BeaconState, req if uint64(curEpoch) < e { continue } - bal, err := st.PendingBalanceToWithdraw(srcIdx) + hasBal, err := st.HasPendingBalanceToWithdraw(srcIdx) if err != nil { log.WithError(err).Error("Failed to fetch pending balance to withdraw") continue } - if bal > 0 { + if hasBal { continue } diff --git a/beacon-chain/core/electra/deposits.go b/beacon-chain/core/electra/deposits.go index 6eb80555ee..f311f90021 100644 --- a/beacon-chain/core/electra/deposits.go +++ b/beacon-chain/core/electra/deposits.go @@ -18,7 +18,6 @@ import ( "github.com/OffchainLabs/prysm/v7/runtime/version" "github.com/OffchainLabs/prysm/v7/time/slots" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) // ProcessDeposits is one of the operations performed on each processed diff --git a/beacon-chain/core/electra/log.go b/beacon-chain/core/electra/log.go new file mode 100644 index 0000000000..e971482bc9 --- /dev/null +++ b/beacon-chain/core/electra/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package electra + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/core/electra") diff --git a/beacon-chain/core/electra/withdrawals.go b/beacon-chain/core/electra/withdrawals.go index 89aa4b16ba..4ceda644f2 100644 --- a/beacon-chain/core/electra/withdrawals.go +++ b/beacon-chain/core/electra/withdrawals.go @@ -17,7 +17,6 @@ import ( "github.com/OffchainLabs/prysm/v7/time/slots" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) // ProcessWithdrawalRequests processes the validator withdrawals from the provided execution payload diff --git a/beacon-chain/core/helpers/BUILD.bazel b/beacon-chain/core/helpers/BUILD.bazel index 86cd9684ac..bfaeed336e 100644 --- a/beacon-chain/core/helpers/BUILD.bazel +++ b/beacon-chain/core/helpers/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "block.go", "genesis.go", "legacy.go", + "log.go", "metrics.go", "randao.go", "ranges.go", diff --git a/beacon-chain/core/helpers/log.go b/beacon-chain/core/helpers/log.go new file mode 100644 index 0000000000..874113c3a9 --- /dev/null +++ b/beacon-chain/core/helpers/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package helpers + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/core/helpers") diff --git a/beacon-chain/core/helpers/sync_committee.go b/beacon-chain/core/helpers/sync_committee.go index 53bca04ac6..dd1340162c 100644 --- a/beacon-chain/core/helpers/sync_committee.go +++ b/beacon-chain/core/helpers/sync_committee.go @@ -14,7 +14,6 @@ import ( "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" "github.com/OffchainLabs/prysm/v7/time/slots" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) var ( diff --git a/beacon-chain/core/helpers/validators.go b/beacon-chain/core/helpers/validators.go index a817daba8e..6d673c67d7 100644 --- a/beacon-chain/core/helpers/validators.go +++ b/beacon-chain/core/helpers/validators.go @@ -21,7 +21,6 @@ import ( "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - log "github.com/sirupsen/logrus" ) var ( diff --git a/beacon-chain/core/peerdas/metrics.go b/beacon-chain/core/peerdas/metrics.go index caa92ebc56..3c20d51157 100644 --- a/beacon-chain/core/peerdas/metrics.go +++ b/beacon-chain/core/peerdas/metrics.go @@ -5,10 +5,20 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" ) -var dataColumnComputationTime = promauto.NewHistogram( - prometheus.HistogramOpts{ - Name: "beacon_data_column_sidecar_computation_milliseconds", - Help: "Captures the time taken to compute data column sidecars from blobs.", - Buckets: []float64{25, 50, 100, 250, 500, 750, 1000}, - }, +var ( + dataColumnComputationTime = promauto.NewHistogram( + prometheus.HistogramOpts{ + Name: "beacon_data_column_sidecar_computation_milliseconds", + Help: "Captures the time taken to compute data column sidecars from blobs.", + Buckets: []float64{25, 50, 100, 250, 500, 750, 1000}, + }, + ) + + cellsAndProofsFromStructuredComputationTime = promauto.NewHistogram( + prometheus.HistogramOpts{ + Name: "cells_and_proofs_from_structured_computation_milliseconds", + Help: "Captures the time taken to compute cells and proofs from structured computation.", + Buckets: []float64{10, 20, 30, 40, 50, 100, 200}, + }, + ) ) diff --git a/beacon-chain/core/peerdas/reconstruction.go b/beacon-chain/core/peerdas/reconstruction.go index 371418e7c9..bb50a0fa7a 100644 --- a/beacon-chain/core/peerdas/reconstruction.go +++ b/beacon-chain/core/peerdas/reconstruction.go @@ -3,6 +3,7 @@ package peerdas import ( "sort" "sync" + "time" "github.com/OffchainLabs/prysm/v7/beacon-chain/blockchain/kzg" fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams" @@ -296,32 +297,42 @@ func ComputeCellsAndProofsFromFlat(blobs [][]byte, cellProofs [][]byte) ([][]kzg return nil, nil, ErrBlobsCellsProofsMismatch } - cellsPerBlob := make([][]kzg.Cell, 0, blobCount) - proofsPerBlob := make([][]kzg.Proof, 0, blobCount) + var wg errgroup.Group + + cellsPerBlob := make([][]kzg.Cell, blobCount) + proofsPerBlob := make([][]kzg.Proof, blobCount) + for i, blob := range blobs { - var kzgBlob kzg.Blob - if copy(kzgBlob[:], blob) != len(kzgBlob) { - return nil, nil, errors.New("wrong blob size - should never happen") - } - - // Compute the extended cells from the (non-extended) blob. - cells, err := kzg.ComputeCells(&kzgBlob) - if err != nil { - return nil, nil, errors.Wrap(err, "compute cells") - } - - var proofs []kzg.Proof - for idx := uint64(i) * numberOfColumns; idx < (uint64(i)+1)*numberOfColumns; idx++ { - var kzgProof kzg.Proof - if copy(kzgProof[:], cellProofs[idx]) != len(kzgProof) { - return nil, nil, errors.New("wrong KZG proof size - should never happen") + wg.Go(func() error { + var kzgBlob kzg.Blob + if copy(kzgBlob[:], blob) != len(kzgBlob) { + return errors.New("wrong blob size - should never happen") } - proofs = append(proofs, kzgProof) - } + // Compute the extended cells from the (non-extended) blob. + cells, err := kzg.ComputeCells(&kzgBlob) + if err != nil { + return errors.Wrap(err, "compute cells") + } - cellsPerBlob = append(cellsPerBlob, cells) - proofsPerBlob = append(proofsPerBlob, proofs) + proofs := make([]kzg.Proof, 0, numberOfColumns) + for idx := uint64(i) * numberOfColumns; idx < (uint64(i)+1)*numberOfColumns; idx++ { + var kzgProof kzg.Proof + if copy(kzgProof[:], cellProofs[idx]) != len(kzgProof) { + return errors.New("wrong KZG proof size - should never happen") + } + + proofs = append(proofs, kzgProof) + } + + cellsPerBlob[i] = cells + proofsPerBlob[i] = proofs + return nil + }) + } + + if err := wg.Wait(); err != nil { + return nil, nil, err } return cellsPerBlob, proofsPerBlob, nil @@ -329,40 +340,55 @@ func ComputeCellsAndProofsFromFlat(blobs [][]byte, cellProofs [][]byte) ([][]kzg // ComputeCellsAndProofsFromStructured computes the cells and proofs from blobs and cell proofs. func ComputeCellsAndProofsFromStructured(blobsAndProofs []*pb.BlobAndProofV2) ([][]kzg.Cell, [][]kzg.Proof, error) { - cellsPerBlob := make([][]kzg.Cell, 0, len(blobsAndProofs)) - proofsPerBlob := make([][]kzg.Proof, 0, len(blobsAndProofs)) - for _, blobAndProof := range blobsAndProofs { + start := time.Now() + defer func() { + cellsAndProofsFromStructuredComputationTime.Observe(float64(time.Since(start).Milliseconds())) + }() + + var wg errgroup.Group + + cellsPerBlob := make([][]kzg.Cell, len(blobsAndProofs)) + proofsPerBlob := make([][]kzg.Proof, len(blobsAndProofs)) + + for i, blobAndProof := range blobsAndProofs { if blobAndProof == nil { return nil, nil, ErrNilBlobAndProof } - var kzgBlob kzg.Blob - if copy(kzgBlob[:], blobAndProof.Blob) != len(kzgBlob) { - return nil, nil, errors.New("wrong blob size - should never happen") - } - - // Compute the extended cells from the (non-extended) blob. - cells, err := kzg.ComputeCells(&kzgBlob) - if err != nil { - return nil, nil, errors.Wrap(err, "compute cells") - } - - kzgProofs := make([]kzg.Proof, 0, fieldparams.NumberOfColumns) - for _, kzgProofBytes := range blobAndProof.KzgProofs { - if len(kzgProofBytes) != kzg.BytesPerProof { - return nil, nil, errors.New("wrong KZG proof size - should never happen") + wg.Go(func() error { + var kzgBlob kzg.Blob + if copy(kzgBlob[:], blobAndProof.Blob) != len(kzgBlob) { + return errors.New("wrong blob size - should never happen") } - var kzgProof kzg.Proof - if copy(kzgProof[:], kzgProofBytes) != len(kzgProof) { - return nil, nil, errors.New("wrong copied KZG proof size - should never happen") + // Compute the extended cells from the (non-extended) blob. + cells, err := kzg.ComputeCells(&kzgBlob) + if err != nil { + return errors.Wrap(err, "compute cells") } - kzgProofs = append(kzgProofs, kzgProof) - } + kzgProofs := make([]kzg.Proof, 0, fieldparams.NumberOfColumns) + for _, kzgProofBytes := range blobAndProof.KzgProofs { + if len(kzgProofBytes) != kzg.BytesPerProof { + return errors.New("wrong KZG proof size - should never happen") + } - cellsPerBlob = append(cellsPerBlob, cells) - proofsPerBlob = append(proofsPerBlob, kzgProofs) + var kzgProof kzg.Proof + if copy(kzgProof[:], kzgProofBytes) != len(kzgProof) { + return errors.New("wrong copied KZG proof size - should never happen") + } + + kzgProofs = append(kzgProofs, kzgProof) + } + + cellsPerBlob[i] = cells + proofsPerBlob[i] = kzgProofs + return nil + }) + } + + if err := wg.Wait(); err != nil { + return nil, nil, err } return cellsPerBlob, proofsPerBlob, nil diff --git a/beacon-chain/core/transition/interop/log.go b/beacon-chain/core/transition/interop/log.go index 21f8e40cdb..dc1c2f3c58 100644 --- a/beacon-chain/core/transition/interop/log.go +++ b/beacon-chain/core/transition/interop/log.go @@ -1,10 +1,9 @@ -// Package interop contains useful utilities for persisting -// ssz-encoded states and blocks to disk during each state -// transition for development purposes. +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package interop -import ( - "github.com/sirupsen/logrus" -) +import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "interop") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/core/transition/interop") diff --git a/beacon-chain/core/transition/log.go b/beacon-chain/core/transition/log.go index 090b6224a5..91598fc30f 100644 --- a/beacon-chain/core/transition/log.go +++ b/beacon-chain/core/transition/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package transition import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "state") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/core/transition") diff --git a/beacon-chain/core/transition/transition_no_verify_sig.go b/beacon-chain/core/transition/transition_no_verify_sig.go index 2873301ae4..a116b1abc1 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig.go +++ b/beacon-chain/core/transition/transition_no_verify_sig.go @@ -182,12 +182,6 @@ func ProcessBlockNoVerifyAnySig( return nil, nil, err } - sig := signed.Signature() - bSet, err := b.BlockSignatureBatch(st, blk.ProposerIndex(), sig[:], blk.HashTreeRoot) - if err != nil { - tracing.AnnotateError(span, err) - return nil, nil, errors.Wrap(err, "could not retrieve block signature set") - } randaoReveal := signed.Block().Body().RandaoReveal() rSet, err := b.RandaoSignatureBatch(ctx, st, randaoReveal[:]) if err != nil { @@ -201,7 +195,7 @@ func ProcessBlockNoVerifyAnySig( // Merge beacon block, randao and attestations signatures into a set. set := bls.NewSet() - set.Join(bSet).Join(rSet).Join(aSet) + set.Join(rSet).Join(aSet) if blk.Version() >= version.Capella { changes, err := signed.Block().Body().BLSToExecutionChanges() diff --git a/beacon-chain/core/transition/transition_no_verify_sig_test.go b/beacon-chain/core/transition/transition_no_verify_sig_test.go index 772feb4186..e5f3610c06 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig_test.go +++ b/beacon-chain/core/transition/transition_no_verify_sig_test.go @@ -157,9 +157,8 @@ func TestProcessBlockNoVerify_SigSetContainsDescriptions(t *testing.T) { set, _, err := transition.ProcessBlockNoVerifyAnySig(t.Context(), beaconState, wsb) require.NoError(t, err) assert.Equal(t, len(set.Signatures), len(set.Descriptions), "Signatures and descriptions do not match up") - assert.Equal(t, "block signature", set.Descriptions[0]) - assert.Equal(t, "randao signature", set.Descriptions[1]) - assert.Equal(t, "attestation signature", set.Descriptions[2]) + assert.Equal(t, "randao signature", set.Descriptions[0]) + assert.Equal(t, "attestation signature", set.Descriptions[1]) } func TestProcessOperationsNoVerifyAttsSigs_OK(t *testing.T) { diff --git a/beacon-chain/das/log.go b/beacon-chain/das/log.go index b641b95a5b..328cab2ae5 100644 --- a/beacon-chain/das/log.go +++ b/beacon-chain/das/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package das import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "das") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/das") diff --git a/beacon-chain/das/needs.go b/beacon-chain/das/needs.go index bd7b53c077..425165ace3 100644 --- a/beacon-chain/das/needs.go +++ b/beacon-chain/das/needs.go @@ -67,9 +67,9 @@ func NewSyncNeeds(current CurrentSlotter, oldestSlotFlagPtr *primitives.Slot, bl // Override spec minimum block retention with user-provided flag only if it is lower than the spec minimum. sn.blockRetention = primitives.Epoch(params.BeaconConfig().MinEpochsForBlockRequests) + if oldestSlotFlagPtr != nil { - oldestEpoch := slots.ToEpoch(*oldestSlotFlagPtr) - if oldestEpoch < sn.blockRetention { + if *oldestSlotFlagPtr <= syncEpochOffset(current(), sn.blockRetention) { sn.validOldestSlotPtr = oldestSlotFlagPtr } else { log.WithField("backfill-oldest-slot", *oldestSlotFlagPtr). diff --git a/beacon-chain/das/needs_test.go b/beacon-chain/das/needs_test.go index 6986f7933a..6b9e863633 100644 --- a/beacon-chain/das/needs_test.go +++ b/beacon-chain/das/needs_test.go @@ -128,6 +128,9 @@ func TestSyncNeedsInitialize(t *testing.T) { slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch minBlobEpochs := params.BeaconConfig().MinEpochsForBlobsSidecarsRequest minColEpochs := params.BeaconConfig().MinEpochsForDataColumnSidecarsRequest + denebSlot := slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch) + fuluSlot := slots.UnsafeEpochStart(params.BeaconConfig().FuluForkEpoch) + minSlots := slots.UnsafeEpochStart(primitives.Epoch(params.BeaconConfig().MinEpochsForBlockRequests)) currentSlot := primitives.Slot(10000) currentFunc := func() primitives.Slot { return currentSlot } @@ -141,6 +144,7 @@ func TestSyncNeedsInitialize(t *testing.T) { expectedCol primitives.Epoch name string input SyncNeeds + current func() primitives.Slot }{ { name: "basic initialization with no flags", @@ -174,13 +178,13 @@ func TestSyncNeedsInitialize(t *testing.T) { { name: "valid oldestSlotFlagPtr (earlier than spec minimum)", blobRetentionFlag: 0, - oldestSlotFlagPtr: func() *primitives.Slot { - slot := primitives.Slot(10) - return &slot - }(), + oldestSlotFlagPtr: &denebSlot, expectValidOldest: true, expectedBlob: minBlobEpochs, expectedCol: minColEpochs, + current: func() primitives.Slot { + return fuluSlot + minSlots + }, }, { name: "invalid oldestSlotFlagPtr (later than spec minimum)", @@ -210,6 +214,9 @@ func TestSyncNeedsInitialize(t *testing.T) { { name: "both blob retention flag and oldest slot set", blobRetentionFlag: minBlobEpochs + 5, + current: func() primitives.Slot { + return fuluSlot + minSlots + }, oldestSlotFlagPtr: func() *primitives.Slot { slot := primitives.Slot(100) return &slot @@ -232,16 +239,27 @@ func TestSyncNeedsInitialize(t *testing.T) { expectedBlob: 5000, expectedCol: 5000, }, + { + name: "regression for deneb start", + blobRetentionFlag: 8212500, + expectValidOldest: true, + oldestSlotFlagPtr: &denebSlot, + current: func() primitives.Slot { + return fuluSlot + minSlots + }, + expectedBlob: 8212500, + expectedCol: 8212500, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - result, err := NewSyncNeeds(currentFunc, tc.oldestSlotFlagPtr, tc.blobRetentionFlag) + if tc.current == nil { + tc.current = currentFunc + } + result, err := NewSyncNeeds(tc.current, tc.oldestSlotFlagPtr, tc.blobRetentionFlag) require.NoError(t, err) - // Check that current, deneb, fulu are set correctly - require.Equal(t, currentSlot, result.current()) - // Check retention calculations require.Equal(t, tc.expectedBlob, result.blobRetention) require.Equal(t, tc.expectedCol, result.colRetention) diff --git a/beacon-chain/db/filesystem/BUILD.bazel b/beacon-chain/db/filesystem/BUILD.bazel index 5c9d2df0b4..98b7717b24 100644 --- a/beacon-chain/db/filesystem/BUILD.bazel +++ b/beacon-chain/db/filesystem/BUILD.bazel @@ -38,6 +38,7 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_spf13_afero//:go_default_library", + "@org_golang_x_sync//errgroup:go_default_library", ], ) diff --git a/beacon-chain/db/filesystem/data_column.go b/beacon-chain/db/filesystem/data_column.go index 221146c556..52a3c7858a 100644 --- a/beacon-chain/db/filesystem/data_column.go +++ b/beacon-chain/db/filesystem/data_column.go @@ -25,6 +25,7 @@ import ( "github.com/OffchainLabs/prysm/v7/time/slots" "github.com/pkg/errors" "github.com/spf13/afero" + "golang.org/x/sync/errgroup" ) const ( @@ -185,73 +186,162 @@ func (dcs *DataColumnStorage) WarmCache() { highestStoredEpoch := primitives.Epoch(0) - // Walk the data column filesystem to warm up the cache. - if err := afero.Walk(dcs.fs, ".", func(path string, info os.FileInfo, fileErr error) (err error) { - if fileErr != nil { - return fileErr - } - - // If not a leaf, skip. - if info.IsDir() { - return nil - } - - // Extract metadata from the file path. - fileMetadata, err := extractFileMetadata(path) - if err != nil { - log.WithError(err).Error("Error encountered while extracting file metadata") - return nil - } - - // Open the data column filesystem file. - f, err := dcs.fs.Open(path) - if err != nil { - log.WithError(err).Error("Error encountered while opening data column filesystem file") - return nil - } - - // Close the file. - defer func() { - // Overwrite the existing error only if it is nil, since the close error is less important. - closeErr := f.Close() - if closeErr != nil && err == nil { - err = closeErr - } - }() - - // Read the metadata of the file. - metadata, err := dcs.metadata(f) - if err != nil { - log.WithError(err).Error("Error encountered while reading metadata from data column filesystem file") - return nil - } - - // Check the indices. - indices := metadata.indices.all() - if len(indices) == 0 { - return nil - } - - // Build the ident. - dataColumnsIdent := DataColumnsIdent{Root: fileMetadata.blockRoot, Epoch: fileMetadata.epoch, Indices: indices} - - // Update the highest stored epoch. - highestStoredEpoch = max(highestStoredEpoch, fileMetadata.epoch) - - // Set the ident in the cache. - if err := dcs.cache.set(dataColumnsIdent); err != nil { - log.WithError(err).Error("Error encountered while ensuring data column filesystem cache") - } - - return nil - }); err != nil { - log.WithError(err).Error("Error encountered while walking data column filesystem.") + // List all period directories + periodFileInfos, err := afero.ReadDir(dcs.fs, ".") + if err != nil { + log.WithError(err).Error("Error reading top directory during warm cache") + return } - // Prune the cache and the filesystem. + // Iterate through periods + for _, periodFileInfo := range periodFileInfos { + if !periodFileInfo.IsDir() { + continue + } + + periodPath := periodFileInfo.Name() + + // List all epoch directories in this period + epochFileInfos, err := afero.ReadDir(dcs.fs, periodPath) + if err != nil { + log.WithError(err).WithField("period", periodPath).Error("Error reading period directory during warm cache") + continue + } + + // Iterate through epochs + for _, epochFileInfo := range epochFileInfos { + if !epochFileInfo.IsDir() { + continue + } + + epochPath := path.Join(periodPath, epochFileInfo.Name()) + + // List all .sszs files in this epoch + files, err := listEpochFiles(dcs.fs, epochPath) + if err != nil { + log.WithError(err).WithField("epoch", epochPath).Error("Error listing epoch files during warm cache") + continue + } + + if len(files) == 0 { + continue + } + + // Process all files in this epoch in parallel + epochHighest, err := dcs.processEpochFiles(files) + if err != nil { + log.WithError(err).WithField("epoch", epochPath).Error("Error processing epoch files during warm cache") + } + + highestStoredEpoch = max(highestStoredEpoch, epochHighest) + } + } + + // Prune the cache and the filesystem dcs.prune() - log.WithField("elapsed", time.Since(start)).Info("Data column filesystem cache warm-up complete") + totalElapsed := time.Since(start) + + // Log summary + log.WithField("elapsed", totalElapsed).Info("Data column filesystem cache warm-up complete") +} + +// listEpochFiles lists all .sszs files in an epoch directory. +func listEpochFiles(fs afero.Fs, epochPath string) ([]string, error) { + fileInfos, err := afero.ReadDir(fs, epochPath) + if err != nil { + return nil, errors.Wrap(err, "read epoch directory") + } + + files := make([]string, 0, len(fileInfos)) + for _, fileInfo := range fileInfos { + if fileInfo.IsDir() { + continue + } + + fileName := fileInfo.Name() + if strings.HasSuffix(fileName, "."+dataColumnsFileExtension) { + files = append(files, path.Join(epochPath, fileName)) + } + } + + return files, nil +} + +// processEpochFiles processes all .sszs files in an epoch directory in parallel. +func (dcs *DataColumnStorage) processEpochFiles(files []string) (primitives.Epoch, error) { + var ( + eg errgroup.Group + mu sync.Mutex + ) + + highestEpoch := primitives.Epoch(0) + for _, filePath := range files { + eg.Go(func() error { + epoch, err := dcs.processFile(filePath) + if err != nil { + log.WithError(err).WithField("file", filePath).Error("Error processing file during warm cache") + return nil + } + + mu.Lock() + defer mu.Unlock() + highestEpoch = max(highestEpoch, epoch) + + return nil + }) + } + + if err := eg.Wait(); err != nil { + return highestEpoch, err + } + + return highestEpoch, nil +} + +// processFile processes a single .sszs file. +func (dcs *DataColumnStorage) processFile(filePath string) (primitives.Epoch, error) { + // Extract metadata from the file path + fileMetadata, err := extractFileMetadata(filePath) + if err != nil { + return 0, errors.Wrap(err, "extract file metadata") + } + + // Open the file (each goroutine gets its own FD) + f, err := dcs.fs.Open(filePath) + if err != nil { + return 0, errors.Wrap(err, "open file") + } + defer func() { + if closeErr := f.Close(); closeErr != nil { + log.WithError(closeErr).WithField("file", filePath).Error("Error closing file during warm cache") + } + }() + + // Read metadata + metadata, err := dcs.metadata(f) + if err != nil { + return 0, errors.Wrap(err, "read metadata") + } + + // Extract indices + indices := metadata.indices.all() + if len(indices) == 0 { + return fileMetadata.epoch, nil // No indices, skip + } + + // Build ident and set in cache (thread-safe) + dataColumnsIdent := DataColumnsIdent{ + Root: fileMetadata.blockRoot, + Epoch: fileMetadata.epoch, + Indices: indices, + } + + if err := dcs.cache.set(dataColumnsIdent); err != nil { + return 0, errors.Wrap(err, "cache set") + } + + return fileMetadata.epoch, nil } // Summary returns the DataColumnStorageSummary. @@ -515,6 +605,11 @@ func (dcs *DataColumnStorage) Clear() error { // prune clean the cache, the filesystem and mutexes. func (dcs *DataColumnStorage) prune() { + startTime := time.Now() + defer func() { + dataColumnPruneLatency.Observe(float64(time.Since(startTime).Milliseconds())) + }() + highestStoredEpoch := dcs.cache.HighestEpoch() // Check if we need to prune. @@ -622,6 +717,9 @@ func (dcs *DataColumnStorage) saveDataColumnSidecarsExistingFile(filePath string // Create the SSZ encoded data column sidecars. var sszEncodedDataColumnSidecars []byte + // Initialize the count of the saved SSZ encoded data column sidecar. + storedCount := uint8(0) + for { dataColumnSidecars := pullChan(inputDataColumnSidecars) if len(dataColumnSidecars) == 0 { @@ -668,6 +766,9 @@ func (dcs *DataColumnStorage) saveDataColumnSidecarsExistingFile(filePath string return errors.Wrap(err, "set index") } + // Increment the count of the saved SSZ encoded data column sidecar. + storedCount++ + // Append the SSZ encoded data column sidecar to the SSZ encoded data column sidecars. sszEncodedDataColumnSidecars = append(sszEncodedDataColumnSidecars, sszEncodedDataColumnSidecar...) } @@ -692,9 +793,12 @@ func (dcs *DataColumnStorage) saveDataColumnSidecarsExistingFile(filePath string return errWrongBytesWritten } + syncStart := time.Now() if err := file.Sync(); err != nil { return errors.Wrap(err, "sync") } + dataColumnFileSyncLatency.Observe(float64(time.Since(syncStart).Milliseconds())) + dataColumnBatchStoreCount.Observe(float64(storedCount)) return nil } @@ -808,10 +912,14 @@ func (dcs *DataColumnStorage) saveDataColumnSidecarsNewFile(filePath string, inp return errWrongBytesWritten } + syncStart := time.Now() if err := file.Sync(); err != nil { return errors.Wrap(err, "sync") } + dataColumnFileSyncLatency.Observe(float64(time.Since(syncStart).Milliseconds())) + dataColumnBatchStoreCount.Observe(float64(storedCount)) + return nil } diff --git a/beacon-chain/db/filesystem/log.go b/beacon-chain/db/filesystem/log.go index 8a85d549c6..9cdeab09ff 100644 --- a/beacon-chain/db/filesystem/log.go +++ b/beacon-chain/db/filesystem/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package filesystem import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "filesystem") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/db/filesystem") diff --git a/beacon-chain/db/filesystem/metrics.go b/beacon-chain/db/filesystem/metrics.go index 495e13836f..03f039349d 100644 --- a/beacon-chain/db/filesystem/metrics.go +++ b/beacon-chain/db/filesystem/metrics.go @@ -36,16 +36,15 @@ var ( }) // Data columns - dataColumnBuckets = []float64{3, 5, 7, 9, 11, 13} dataColumnSaveLatency = promauto.NewHistogram(prometheus.HistogramOpts{ Name: "data_column_storage_save_latency", Help: "Latency of DataColumnSidecar storage save operations in milliseconds", - Buckets: dataColumnBuckets, + Buckets: []float64{10, 20, 30, 50, 100, 200, 500}, }) dataColumnFetchLatency = promauto.NewHistogram(prometheus.HistogramOpts{ Name: "data_column_storage_get_latency", Help: "Latency of DataColumnSidecar storage get operations in milliseconds", - Buckets: dataColumnBuckets, + Buckets: []float64{3, 5, 7, 9, 11, 13}, }) dataColumnPrunedCounter = promauto.NewCounter(prometheus.CounterOpts{ Name: "data_column_pruned", @@ -59,4 +58,16 @@ var ( Name: "data_column_disk_count", Help: "Approximate number of data columns in storage", }) + dataColumnFileSyncLatency = promauto.NewSummary(prometheus.SummaryOpts{ + Name: "data_column_file_sync_latency", + Help: "Latency of sync operations when saving data columns in milliseconds", + }) + dataColumnBatchStoreCount = promauto.NewSummary(prometheus.SummaryOpts{ + Name: "data_column_batch_store_count", + Help: "Number of data columns stored in a batch", + }) + dataColumnPruneLatency = promauto.NewSummary(prometheus.SummaryOpts{ + Name: "data_column_prune_latency", + Help: "Latency of data column prune operations in milliseconds", + }) ) diff --git a/beacon-chain/db/kv/log.go b/beacon-chain/db/kv/log.go index 5c1d80880c..086e552887 100644 --- a/beacon-chain/db/kv/log.go +++ b/beacon-chain/db/kv/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package kv import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "db") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/db/kv") diff --git a/beacon-chain/db/log.go b/beacon-chain/db/log.go index f320f2fe6a..2740265fe3 100644 --- a/beacon-chain/db/log.go +++ b/beacon-chain/db/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package db import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "db") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/db") diff --git a/beacon-chain/db/pruner/BUILD.bazel b/beacon-chain/db/pruner/BUILD.bazel index 26d5e32cf2..5474232ed2 100644 --- a/beacon-chain/db/pruner/BUILD.bazel +++ b/beacon-chain/db/pruner/BUILD.bazel @@ -2,7 +2,10 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = ["pruner.go"], + srcs = [ + "log.go", + "pruner.go", + ], importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/db/pruner", visibility = [ "//beacon-chain:__subpackages__", diff --git a/beacon-chain/db/pruner/log.go b/beacon-chain/db/pruner/log.go new file mode 100644 index 0000000000..b24b5c1b20 --- /dev/null +++ b/beacon-chain/db/pruner/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package pruner + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/db/pruner") diff --git a/beacon-chain/db/pruner/pruner.go b/beacon-chain/db/pruner/pruner.go index a078b1aab1..118aa3aff1 100644 --- a/beacon-chain/db/pruner/pruner.go +++ b/beacon-chain/db/pruner/pruner.go @@ -13,8 +13,6 @@ import ( "github.com/sirupsen/logrus" ) -var log = logrus.WithField("prefix", "db-pruner") - const ( // defaultPrunableBatchSize is the number of slots that can be pruned at once. defaultPrunableBatchSize = 32 diff --git a/beacon-chain/db/slasherkv/log.go b/beacon-chain/db/slasherkv/log.go index bbd2581220..d2825073f0 100644 --- a/beacon-chain/db/slasherkv/log.go +++ b/beacon-chain/db/slasherkv/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package slasherkv import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "slasherdb") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/db/slasherkv") diff --git a/beacon-chain/execution/engine_client.go b/beacon-chain/execution/engine_client.go index 5e6101238c..af3bf25679 100644 --- a/beacon-chain/execution/engine_client.go +++ b/beacon-chain/execution/engine_client.go @@ -563,12 +563,19 @@ func (s *Service) GetBlobsV2(ctx context.Context, versionedHashes []common.Hash) ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetBlobsV2") defer span.End() + start := time.Now() + if !s.capabilityCache.has(GetBlobsV2) { return nil, errors.New(fmt.Sprintf("%s is not supported", GetBlobsV2)) } result := make([]*pb.BlobAndProofV2, len(versionedHashes)) err := s.rpcClient.CallContext(ctx, &result, GetBlobsV2, versionedHashes) + + if len(result) != 0 { + getBlobsV2Latency.Observe(float64(time.Since(start).Milliseconds())) + } + return result, handleRPCError(err) } diff --git a/beacon-chain/execution/log.go b/beacon-chain/execution/log.go index 1d1840a9e4..ffef82774f 100644 --- a/beacon-chain/execution/log.go +++ b/beacon-chain/execution/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package execution import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "execution") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/execution") diff --git a/beacon-chain/execution/metrics.go b/beacon-chain/execution/metrics.go index 1fc2027b4f..b1ec43527f 100644 --- a/beacon-chain/execution/metrics.go +++ b/beacon-chain/execution/metrics.go @@ -27,6 +27,13 @@ var ( Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000}, }, ) + getBlobsV2Latency = promauto.NewHistogram( + prometheus.HistogramOpts{ + Name: "get_blobs_v2_latency_milliseconds", + Help: "Captures RPC latency for getBlobsV2 in milliseconds", + Buckets: []float64{25, 50, 100, 200, 500, 1000, 2000, 4000}, + }, + ) errParseCount = promauto.NewCounter(prometheus.CounterOpts{ Name: "execution_parse_error_count", Help: "The number of errors that occurred while parsing execution payload", diff --git a/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel b/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel index 619c9fc046..12e5a293af 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel +++ b/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "errors.go", "forkchoice.go", "last_root.go", + "log.go", "metrics.go", "node.go", "on_tick.go", diff --git a/beacon-chain/forkchoice/doubly-linked-tree/log.go b/beacon-chain/forkchoice/doubly-linked-tree/log.go new file mode 100644 index 0000000000..2954898deb --- /dev/null +++ b/beacon-chain/forkchoice/doubly-linked-tree/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package doublylinkedtree + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/forkchoice/doubly-linked-tree") diff --git a/beacon-chain/forkchoice/doubly-linked-tree/metrics.go b/beacon-chain/forkchoice/doubly-linked-tree/metrics.go index ed6d4ad1eb..c6a13ed896 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/metrics.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/metrics.go @@ -3,12 +3,9 @@ package doublylinkedtree import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/sirupsen/logrus" ) var ( - log = logrus.WithField("prefix", "forkchoice-doublylinkedtree") - headSlotNumber = promauto.NewGauge( prometheus.GaugeOpts{ Name: "doublylinkedtree_head_slot", diff --git a/beacon-chain/light-client/log.go b/beacon-chain/light-client/log.go index 755e9b685a..0655c0b770 100644 --- a/beacon-chain/light-client/log.go +++ b/beacon-chain/light-client/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package light_client import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "light-client") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/light-client") diff --git a/beacon-chain/monitor/BUILD.bazel b/beacon-chain/monitor/BUILD.bazel index de5b433c31..8fbd58cca9 100644 --- a/beacon-chain/monitor/BUILD.bazel +++ b/beacon-chain/monitor/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "doc.go", + "log.go", "metrics.go", "process_attestation.go", "process_block.go", diff --git a/beacon-chain/monitor/log.go b/beacon-chain/monitor/log.go new file mode 100644 index 0000000000..2333b4db93 --- /dev/null +++ b/beacon-chain/monitor/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package monitor + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/monitor") diff --git a/beacon-chain/monitor/metrics.go b/beacon-chain/monitor/metrics.go index a45fb5c983..a7bc9a9b86 100644 --- a/beacon-chain/monitor/metrics.go +++ b/beacon-chain/monitor/metrics.go @@ -3,11 +3,9 @@ package monitor import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/sirupsen/logrus" ) var ( - log = logrus.WithField("prefix", "monitor") // TODO: The Prometheus gauge vectors and counters in this package deprecate the // corresponding gauge vectors and counters in the validator client. diff --git a/beacon-chain/monitor/process_attestation_test.go b/beacon-chain/monitor/process_attestation_test.go index fcd4665e1c..88907bdf88 100644 --- a/beacon-chain/monitor/process_attestation_test.go +++ b/beacon-chain/monitor/process_attestation_test.go @@ -54,8 +54,8 @@ func TestProcessIncludedAttestationTwoTracked(t *testing.T) { AggregationBits: bitfield.Bitlist{0b11, 0b1}, } s.processIncludedAttestation(t.Context(), state, att) - wanted1 := "\"Attestation included\" balanceChange=0 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2" - wanted2 := "\"Attestation included\" balanceChange=100000000 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12" + wanted1 := "\"Attestation included\" balanceChange=0 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2" + wanted2 := "\"Attestation included\" balanceChange=100000000 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12" require.LogsContain(t, hook, wanted1) require.LogsContain(t, hook, wanted2) } @@ -123,8 +123,8 @@ func TestProcessUnaggregatedAttestationStateCached(t *testing.T) { } require.NoError(t, s.config.StateGen.SaveState(ctx, root, state)) s.processUnaggregatedAttestation(t.Context(), att) - wanted1 := "\"Processed unaggregated attestation\" head=0x68656c6c6f2d prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2" - wanted2 := "\"Processed unaggregated attestation\" head=0x68656c6c6f2d prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12" + wanted1 := "\"Processed unaggregated attestation\" head=0x68656c6c6f2d package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2" + wanted2 := "\"Processed unaggregated attestation\" head=0x68656c6c6f2d package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12" require.LogsContain(t, hook, wanted1) require.LogsContain(t, hook, wanted2) } @@ -161,7 +161,7 @@ func TestProcessAggregatedAttestationStateNotCached(t *testing.T) { }, } s.processAggregatedAttestation(ctx, att) - require.LogsContain(t, hook, "\"Processed attestation aggregation\" aggregatorIndex=2 beaconBlockRoot=0x000000000000 prefix=monitor slot=1 sourceRoot=0x68656c6c6f2d targetRoot=0x68656c6c6f2d") + require.LogsContain(t, hook, "\"Processed attestation aggregation\" aggregatorIndex=2 beaconBlockRoot=0x000000000000 package=beacon-chain/monitor slot=1 sourceRoot=0x68656c6c6f2d targetRoot=0x68656c6c6f2d") require.LogsContain(t, hook, "Skipping aggregated attestation due to state not found in cache") logrus.SetLevel(logrus.InfoLevel) } @@ -199,9 +199,9 @@ func TestProcessAggregatedAttestationStateCached(t *testing.T) { require.NoError(t, s.config.StateGen.SaveState(ctx, root, state)) s.processAggregatedAttestation(ctx, att) - require.LogsContain(t, hook, "\"Processed attestation aggregation\" aggregatorIndex=2 beaconBlockRoot=0x68656c6c6f2d prefix=monitor slot=1 sourceRoot=0x68656c6c6f2d targetRoot=0x68656c6c6f2d") - require.LogsContain(t, hook, "\"Processed aggregated attestation\" head=0x68656c6c6f2d prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2") - require.LogsDoNotContain(t, hook, "\"Processed aggregated attestation\" head=0x68656c6c6f2d prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12") + require.LogsContain(t, hook, "\"Processed attestation aggregation\" aggregatorIndex=2 beaconBlockRoot=0x68656c6c6f2d package=beacon-chain/monitor slot=1 sourceRoot=0x68656c6c6f2d targetRoot=0x68656c6c6f2d") + require.LogsContain(t, hook, "\"Processed aggregated attestation\" head=0x68656c6c6f2d package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2") + require.LogsDoNotContain(t, hook, "\"Processed aggregated attestation\" head=0x68656c6c6f2d package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12") } func TestProcessAttestations(t *testing.T) { @@ -239,8 +239,8 @@ func TestProcessAttestations(t *testing.T) { wrappedBlock, err := blocks.NewBeaconBlock(block) require.NoError(t, err) s.processAttestations(ctx, state, wrappedBlock) - wanted1 := "\"Attestation included\" balanceChange=0 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2" - wanted2 := "\"Attestation included\" balanceChange=100000000 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 prefix=monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12" + wanted1 := "\"Attestation included\" balanceChange=0 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=2" + wanted2 := "\"Attestation included\" balanceChange=100000000 correctHead=true correctSource=true correctTarget=true head=0x68656c6c6f2d inclusionSlot=2 newBalance=32000000000 package=beacon-chain/monitor slot=1 source=0x68656c6c6f2d target=0x68656c6c6f2d validatorIndex=12" require.LogsContain(t, hook, wanted1) require.LogsContain(t, hook, wanted2) diff --git a/beacon-chain/monitor/process_block_test.go b/beacon-chain/monitor/process_block_test.go index 7000d5eac2..5734fc1cca 100644 --- a/beacon-chain/monitor/process_block_test.go +++ b/beacon-chain/monitor/process_block_test.go @@ -43,7 +43,7 @@ func TestProcessSlashings(t *testing.T) { }, }, }, - wantedErr: "\"Proposer slashing was included\" bodyRoot1= bodyRoot2= prefix=monitor proposerIndex=2", + wantedErr: "\"Proposer slashing was included\" bodyRoot1= bodyRoot2= package=beacon-chain/monitor proposerIndex=2", }, { name: "Proposer slashing an untracked index", @@ -89,7 +89,7 @@ func TestProcessSlashings(t *testing.T) { }, }, wantedErr: "\"Attester slashing was included\" attestationSlot1=0 attestationSlot2=0 attesterIndex=1 " + - "beaconBlockRoot1=0x000000000000 beaconBlockRoot2=0x000000000000 blockInclusionSlot=0 prefix=monitor sourceEpoch1=1 sourceEpoch2=0 targetEpoch1=0 targetEpoch2=0", + "beaconBlockRoot1=0x000000000000 beaconBlockRoot2=0x000000000000 blockInclusionSlot=0 package=beacon-chain/monitor sourceEpoch1=1 sourceEpoch2=0 targetEpoch1=0 targetEpoch2=0", }, { name: "Attester slashing untracked index", @@ -149,7 +149,7 @@ func TestProcessProposedBlock(t *testing.T) { StateRoot: bytesutil.PadTo([]byte("state-world"), 32), Body: ðpb.BeaconBlockBody{}, }, - wantedErr: "\"Proposed beacon block was included\" balanceChange=100000000 blockRoot=0x68656c6c6f2d newBalance=32000000000 parentRoot=0x68656c6c6f2d prefix=monitor proposerIndex=12 slot=6 version=0", + wantedErr: "\"Proposed beacon block was included\" balanceChange=100000000 blockRoot=0x68656c6c6f2d newBalance=32000000000 package=beacon-chain/monitor parentRoot=0x68656c6c6f2d proposerIndex=12 slot=6 version=0", }, { name: "Block proposed by untracked validator", @@ -224,10 +224,10 @@ func TestProcessBlock_AllEventsTrackedVals(t *testing.T) { root, err := b.GetBlock().HashTreeRoot() require.NoError(t, err) require.NoError(t, s.config.StateGen.SaveState(ctx, root, genesis)) - wanted1 := fmt.Sprintf("\"Proposed beacon block was included\" balanceChange=100000000 blockRoot=%#x newBalance=32000000000 parentRoot=0xf732eaeb7fae prefix=monitor proposerIndex=15 slot=1 version=1", bytesutil.Trunc(root[:])) - wanted2 := fmt.Sprintf("\"Proposer slashing was included\" bodyRoot1=0x000100000000 bodyRoot2=0x000200000000 prefix=monitor proposerIndex=%d slashingSlot=0 slot=1", idx) - wanted3 := "\"Sync committee contribution included\" balanceChange=0 contribCount=3 expectedContribCount=3 newBalance=32000000000 prefix=monitor validatorIndex=1" - wanted4 := "\"Sync committee contribution included\" balanceChange=0 contribCount=1 expectedContribCount=1 newBalance=32000000000 prefix=monitor validatorIndex=2" + wanted1 := fmt.Sprintf("\"Proposed beacon block was included\" balanceChange=100000000 blockRoot=%#x newBalance=32000000000 package=beacon-chain/monitor parentRoot=0xf732eaeb7fae proposerIndex=15 slot=1 version=1", bytesutil.Trunc(root[:])) + wanted2 := fmt.Sprintf("\"Proposer slashing was included\" bodyRoot1=0x000100000000 bodyRoot2=0x000200000000 package=beacon-chain/monitor proposerIndex=%d slashingSlot=0 slot=1", idx) + wanted3 := "\"Sync committee contribution included\" balanceChange=0 contribCount=3 expectedContribCount=3 newBalance=32000000000 package=beacon-chain/monitor validatorIndex=1" + wanted4 := "\"Sync committee contribution included\" balanceChange=0 contribCount=1 expectedContribCount=1 newBalance=32000000000 package=beacon-chain/monitor validatorIndex=2" wrapped, err := blocks.NewSignedBeaconBlock(b) require.NoError(t, err) s.processBlock(ctx, wrapped) @@ -279,7 +279,7 @@ func TestLogAggregatedPerformance(t *testing.T) { s.logAggregatedPerformance() wanted := "\"Aggregated performance since launch\" attestationInclusion=\"80.00%\"" + " averageInclusionDistance=1.2 balanceChangePct=\"0.95%\" correctlyVotedHeadPct=\"66.67%\" " + - "correctlyVotedSourcePct=\"91.67%\" correctlyVotedTargetPct=\"100.00%\" prefix=monitor startBalance=31700000000 " + + "correctlyVotedSourcePct=\"91.67%\" correctlyVotedTargetPct=\"100.00%\" package=beacon-chain/monitor startBalance=31700000000 " + "startEpoch=0 totalAggregations=0 totalProposedBlocks=1 totalRequested=15 totalSyncContributions=0 " + "validatorIndex=1" require.LogsContain(t, hook, wanted) diff --git a/beacon-chain/monitor/process_exit_test.go b/beacon-chain/monitor/process_exit_test.go index 0375463c13..e1db6c2ad2 100644 --- a/beacon-chain/monitor/process_exit_test.go +++ b/beacon-chain/monitor/process_exit_test.go @@ -43,7 +43,7 @@ func TestProcessExitsFromBlockTrackedIndices(t *testing.T) { wb, err := blocks.NewBeaconBlock(block) require.NoError(t, err) s.processExitsFromBlock(wb) - require.LogsContain(t, hook, "\"Voluntary exit was included\" prefix=monitor slot=0 validatorIndex=2") + require.LogsContain(t, hook, "\"Voluntary exit was included\" package=beacon-chain/monitor slot=0 validatorIndex=2") } func TestProcessExitsFromBlockUntrackedIndices(t *testing.T) { @@ -99,7 +99,7 @@ func TestProcessExitP2PTrackedIndices(t *testing.T) { Signature: make([]byte, 96), } s.processExit(exit) - require.LogsContain(t, hook, "\"Voluntary exit was processed\" prefix=monitor validatorIndex=1") + require.LogsContain(t, hook, "\"Voluntary exit was processed\" package=beacon-chain/monitor validatorIndex=1") } func TestProcessExitP2PUntrackedIndices(t *testing.T) { diff --git a/beacon-chain/monitor/process_sync_committee_test.go b/beacon-chain/monitor/process_sync_committee_test.go index a1365f9aa5..a2d6b55168 100644 --- a/beacon-chain/monitor/process_sync_committee_test.go +++ b/beacon-chain/monitor/process_sync_committee_test.go @@ -22,7 +22,7 @@ func TestProcessSyncCommitteeContribution(t *testing.T) { } s.processSyncCommitteeContribution(contrib) - require.LogsContain(t, hook, "\"Sync committee aggregation processed\" prefix=monitor validatorIndex=1") + require.LogsContain(t, hook, "\"Sync committee aggregation processed\" package=beacon-chain/monitor validatorIndex=1") require.LogsDoNotContain(t, hook, "validatorIndex=2") } @@ -53,7 +53,7 @@ func TestProcessSyncAggregate(t *testing.T) { require.NoError(t, err) s.processSyncAggregate(beaconState, wrappedBlock) - require.LogsContain(t, hook, "\"Sync committee contribution included\" balanceChange=0 contribCount=1 expectedContribCount=4 newBalance=32000000000 prefix=monitor validatorIndex=1") - require.LogsContain(t, hook, "\"Sync committee contribution included\" balanceChange=100000000 contribCount=2 expectedContribCount=2 newBalance=32000000000 prefix=monitor validatorIndex=12") + require.LogsContain(t, hook, "\"Sync committee contribution included\" balanceChange=0 contribCount=1 expectedContribCount=4 newBalance=32000000000 package=beacon-chain/monitor validatorIndex=1") + require.LogsContain(t, hook, "\"Sync committee contribution included\" balanceChange=100000000 contribCount=2 expectedContribCount=2 newBalance=32000000000 package=beacon-chain/monitor validatorIndex=12") require.LogsDoNotContain(t, hook, "validatorIndex=2") } diff --git a/beacon-chain/monitor/service_test.go b/beacon-chain/monitor/service_test.go index 0e83bd46c2..e6004ee8e0 100644 --- a/beacon-chain/monitor/service_test.go +++ b/beacon-chain/monitor/service_test.go @@ -148,7 +148,7 @@ func TestStart(t *testing.T) { // wait for Logrus time.Sleep(1000 * time.Millisecond) require.LogsContain(t, hook, "Synced to head epoch, starting reporting performance") - require.LogsContain(t, hook, "\"Starting service\" prefix=monitor validatorIndices=\"[1 2 12 15]\"") + require.LogsContain(t, hook, "\"Starting service\" package=beacon-chain/monitor validatorIndices=\"[1 2 12 15]\"") s.Lock() require.Equal(t, s.isLogging, true, "monitor is not running") s.Unlock() @@ -235,7 +235,7 @@ func TestMonitorRoutine(t *testing.T) { // Wait for Logrus time.Sleep(1000 * time.Millisecond) - wanted1 := fmt.Sprintf("\"Proposed beacon block was included\" balanceChange=100000000 blockRoot=%#x newBalance=32000000000 parentRoot=0xf732eaeb7fae prefix=monitor proposerIndex=15 slot=1 version=1", bytesutil.Trunc(root[:])) + wanted1 := fmt.Sprintf("\"Proposed beacon block was included\" balanceChange=100000000 blockRoot=%#x newBalance=32000000000 package=beacon-chain/monitor parentRoot=0xf732eaeb7fae proposerIndex=15 slot=1 version=1", bytesutil.Trunc(root[:])) require.LogsContain(t, hook, wanted1) } diff --git a/beacon-chain/node/log.go b/beacon-chain/node/log.go index 2c3b06e822..8e5e0ee032 100644 --- a/beacon-chain/node/log.go +++ b/beacon-chain/node/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package node import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "node") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/node") diff --git a/beacon-chain/node/registration/log.go b/beacon-chain/node/registration/log.go index 0e3ed0b8e3..cbf6740f57 100644 --- a/beacon-chain/node/registration/log.go +++ b/beacon-chain/node/registration/log.go @@ -1 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package registration + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/node/registration") diff --git a/beacon-chain/node/registration/p2p.go b/beacon-chain/node/registration/p2p.go index 3fdabfc7a5..a864f8e355 100644 --- a/beacon-chain/node/registration/p2p.go +++ b/beacon-chain/node/registration/p2p.go @@ -7,7 +7,6 @@ import ( "github.com/OffchainLabs/prysm/v7/cmd" "github.com/OffchainLabs/prysm/v7/config/params" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" "gopkg.in/yaml.v2" ) diff --git a/beacon-chain/operations/attestations/kv/BUILD.bazel b/beacon-chain/operations/attestations/kv/BUILD.bazel index f2251084da..1cfdac868e 100644 --- a/beacon-chain/operations/attestations/kv/BUILD.bazel +++ b/beacon-chain/operations/attestations/kv/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "aggregated.go", "block.go", "kv.go", + "log.go", "seen_bits.go", "unaggregated.go", ], diff --git a/beacon-chain/operations/attestations/kv/aggregated.go b/beacon-chain/operations/attestations/kv/aggregated.go index 3339f36d89..8a5b021af3 100644 --- a/beacon-chain/operations/attestations/kv/aggregated.go +++ b/beacon-chain/operations/attestations/kv/aggregated.go @@ -13,7 +13,6 @@ import ( attaggregation "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1/attestation/aggregation/attestations" "github.com/OffchainLabs/prysm/v7/runtime/version" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) // AggregateUnaggregatedAttestations aggregates the unaggregated attestations and saves the diff --git a/beacon-chain/operations/attestations/kv/log.go b/beacon-chain/operations/attestations/kv/log.go new file mode 100644 index 0000000000..2d407204b6 --- /dev/null +++ b/beacon-chain/operations/attestations/kv/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package kv + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/operations/attestations/kv") diff --git a/beacon-chain/operations/attestations/kv/unaggregated.go b/beacon-chain/operations/attestations/kv/unaggregated.go index dc258b84b7..bb4190712e 100644 --- a/beacon-chain/operations/attestations/kv/unaggregated.go +++ b/beacon-chain/operations/attestations/kv/unaggregated.go @@ -9,7 +9,6 @@ import ( "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1/attestation" "github.com/OffchainLabs/prysm/v7/runtime/version" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) // SaveUnaggregatedAttestation saves an unaggregated attestation in cache. diff --git a/beacon-chain/operations/attestations/log.go b/beacon-chain/operations/attestations/log.go index 9a30bf344e..95b310dfdc 100644 --- a/beacon-chain/operations/attestations/log.go +++ b/beacon-chain/operations/attestations/log.go @@ -1,7 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package attestations -import ( - "github.com/sirupsen/logrus" -) +import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "pool/attestations") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/operations/attestations") diff --git a/beacon-chain/operations/blstoexec/BUILD.bazel b/beacon-chain/operations/blstoexec/BUILD.bazel index 4fcc38d760..3a74fce408 100644 --- a/beacon-chain/operations/blstoexec/BUILD.bazel +++ b/beacon-chain/operations/blstoexec/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "doc.go", + "log.go", "pool.go", ], importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/operations/blstoexec", diff --git a/beacon-chain/operations/blstoexec/log.go b/beacon-chain/operations/blstoexec/log.go new file mode 100644 index 0000000000..cbcded4941 --- /dev/null +++ b/beacon-chain/operations/blstoexec/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package blstoexec + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/operations/blstoexec") diff --git a/beacon-chain/operations/slashings/log.go b/beacon-chain/operations/slashings/log.go index 7c2a498e5d..17419dc1c4 100644 --- a/beacon-chain/operations/slashings/log.go +++ b/beacon-chain/operations/slashings/log.go @@ -1,7 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package slashings -import ( - "github.com/sirupsen/logrus" -) +import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "pool/slashings") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/operations/slashings") diff --git a/beacon-chain/operations/voluntaryexits/BUILD.bazel b/beacon-chain/operations/voluntaryexits/BUILD.bazel index 5a76900e8e..7968a45205 100644 --- a/beacon-chain/operations/voluntaryexits/BUILD.bazel +++ b/beacon-chain/operations/voluntaryexits/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "doc.go", + "log.go", "pool.go", ], importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/operations/voluntaryexits", diff --git a/beacon-chain/operations/voluntaryexits/log.go b/beacon-chain/operations/voluntaryexits/log.go new file mode 100644 index 0000000000..db584d7f0c --- /dev/null +++ b/beacon-chain/operations/voluntaryexits/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package voluntaryexits + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/operations/voluntaryexits") diff --git a/beacon-chain/p2p/BUILD.bazel b/beacon-chain/p2p/BUILD.bazel index 5f7866fad4..06b5a2f421 100644 --- a/beacon-chain/p2p/BUILD.bazel +++ b/beacon-chain/p2p/BUILD.bazel @@ -19,6 +19,7 @@ go_library( "info.go", "interfaces.go", "log.go", + "log_helpers.go", "message_id.go", "monitoring.go", "options.go", diff --git a/beacon-chain/p2p/log.go b/beacon-chain/p2p/log.go index bc848a1dbb..6f4aa21811 100644 --- a/beacon-chain/p2p/log.go +++ b/beacon-chain/p2p/log.go @@ -1,54 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package p2p -import ( - "net" - "strconv" - "strings" +import "github.com/sirupsen/logrus" - "github.com/libp2p/go-libp2p/core/peer" - ma "github.com/multiformats/go-multiaddr" - "github.com/sirupsen/logrus" -) - -var log = logrus.WithField("prefix", "p2p") - -func logIPAddr(id peer.ID, addrs ...ma.Multiaddr) { - for _, addr := range addrs { - if !(strings.Contains(addr.String(), "/ip4/") || strings.Contains(addr.String(), "/ip6/")) { - continue - } - - log.WithField( - "multiAddr", - addr.String()+"/p2p/"+id.String(), - ).Info("Node started p2p server") - } -} - -func logExternalIPAddr(id peer.ID, addr string, tcpPort, quicPort uint) { - if addr != "" { - multiAddrs, err := MultiAddressBuilder(net.ParseIP(addr), tcpPort, quicPort) - if err != nil { - log.WithError(err).Error("Could not create multiaddress") - return - } - - for _, multiAddr := range multiAddrs { - log.WithField( - "multiAddr", - multiAddr.String()+"/p2p/"+id.String(), - ).Info("Node started external p2p server") - } - } -} - -func logExternalDNSAddr(id peer.ID, addr string, port uint) { - if addr != "" { - p := strconv.FormatUint(uint64(port), 10) - - log.WithField( - "multiAddr", - "/dns4/"+addr+"/tcp/"+p+"/p2p/"+id.String(), - ).Info("Node started external p2p server") - } -} +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/p2p") diff --git a/beacon-chain/p2p/log_helpers.go b/beacon-chain/p2p/log_helpers.go new file mode 100644 index 0000000000..d402b0fbb5 --- /dev/null +++ b/beacon-chain/p2p/log_helpers.go @@ -0,0 +1,51 @@ +package p2p + +import ( + "net" + "strconv" + "strings" + + "github.com/libp2p/go-libp2p/core/peer" + ma "github.com/multiformats/go-multiaddr" +) + +func logIPAddr(id peer.ID, addrs ...ma.Multiaddr) { + for _, addr := range addrs { + if !(strings.Contains(addr.String(), "/ip4/") || strings.Contains(addr.String(), "/ip6/")) { + continue + } + + log.WithField( + "multiAddr", + addr.String()+"/p2p/"+id.String(), + ).Info("Node started p2p server") + } +} + +func logExternalIPAddr(id peer.ID, addr string, tcpPort, quicPort uint) { + if addr != "" { + multiAddrs, err := MultiAddressBuilder(net.ParseIP(addr), tcpPort, quicPort) + if err != nil { + log.WithError(err).Error("Could not create multiaddress") + return + } + + for _, multiAddr := range multiAddrs { + log.WithField( + "multiAddr", + multiAddr.String()+"/p2p/"+id.String(), + ).Info("Node started external p2p server") + } + } +} + +func logExternalDNSAddr(id peer.ID, addr string, port uint) { + if addr != "" { + p := strconv.FormatUint(uint64(port), 10) + + log.WithField( + "multiAddr", + "/dns4/"+addr+"/tcp/"+p+"/p2p/"+id.String(), + ).Info("Node started external p2p server") + } +} diff --git a/beacon-chain/p2p/peers/log.go b/beacon-chain/p2p/peers/log.go index eca49d07c1..27941f4c56 100644 --- a/beacon-chain/p2p/peers/log.go +++ b/beacon-chain/p2p/peers/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package peers import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "peers") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/p2p/peers") diff --git a/beacon-chain/p2p/types/object_mapping.go b/beacon-chain/p2p/types/object_mapping.go index 45d1b756e2..a94f6a3076 100644 --- a/beacon-chain/p2p/types/object_mapping.go +++ b/beacon-chain/p2p/types/object_mapping.go @@ -204,6 +204,9 @@ func InitializeDataMaps() { bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion): func() (interfaces.LightClientOptimisticUpdate, error) { return lightclientConsensusTypes.NewEmptyOptimisticUpdateDeneb(), nil }, + bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion): func() (interfaces.LightClientOptimisticUpdate, error) { + return lightclientConsensusTypes.NewEmptyOptimisticUpdateDeneb(), nil + }, } // Reset our light client finality update map. @@ -223,5 +226,8 @@ func InitializeDataMaps() { bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion): func() (interfaces.LightClientFinalityUpdate, error) { return lightclientConsensusTypes.NewEmptyFinalityUpdateElectra(), nil }, + bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion): func() (interfaces.LightClientFinalityUpdate, error) { + return lightclientConsensusTypes.NewEmptyFinalityUpdateElectra(), nil + }, } } diff --git a/beacon-chain/rpc/core/log.go b/beacon-chain/rpc/core/log.go index 6fa1855871..4d73afc2ae 100644 --- a/beacon-chain/rpc/core/log.go +++ b/beacon-chain/rpc/core/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package core import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "rpc/core") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/rpc/core") diff --git a/beacon-chain/rpc/eth/beacon/handlers.go b/beacon-chain/rpc/eth/beacon/handlers.go index dd61b75598..1b17045cb9 100644 --- a/beacon-chain/rpc/eth/beacon/handlers.go +++ b/beacon-chain/rpc/eth/beacon/handlers.go @@ -14,6 +14,7 @@ import ( "github.com/OffchainLabs/prysm/v7/api" "github.com/OffchainLabs/prysm/v7/api/server/structs" "github.com/OffchainLabs/prysm/v7/beacon-chain/blockchain/kzg" + coreblocks "github.com/OffchainLabs/prysm/v7/beacon-chain/core/blocks" corehelpers "github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/transition" "github.com/OffchainLabs/prysm/v7/beacon-chain/db/filters" @@ -957,6 +958,13 @@ func (s *Server) validateConsensus(ctx context.Context, b *eth.GenericSignedBeac } } } + blockRoot, err := blk.Block().HashTreeRoot() + if err != nil { + return errors.Wrap(err, "could not hash block") + } + if err := coreblocks.VerifyBlockSignatureUsingCurrentFork(parentState, blk, blockRoot); err != nil { + return errors.Wrap(err, "could not verify block signature") + } _, err = transition.ExecuteStateTransition(ctx, parentState, blk) if err != nil { return errors.Wrap(err, "could not execute state transition") diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index b26b298976..8b7be09d05 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -130,6 +130,10 @@ func (s *Server) SubmitAttestationsV2(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitAttestationsV2") defer span.End() + if shared.IsSyncing(ctx, w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) { + return + } + versionHeader := r.Header.Get(api.VersionHeader) if versionHeader == "" { httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) @@ -238,22 +242,14 @@ func (s *Server) handleAttestationsElectra( }, }) - targetState, err := s.AttestationStateFetcher.AttestationTargetState(ctx, singleAtt.Data.Target) - if err != nil { - return nil, nil, errors.Wrap(err, "could not get target state for attestation") - } - committee, err := corehelpers.BeaconCommitteeFromState(ctx, targetState, singleAtt.Data.Slot, singleAtt.CommitteeId) - if err != nil { - return nil, nil, errors.Wrap(err, "could not get committee for attestation") - } - att := singleAtt.ToAttestationElectra(committee) - - wantedEpoch := slots.ToEpoch(att.Data.Slot) + // Broadcast first using CommitteeId directly (fast path) + // This matches gRPC behavior and avoids blocking on state fetching + wantedEpoch := slots.ToEpoch(singleAtt.Data.Slot) vals, err := s.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch) if err != nil { return nil, nil, errors.Wrap(err, "could not get head validator indices") } - subnet := corehelpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), att.GetCommitteeIndex(), att.Data.Slot) + subnet := corehelpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), singleAtt.CommitteeId, singleAtt.Data.Slot) if err = s.Broadcaster.BroadcastAttestation(ctx, subnet, singleAtt); err != nil { failedBroadcasts = append(failedBroadcasts, &server.IndexedError{ Index: i, @@ -264,17 +260,35 @@ func (s *Server) handleAttestationsElectra( } continue } + } - if features.Get().EnableExperimentalAttestationPool { - if err = s.AttestationCache.Add(att); err != nil { - log.WithError(err).Error("Could not save attestation") + // Save to pool after broadcast (slow path - requires state fetching) + // Run in goroutine to avoid blocking the HTTP response + go func() { + for _, singleAtt := range validAttestations { + targetState, err := s.AttestationStateFetcher.AttestationTargetState(context.Background(), singleAtt.Data.Target) + if err != nil { + log.WithError(err).Error("Could not get target state for attestation") + continue } - } else { - if err = s.AttestationsPool.SaveUnaggregatedAttestation(att); err != nil { - log.WithError(err).Error("Could not save attestation") + committee, err := corehelpers.BeaconCommitteeFromState(context.Background(), targetState, singleAtt.Data.Slot, singleAtt.CommitteeId) + if err != nil { + log.WithError(err).Error("Could not get committee for attestation") + continue + } + att := singleAtt.ToAttestationElectra(committee) + + if features.Get().EnableExperimentalAttestationPool { + if err = s.AttestationCache.Add(att); err != nil { + log.WithError(err).Error("Could not save attestation") + } + } else { + if err = s.AttestationsPool.SaveUnaggregatedAttestation(att); err != nil { + log.WithError(err).Error("Could not save attestation") + } } } - } + }() if len(failedBroadcasts) > 0 { log.WithFields(logrus.Fields{ @@ -470,6 +484,10 @@ func (s *Server) SubmitSyncCommitteeSignatures(w http.ResponseWriter, r *http.Re ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitPoolSyncCommitteeSignatures") defer span.End() + if shared.IsSyncing(ctx, w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) { + return + } + var req structs.SubmitSyncCommitteeSignaturesRequest err := json.NewDecoder(r.Body).Decode(&req.Data) switch { diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool_test.go b/beacon-chain/rpc/eth/beacon/handlers_pool_test.go index f86734b1b3..0601428371 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool_test.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool_test.go @@ -26,6 +26,7 @@ import ( "github.com/OffchainLabs/prysm/v7/beacon-chain/operations/voluntaryexits/mock" p2pMock "github.com/OffchainLabs/prysm/v7/beacon-chain/p2p/testing" "github.com/OffchainLabs/prysm/v7/beacon-chain/rpc/core" + mockSync "github.com/OffchainLabs/prysm/v7/beacon-chain/sync/initial-sync/testing" state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native" "github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" @@ -622,6 +623,8 @@ func TestSubmitAttestationsV2(t *testing.T) { HeadFetcher: chainService, ChainInfoFetcher: chainService, TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, OperationNotifier: &blockchainmock.MockOperationNotifier{}, AttestationStateFetcher: chainService, } @@ -654,6 +657,7 @@ func TestSubmitAttestationsV2(t *testing.T) { assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch) assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root)) assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch) + time.Sleep(100 * time.Millisecond) // Wait for async pool save assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount()) }) t.Run("multiple", func(t *testing.T) { @@ -673,6 +677,7 @@ func TestSubmitAttestationsV2(t *testing.T) { assert.Equal(t, http.StatusOK, writer.Code) assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) assert.Equal(t, 2, broadcaster.NumAttestations()) + time.Sleep(100 * time.Millisecond) // Wait for async pool save assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount()) }) t.Run("phase0 att post electra", func(t *testing.T) { @@ -793,6 +798,7 @@ func TestSubmitAttestationsV2(t *testing.T) { assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch) assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root)) assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch) + time.Sleep(100 * time.Millisecond) // Wait for async pool save assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount()) }) t.Run("multiple", func(t *testing.T) { @@ -812,6 +818,7 @@ func TestSubmitAttestationsV2(t *testing.T) { assert.Equal(t, http.StatusOK, writer.Code) assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) assert.Equal(t, 2, broadcaster.NumAttestations()) + time.Sleep(100 * time.Millisecond) // Wait for async pool save assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount()) }) t.Run("no body", func(t *testing.T) { @@ -861,6 +868,27 @@ func TestSubmitAttestationsV2(t *testing.T) { assert.Equal(t, true, strings.Contains(e.Failures[0].Message, "Incorrect attestation signature")) }) }) + t.Run("syncing", func(t *testing.T) { + chainService := &blockchainmock.ChainService{} + s := &Server{ + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: true}, + } + + var body bytes.Buffer + _, err := body.WriteString(singleAtt) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusServiceUnavailable, writer.Code) + assert.Equal(t, true, strings.Contains(writer.Body.String(), "Beacon node is currently syncing")) + }) } func TestListVoluntaryExits(t *testing.T) { @@ -1057,14 +1085,19 @@ func TestSubmitSyncCommitteeSignatures(t *testing.T) { t.Run("single", func(t *testing.T) { broadcaster := &p2pMock.MockBroadcaster{} + chainService := &blockchainmock.ChainService{ + State: st, + SyncCommitteeIndices: []primitives.CommitteeIndex{0}, + } s := &Server{ + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, CoreService: &core.Service{ SyncCommitteePool: synccommittee.NewStore(), P2P: broadcaster, - HeadFetcher: &blockchainmock.ChainService{ - State: st, - SyncCommitteeIndices: []primitives.CommitteeIndex{0}, - }, + HeadFetcher: chainService, }, } @@ -1089,14 +1122,19 @@ func TestSubmitSyncCommitteeSignatures(t *testing.T) { }) t.Run("multiple", func(t *testing.T) { broadcaster := &p2pMock.MockBroadcaster{} + chainService := &blockchainmock.ChainService{ + State: st, + SyncCommitteeIndices: []primitives.CommitteeIndex{0}, + } s := &Server{ + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, CoreService: &core.Service{ SyncCommitteePool: synccommittee.NewStore(), P2P: broadcaster, - HeadFetcher: &blockchainmock.ChainService{ - State: st, - SyncCommitteeIndices: []primitives.CommitteeIndex{0}, - }, + HeadFetcher: chainService, }, } @@ -1120,13 +1158,18 @@ func TestSubmitSyncCommitteeSignatures(t *testing.T) { }) t.Run("invalid", func(t *testing.T) { broadcaster := &p2pMock.MockBroadcaster{} + chainService := &blockchainmock.ChainService{ + State: st, + } s := &Server{ + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, CoreService: &core.Service{ SyncCommitteePool: synccommittee.NewStore(), P2P: broadcaster, - HeadFetcher: &blockchainmock.ChainService{ - State: st, - }, + HeadFetcher: chainService, }, } @@ -1149,7 +1192,13 @@ func TestSubmitSyncCommitteeSignatures(t *testing.T) { assert.Equal(t, false, broadcaster.BroadcastCalled.Load()) }) t.Run("empty", func(t *testing.T) { - s := &Server{} + chainService := &blockchainmock.ChainService{State: st} + s := &Server{ + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } var body bytes.Buffer _, err := body.WriteString("[]") @@ -1166,7 +1215,13 @@ func TestSubmitSyncCommitteeSignatures(t *testing.T) { assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) }) t.Run("no body", func(t *testing.T) { - s := &Server{} + chainService := &blockchainmock.ChainService{State: st} + s := &Server{ + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) writer := httptest.NewRecorder() @@ -1179,6 +1234,26 @@ func TestSubmitSyncCommitteeSignatures(t *testing.T) { assert.Equal(t, http.StatusBadRequest, e.Code) assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) }) + t.Run("syncing", func(t *testing.T) { + chainService := &blockchainmock.ChainService{State: st} + s := &Server{ + HeadFetcher: chainService, + TimeFetcher: chainService, + OptimisticModeFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: true}, + } + + var body bytes.Buffer + _, err := body.WriteString(singleSyncCommitteeMsg) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitSyncCommitteeSignatures(writer, request) + assert.Equal(t, http.StatusServiceUnavailable, writer.Code) + assert.Equal(t, true, strings.Contains(writer.Body.String(), "Beacon node is currently syncing")) + }) } func TestListBLSToExecutionChanges(t *testing.T) { diff --git a/beacon-chain/rpc/eth/beacon/log.go b/beacon-chain/rpc/eth/beacon/log.go index b13781302a..d062044b0a 100644 --- a/beacon-chain/rpc/eth/beacon/log.go +++ b/beacon-chain/rpc/eth/beacon/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package beacon import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "rpc/beaconv1") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/rpc/eth/beacon") diff --git a/beacon-chain/rpc/eth/config/handlers.go b/beacon-chain/rpc/eth/config/handlers.go index 6ef4da6e17..38c29839d2 100644 --- a/beacon-chain/rpc/eth/config/handlers.go +++ b/beacon-chain/rpc/eth/config/handlers.go @@ -40,6 +40,7 @@ func GetForkSchedule(w http.ResponseWriter, r *http.Request) { httputil.WriteJson(w, &structs.GetForkScheduleResponse{ Data: data, }) + return } previous := schedule[0] for _, entry := range schedule { diff --git a/beacon-chain/rpc/eth/events/events_test.go b/beacon-chain/rpc/eth/events/events_test.go index f34181f003..284c331905 100644 --- a/beacon-chain/rpc/eth/events/events_test.go +++ b/beacon-chain/rpc/eth/events/events_test.go @@ -36,6 +36,7 @@ import ( ) var testEventWriteTimeout = 100 * time.Millisecond +var logger = logrus.StandardLogger() func requireAllEventsReceived(t *testing.T, stn, opn *mockChain.EventFeedWrapper, events []*feed.Event, req *topicRequest, s *Server, w *StreamingResponseWriterRecorder, logs chan *logrus.Entry) { // maxBufferSize param copied from sse lib client code diff --git a/beacon-chain/rpc/eth/events/log.go b/beacon-chain/rpc/eth/events/log.go index 6d218a4f03..543facfbc6 100644 --- a/beacon-chain/rpc/eth/events/log.go +++ b/beacon-chain/rpc/eth/events/log.go @@ -1,6 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package events import "github.com/sirupsen/logrus" -var logger = logrus.StandardLogger() -var log = logger.WithField("prefix", "events") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/rpc/eth/events") diff --git a/beacon-chain/rpc/eth/validator/log.go b/beacon-chain/rpc/eth/validator/log.go index de331ebcf6..8bfd2739d8 100644 --- a/beacon-chain/rpc/eth/validator/log.go +++ b/beacon-chain/rpc/eth/validator/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package validator import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "beacon-api") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/rpc/eth/validator") diff --git a/beacon-chain/rpc/log.go b/beacon-chain/rpc/log.go index 5c2ea5ccf3..4f697a1b74 100644 --- a/beacon-chain/rpc/log.go +++ b/beacon-chain/rpc/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package rpc import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "rpc") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/rpc") diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/log.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/log.go index 99ec18c4db..6d241c2756 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/log.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package beacon import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "rpc") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/rpc/prysm/v1alpha1/beacon") diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go index d23cd25186..e4e386c223 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -52,24 +52,27 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestation") defer span.End() + if vs.SyncChecker.Syncing() { + return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond") + } + resp, err := vs.proposeAtt(ctx, att, att.GetData().CommitteeIndex) if err != nil { return nil, err } - if features.Get().EnableExperimentalAttestationPool { - if err = vs.AttestationCache.Add(att); err != nil { - log.WithError(err).Error("Could not save attestation") - } - } else { - go func() { + go func() { + if features.Get().EnableExperimentalAttestationPool { + if err := vs.AttestationCache.Add(att); err != nil { + log.WithError(err).Error("Could not save attestation") + } + } else { attCopy := att.Copy() if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil { log.WithError(err).Error("Could not save unaggregated attestation") - return } - }() - } + } + }() return resp, nil } @@ -82,6 +85,10 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, singleAtt *ethp ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestationElectra") defer span.End() + if vs.SyncChecker.Syncing() { + return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond") + } + resp, err := vs.proposeAtt(ctx, singleAtt, singleAtt.GetCommitteeIndex()) if err != nil { return nil, err @@ -98,18 +105,17 @@ func (vs *Server) ProposeAttestationElectra(ctx context.Context, singleAtt *ethp singleAttCopy := singleAtt.Copy() att := singleAttCopy.ToAttestationElectra(committee) - if features.Get().EnableExperimentalAttestationPool { - if err = vs.AttestationCache.Add(att); err != nil { - log.WithError(err).Error("Could not save attestation") - } - } else { - go func() { + go func() { + if features.Get().EnableExperimentalAttestationPool { + if err := vs.AttestationCache.Add(att); err != nil { + log.WithError(err).Error("Could not save attestation") + } + } else { if err := vs.AttPool.SaveUnaggregatedAttestation(att); err != nil { log.WithError(err).Error("Could not save unaggregated attestation") - return } - }() - } + } + }() return resp, nil } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go index 70916c4ac7..064e3f32b2 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go @@ -38,6 +38,7 @@ func TestProposeAttestation(t *testing.T) { OperationNotifier: (&mock.ChainService{}).OperationNotifier(), TimeFetcher: chainService, AttestationStateFetcher: chainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, } head := util.NewBeaconBlock() head.Block.Slot = 999 @@ -141,6 +142,7 @@ func TestProposeAttestation_IncorrectSignature(t *testing.T) { P2P: &mockp2p.MockBroadcaster{}, AttPool: attestations.NewPool(), OperationNotifier: (&mock.ChainService{}).OperationNotifier(), + SyncChecker: &mockSync.Sync{IsSyncing: false}, } req := util.HydrateAttestation(ðpb.Attestation{}) @@ -149,6 +151,37 @@ func TestProposeAttestation_IncorrectSignature(t *testing.T) { assert.ErrorContains(t, wanted, err) } +func TestProposeAttestation_Syncing(t *testing.T) { + attesterServer := &Server{ + SyncChecker: &mockSync.Sync{IsSyncing: true}, + } + + req := util.HydrateAttestation(ðpb.Attestation{}) + _, err := attesterServer.ProposeAttestation(t.Context(), req) + assert.ErrorContains(t, "Syncing to latest head", err) + s, ok := status.FromError(err) + require.Equal(t, true, ok) + assert.Equal(t, codes.Unavailable, s.Code()) +} + +func TestProposeAttestationElectra_Syncing(t *testing.T) { + attesterServer := &Server{ + SyncChecker: &mockSync.Sync{IsSyncing: true}, + } + + req := ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + Source: ðpb.Checkpoint{Root: make([]byte, 32)}, + Target: ðpb.Checkpoint{Root: make([]byte, 32)}, + }, + } + _, err := attesterServer.ProposeAttestationElectra(t.Context(), req) + assert.ErrorContains(t, "Syncing to latest head", err) + s, ok := status.FromError(err) + require.Equal(t, true, ok) + assert.Equal(t, codes.Unavailable, s.Code()) +} + func TestGetAttestationData_OK(t *testing.T) { block := util.NewBeaconBlock() block.Block.Slot = 3*params.BeaconConfig().SlotsPerEpoch + 1 diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/log.go b/beacon-chain/rpc/prysm/v1alpha1/validator/log.go index 43f3b2870b..2be7cdffc0 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/log.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package validator import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "rpc/validator") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/rpc/prysm/v1alpha1/validator") diff --git a/beacon-chain/slasher/log.go b/beacon-chain/slasher/log.go index d45613e76e..d9c6963897 100644 --- a/beacon-chain/slasher/log.go +++ b/beacon-chain/slasher/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package slasher import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "slasher") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/slasher") diff --git a/beacon-chain/state/stategen/log.go b/beacon-chain/state/stategen/log.go index b3414dc6cf..0225f47e2d 100644 --- a/beacon-chain/state/stategen/log.go +++ b/beacon-chain/state/stategen/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package stategen import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "state-gen") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/state/stategen") diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state/stateutil/BUILD.bazel index 7d711446b2..ebb36a0d5c 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "field_root_validator.go", "field_root_vector.go", "historical_summaries_root.go", + "log.go", "participation_bit_root.go", "pending_attestation_root.go", "pending_consolidations_root.go", diff --git a/beacon-chain/state/stateutil/log.go b/beacon-chain/state/stateutil/log.go new file mode 100644 index 0000000000..4464e2aafc --- /dev/null +++ b/beacon-chain/state/stateutil/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package stateutil + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/state/stateutil") diff --git a/beacon-chain/sync/backfill/BUILD.bazel b/beacon-chain/sync/backfill/BUILD.bazel index 0940ae01ef..419c019eed 100644 --- a/beacon-chain/sync/backfill/BUILD.bazel +++ b/beacon-chain/sync/backfill/BUILD.bazel @@ -10,6 +10,7 @@ go_library( "error.go", "fulu_transition.go", "log.go", + "log_helpers.go", "metrics.go", "pool.go", "service.go", diff --git a/beacon-chain/sync/backfill/log.go b/beacon-chain/sync/backfill/log.go index 3402d3e450..b3298c9f93 100644 --- a/beacon-chain/sync/backfill/log.go +++ b/beacon-chain/sync/backfill/log.go @@ -1,115 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package backfill -import ( - "sync" - "sync/atomic" - "time" +import "github.com/sirupsen/logrus" - "github.com/sirupsen/logrus" -) - -var log = logrus.WithField("prefix", "backfill") - -// intervalLogger only logs once for each interval. It only customizes a single -// instance of the entry/logger and should just be used to control the logging rate for -// *one specific line of code*. -type intervalLogger struct { - *logrus.Entry - base *logrus.Entry - mux sync.Mutex - seconds int64 // seconds is the number of seconds per logging interval - last *atomic.Int64 // last is the quantized representation of the last time a log was emitted - now func() time.Time -} - -func newIntervalLogger(base *logrus.Entry, secondsBetweenLogs int64) *intervalLogger { - return &intervalLogger{ - Entry: base, - base: base, - seconds: secondsBetweenLogs, - last: new(atomic.Int64), - now: time.Now, - } -} - -// intervalNumber is a separate pure function because this helps tests determine -// proposer timestamp alignment. -func intervalNumber(t time.Time, seconds int64) int64 { - return t.Unix() / seconds -} - -// intervalNumber is the integer division of the current unix timestamp -// divided by the number of seconds per interval. -func (l *intervalLogger) intervalNumber() int64 { - return intervalNumber(l.now(), l.seconds) -} - -func (l *intervalLogger) copy() *intervalLogger { - return &intervalLogger{ - Entry: l.Entry, - base: l.base, - seconds: l.seconds, - last: l.last, - now: l.now, - } -} - -// Log overloads the Log() method of logrus.Entry, which is called under the hood -// when a log-level specific method (like Info(), Warn(), Error()) is invoked. -// By intercepting this call we can rate limit how often we log. -func (l *intervalLogger) Log(level logrus.Level, args ...any) { - n := l.intervalNumber() - // If Swap returns a different value that the current interval number, we haven't - // emitted a log yet this interval, so we can do so now. - if l.last.Swap(n) != n { - l.Entry.Log(level, args...) - } - // reset the Entry to the base so that any WithField/WithError calls - // don't persist across calls to Log() -} - -func (l *intervalLogger) WithField(key string, value any) *intervalLogger { - cp := l.copy() - cp.Entry = cp.Entry.WithField(key, value) - return cp -} - -func (l *intervalLogger) WithFields(fields logrus.Fields) *intervalLogger { - cp := l.copy() - cp.Entry = cp.Entry.WithFields(fields) - return cp -} - -func (l *intervalLogger) WithError(err error) *intervalLogger { - cp := l.copy() - cp.Entry = cp.Entry.WithError(err) - return cp -} - -func (l *intervalLogger) Trace(args ...any) { - l.Log(logrus.TraceLevel, args...) -} - -func (l *intervalLogger) Debug(args ...any) { - l.Log(logrus.DebugLevel, args...) -} - -func (l *intervalLogger) Print(args ...any) { - l.Info(args...) -} - -func (l *intervalLogger) Info(args ...any) { - l.Log(logrus.InfoLevel, args...) -} - -func (l *intervalLogger) Warn(args ...any) { - l.Log(logrus.WarnLevel, args...) -} - -func (l *intervalLogger) Warning(args ...any) { - l.Warn(args...) -} - -func (l *intervalLogger) Error(args ...any) { - l.Log(logrus.ErrorLevel, args...) -} +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/sync/backfill") diff --git a/beacon-chain/sync/backfill/log_helpers.go b/beacon-chain/sync/backfill/log_helpers.go new file mode 100644 index 0000000000..71166c0c69 --- /dev/null +++ b/beacon-chain/sync/backfill/log_helpers.go @@ -0,0 +1,113 @@ +package backfill + +import ( + "sync" + "sync/atomic" + "time" + + "github.com/sirupsen/logrus" +) + +// intervalLogger only logs once for each interval. It only customizes a single +// instance of the entry/logger and should just be used to control the logging rate for +// *one specific line of code*. +type intervalLogger struct { + *logrus.Entry + base *logrus.Entry + mux sync.Mutex + seconds int64 // seconds is the number of seconds per logging interval + last *atomic.Int64 // last is the quantized representation of the last time a log was emitted + now func() time.Time +} + +func newIntervalLogger(base *logrus.Entry, secondsBetweenLogs int64) *intervalLogger { + return &intervalLogger{ + Entry: base, + base: base, + seconds: secondsBetweenLogs, + last: new(atomic.Int64), + now: time.Now, + } +} + +// intervalNumber is a separate pure function because this helps tests determine +// proposer timestamp alignment. +func intervalNumber(t time.Time, seconds int64) int64 { + return t.Unix() / seconds +} + +// intervalNumber is the integer division of the current unix timestamp +// divided by the number of seconds per interval. +func (l *intervalLogger) intervalNumber() int64 { + return intervalNumber(l.now(), l.seconds) +} + +func (l *intervalLogger) copy() *intervalLogger { + return &intervalLogger{ + Entry: l.Entry, + base: l.base, + seconds: l.seconds, + last: l.last, + now: l.now, + } +} + +// Log overloads the Log() method of logrus.Entry, which is called under the hood +// when a log-level specific method (like Info(), Warn(), Error()) is invoked. +// By intercepting this call we can rate limit how often we log. +func (l *intervalLogger) Log(level logrus.Level, args ...any) { + n := l.intervalNumber() + // If Swap returns a different value that the current interval number, we haven't + // emitted a log yet this interval, so we can do so now. + if l.last.Swap(n) != n { + l.Entry.Log(level, args...) + } + // reset the Entry to the base so that any WithField/WithError calls + // don't persist across calls to Log() +} + +func (l *intervalLogger) WithField(key string, value any) *intervalLogger { + cp := l.copy() + cp.Entry = cp.Entry.WithField(key, value) + return cp +} + +func (l *intervalLogger) WithFields(fields logrus.Fields) *intervalLogger { + cp := l.copy() + cp.Entry = cp.Entry.WithFields(fields) + return cp +} + +func (l *intervalLogger) WithError(err error) *intervalLogger { + cp := l.copy() + cp.Entry = cp.Entry.WithError(err) + return cp +} + +func (l *intervalLogger) Trace(args ...any) { + l.Log(logrus.TraceLevel, args...) +} + +func (l *intervalLogger) Debug(args ...any) { + l.Log(logrus.DebugLevel, args...) +} + +func (l *intervalLogger) Print(args ...any) { + l.Info(args...) +} + +func (l *intervalLogger) Info(args ...any) { + l.Log(logrus.InfoLevel, args...) +} + +func (l *intervalLogger) Warn(args ...any) { + l.Log(logrus.WarnLevel, args...) +} + +func (l *intervalLogger) Warning(args ...any) { + l.Warn(args...) +} + +func (l *intervalLogger) Error(args ...any) { + l.Log(logrus.ErrorLevel, args...) +} diff --git a/beacon-chain/sync/batch_verifier.go b/beacon-chain/sync/batch_verifier.go index f9979f0a8e..e5e4926d5b 100644 --- a/beacon-chain/sync/batch_verifier.go +++ b/beacon-chain/sync/batch_verifier.go @@ -163,11 +163,15 @@ func (s *Service) validateWithKzgBatchVerifier(ctx context.Context, dataColumns resChan := make(chan error, 1) verificationSet := &kzgVerifier{dataColumns: dataColumns, resChan: resChan} - s.kzgChan <- verificationSet - ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() + select { + case s.kzgChan <- verificationSet: + case <-ctx.Done(): + return pubsub.ValidationIgnore, ctx.Err() + } + select { case <-ctx.Done(): return pubsub.ValidationIgnore, ctx.Err() // parent context canceled, give up diff --git a/beacon-chain/sync/checkpoint/log.go b/beacon-chain/sync/checkpoint/log.go index 3cf5fad74c..3d16723484 100644 --- a/beacon-chain/sync/checkpoint/log.go +++ b/beacon-chain/sync/checkpoint/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package checkpoint import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "checkpoint-sync") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/sync/checkpoint") diff --git a/beacon-chain/sync/data_column_sidecars.go b/beacon-chain/sync/data_column_sidecars.go index 0459eb2de4..31b21bff4a 100644 --- a/beacon-chain/sync/data_column_sidecars.go +++ b/beacon-chain/sync/data_column_sidecars.go @@ -3,6 +3,7 @@ package sync import ( "bytes" "context" + "fmt" "maps" "slices" "sync" @@ -243,8 +244,10 @@ func requestDirectSidecarsFromPeers( } // Compute missing indices by root, excluding those already in storage. + var lastRoot [fieldparams.RootLength]byte missingIndicesByRoot := make(map[[fieldparams.RootLength]byte]map[uint64]bool, len(incompleteRoots)) for root := range incompleteRoots { + lastRoot = root storedIndices := storedIndicesByRoot[root] missingIndices := make(map[uint64]bool, len(requestedIndices)) @@ -259,6 +262,7 @@ func requestDirectSidecarsFromPeers( } } + initialMissingRootCount := len(missingIndicesByRoot) initialMissingCount := computeTotalCount(missingIndicesByRoot) indicesByRootByPeer, err := computeIndicesByRootByPeer(params.P2P, slotByRoot, missingIndicesByRoot, connectedPeers) @@ -301,11 +305,19 @@ func requestDirectSidecarsFromPeers( } } - log.WithFields(logrus.Fields{ - "duration": time.Since(start), - "initialMissingCount": initialMissingCount, - "finalMissingCount": computeTotalCount(missingIndicesByRoot), - }).Debug("Requested direct data column sidecars from peers") + log := log.WithFields(logrus.Fields{ + "duration": time.Since(start), + "initialMissingRootCount": initialMissingRootCount, + "initialMissingCount": initialMissingCount, + "finalMissingRootCount": len(missingIndicesByRoot), + "finalMissingCount": computeTotalCount(missingIndicesByRoot), + }) + + if initialMissingRootCount == 1 { + log = log.WithField("root", fmt.Sprintf("%#x", lastRoot)) + } + + log.Debug("Requested direct data column sidecars from peers") return verifiedColumnsByRoot, nil } diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher_test.go b/beacon-chain/sync/initial-sync/blocks_fetcher_test.go index 6cbf413ed2..5d90c6e018 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher_test.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher_test.go @@ -604,7 +604,7 @@ func TestBlocksFetcher_RequestBlocksRateLimitingLocks(t *testing.T) { // p3 responded w/o waiting for rate limiter's lock (on which p2 spins). } // Make sure that p2 has been rate limited. - require.LogsContain(t, hook, fmt.Sprintf("msg=\"Slowing down for rate limit\" peer=%s", p2.PeerID())) + require.LogsContain(t, hook, fmt.Sprintf("msg=\"Slowing down for rate limit\" package=beacon-chain/sync/initial-sync peer=%s", p2.PeerID())) } func TestBlocksFetcher_WaitForBandwidth(t *testing.T) { diff --git a/beacon-chain/sync/initial-sync/log.go b/beacon-chain/sync/initial-sync/log.go index 1f79b69d6e..12bdc2390b 100644 --- a/beacon-chain/sync/initial-sync/log.go +++ b/beacon-chain/sync/initial-sync/log.go @@ -1,7 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package initialsync -import ( - "github.com/sirupsen/logrus" -) +import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "initial-sync") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/sync/initial-sync") diff --git a/beacon-chain/sync/kzg_batch_verifier_test.go b/beacon-chain/sync/kzg_batch_verifier_test.go index 80ce24fe6f..97cbe48808 100644 --- a/beacon-chain/sync/kzg_batch_verifier_test.go +++ b/beacon-chain/sync/kzg_batch_verifier_test.go @@ -304,6 +304,36 @@ func TestValidateWithKzgBatchVerifier_DeadlockOnTimeout(t *testing.T) { } } +func TestValidateWithKzgBatchVerifier_ContextCanceledBeforeSend(t *testing.T) { + cancelledCtx, cancel := context.WithCancel(t.Context()) + cancel() + + service := &Service{ + ctx: context.Background(), + kzgChan: make(chan *kzgVerifier), + } + + done := make(chan struct{}) + go func() { + result, err := service.validateWithKzgBatchVerifier(cancelledCtx, nil) + require.Equal(t, pubsub.ValidationIgnore, result) + require.ErrorIs(t, err, context.Canceled) + close(done) + }() + + select { + case <-done: + case <-time.After(500 * time.Millisecond): + t.Fatal("validateWithKzgBatchVerifier did not return after context cancellation") + } + + select { + case <-service.kzgChan: + t.Fatal("verificationSet was sent to kzgChan despite canceled context") + default: + } +} + func createValidTestDataColumns(t *testing.T, count int) []blocks.RODataColumn { _, roSidecars, _ := util.GenerateTestFuluBlockWithSidecars(t, count) if len(roSidecars) >= count { diff --git a/beacon-chain/sync/log.go b/beacon-chain/sync/log.go index 5ad819f5c4..166efd4e81 100644 --- a/beacon-chain/sync/log.go +++ b/beacon-chain/sync/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package sync import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "sync") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/sync") diff --git a/beacon-chain/sync/metrics.go b/beacon-chain/sync/metrics.go index 7acfab0f5d..e4b634910d 100644 --- a/beacon-chain/sync/metrics.go +++ b/beacon-chain/sync/metrics.go @@ -204,6 +204,13 @@ var ( }, ) + dataColumnsRecoveredFromELAttempts = promauto.NewCounter( + prometheus.CounterOpts{ + Name: "data_columns_recovered_from_el_attempts", + Help: "Count the number of data columns recovery attempts from the execution layer.", + }, + ) + dataColumnsRecoveredFromELTotal = promauto.NewCounter( prometheus.CounterOpts{ Name: "data_columns_recovered_from_el_total", @@ -242,6 +249,13 @@ var ( Buckets: []float64{100, 250, 500, 750, 1000, 1500, 2000, 4000, 8000, 12000, 16000}, }, ) + + dataColumnSidecarsObtainedViaELCount = promauto.NewSummary( + prometheus.SummaryOpts{ + Name: "data_column_obtained_via_el_count", + Help: "Count the number of data column sidecars obtained via the execution layer.", + }, + ) ) func (s *Service) updateMetrics() { diff --git a/beacon-chain/sync/pending_attestations_queue.go b/beacon-chain/sync/pending_attestations_queue.go index 06054abab1..d16a7a9c1e 100644 --- a/beacon-chain/sync/pending_attestations_queue.go +++ b/beacon-chain/sync/pending_attestations_queue.go @@ -3,9 +3,9 @@ package sync import ( "bytes" "context" - "encoding/hex" "fmt" "slices" + "time" "github.com/OffchainLabs/prysm/v7/beacon-chain/blockchain" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/blocks" @@ -21,13 +21,23 @@ import ( "github.com/OffchainLabs/prysm/v7/monitoring/tracing/trace" ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v7/runtime/version" - "github.com/OffchainLabs/prysm/v7/time" "github.com/OffchainLabs/prysm/v7/time/slots" pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/pkg/errors" "github.com/sirupsen/logrus" ) -var pendingAttsLimit = 32768 +const pendingAttsLimit = 32768 + +// aggregatorIndexFilter defines how aggregator index should be handled in equality checks. +type aggregatorIndexFilter int + +const ( + // ignoreAggregatorIndex means aggregates differing only by aggregator index are considered equal. + ignoreAggregatorIndex aggregatorIndexFilter = iota + // includeAggregatorIndex means aggregator index must also match for aggregates to be considered equal. + includeAggregatorIndex +) // This method processes pending attestations as a "known" block as arrived. With validations, // the valid attestations get saved into the operation mem pool, and the invalid attestations gets deleted @@ -50,16 +60,7 @@ func (s *Service) processPendingAttsForBlock(ctx context.Context, bRoot [32]byte attestations := s.blkRootToPendingAtts[bRoot] s.pendingAttsLock.RUnlock() - if len(attestations) > 0 { - start := time.Now() - s.processAttestations(ctx, attestations) - duration := time.Since(start) - log.WithFields(logrus.Fields{ - "blockRoot": hex.EncodeToString(bytesutil.Trunc(bRoot[:])), - "pendingAttsCount": len(attestations), - "duration": duration, - }).Debug("Verified and saved pending attestations to pool") - } + s.processAttestations(ctx, attestations) randGen := rand.NewGenerator() // Delete the missing block root key from pending attestation queue so a node will not request for the block again. @@ -79,26 +80,71 @@ func (s *Service) processPendingAttsForBlock(ctx context.Context, bRoot [32]byte return s.sendBatchRootRequest(ctx, pendingRoots, randGen) } +// processAttestations processes a list of attestations. +// It assumes (for logging purposes only) that all attestations pertain to the same block. func (s *Service) processAttestations(ctx context.Context, attestations []any) { if len(attestations) == 0 { return } + firstAttestation := attestations[0] + var blockRoot []byte + switch v := firstAttestation.(type) { + case ethpb.Att: + blockRoot = v.GetData().BeaconBlockRoot + case ethpb.SignedAggregateAttAndProof: + blockRoot = v.AggregateAttestationAndProof().AggregateVal().GetData().BeaconBlockRoot + default: + log.Warnf("Unexpected attestation type %T, skipping processing", v) + return + } + + validAggregates := make([]ethpb.SignedAggregateAttAndProof, 0, len(attestations)) + startAggregate := time.Now() atts := make([]ethpb.Att, 0, len(attestations)) + aggregateAttAndProofCount := 0 for _, att := range attestations { switch v := att.(type) { case ethpb.Att: atts = append(atts, v) case ethpb.SignedAggregateAttAndProof: - s.processAggregate(ctx, v) + aggregateAttAndProofCount++ + // Avoid processing multiple aggregates only differing by aggregator index. + if slices.ContainsFunc(validAggregates, func(other ethpb.SignedAggregateAttAndProof) bool { + return pendingAggregatesAreEqual(v, other, ignoreAggregatorIndex) + }) { + continue + } + + if err := s.processAggregate(ctx, v); err != nil { + log.WithError(err).Debug("Pending aggregate attestation could not be processed") + continue + } + + validAggregates = append(validAggregates, v) default: log.Warnf("Unexpected attestation type %T, skipping", v) } } + durationAggregateAttAndProof := time.Since(startAggregate) + startAtts := time.Now() for _, bucket := range bucketAttestationsByData(atts) { s.processAttestationBucket(ctx, bucket) } + + durationAtts := time.Since(startAtts) + + log.WithFields(logrus.Fields{ + "blockRoot": fmt.Sprintf("%#x", blockRoot), + "totalCount": len(attestations), + "aggregateAttAndProofCount": aggregateAttAndProofCount, + "uniqueAggregateAttAndProofCount": len(validAggregates), + "attCount": len(atts), + "durationTotal": durationAggregateAttAndProof + durationAtts, + "durationAggregateAttAndProof": durationAggregateAttAndProof, + "durationAtts": durationAtts, + }).Debug("Verified and saved pending attestations to pool") } // attestationBucket groups attestations with the same AttestationData for batch processing. @@ -303,21 +349,20 @@ func (s *Service) processVerifiedAttestation( }) } -func (s *Service) processAggregate(ctx context.Context, aggregate ethpb.SignedAggregateAttAndProof) { +func (s *Service) processAggregate(ctx context.Context, aggregate ethpb.SignedAggregateAttAndProof) error { res, err := s.validateAggregatedAtt(ctx, aggregate) if err != nil { log.WithError(err).Debug("Pending aggregated attestation failed validation") - return + return errors.Wrap(err, "validate aggregated att") } + if res != pubsub.ValidationAccept || !s.validateBlockInAttestation(ctx, aggregate) { - log.Debug("Pending aggregated attestation failed validation") - return + return errors.New("Pending aggregated attestation failed validation") } att := aggregate.AggregateAttestationAndProof().AggregateVal() if err := s.saveAttestation(att); err != nil { - log.WithError(err).Debug("Could not save aggregated attestation") - return + return errors.Wrap(err, "save attestation") } _ = s.setAggregatorIndexEpochSeen(att.GetData().Target.Epoch, aggregate.AggregateAttestationAndProof().GetAggregatorIndex()) @@ -325,6 +370,8 @@ func (s *Service) processAggregate(ctx context.Context, aggregate ethpb.SignedAg if err := s.cfg.p2p.Broadcast(ctx, aggregate); err != nil { log.WithError(err).Debug("Could not broadcast aggregated attestation") } + + return nil } // This defines how pending aggregates are saved in the map. The key is the @@ -336,7 +383,7 @@ func (s *Service) savePendingAggregate(agg ethpb.SignedAggregateAttAndProof) { s.savePending(root, agg, func(other any) bool { a, ok := other.(ethpb.SignedAggregateAttAndProof) - return ok && pendingAggregatesAreEqual(agg, a) + return ok && pendingAggregatesAreEqual(agg, a, includeAggregatorIndex) }) } @@ -391,13 +438,19 @@ func (s *Service) savePending(root [32]byte, pending any, isEqual func(other any s.blkRootToPendingAtts[root] = append(s.blkRootToPendingAtts[root], pending) } -func pendingAggregatesAreEqual(a, b ethpb.SignedAggregateAttAndProof) bool { +// pendingAggregatesAreEqual checks if two pending aggregate attestations are equal. +// The filter parameter controls whether aggregator index is considered in the equality check. +func pendingAggregatesAreEqual(a, b ethpb.SignedAggregateAttAndProof, filter aggregatorIndexFilter) bool { if a.Version() != b.Version() { return false } - if a.AggregateAttestationAndProof().GetAggregatorIndex() != b.AggregateAttestationAndProof().GetAggregatorIndex() { - return false + + if filter == includeAggregatorIndex { + if a.AggregateAttestationAndProof().GetAggregatorIndex() != b.AggregateAttestationAndProof().GetAggregatorIndex() { + return false + } } + aAtt := a.AggregateAttestationAndProof().AggregateVal() bAtt := b.AggregateAttestationAndProof().AggregateVal() if aAtt.GetData().Slot != bAtt.GetData().Slot { diff --git a/beacon-chain/sync/pending_attestations_queue_test.go b/beacon-chain/sync/pending_attestations_queue_test.go index 19fc363494..a44647da4f 100644 --- a/beacon-chain/sync/pending_attestations_queue_test.go +++ b/beacon-chain/sync/pending_attestations_queue_test.go @@ -94,7 +94,7 @@ func TestProcessPendingAtts_NoBlockRequestBlock(t *testing.T) { // Process block A (which exists and has no pending attestations) // This should skip processing attestations for A and request blocks B and C require.NoError(t, r.processPendingAttsForBlock(t.Context(), rootA)) - require.LogsContain(t, hook, "Requesting block by root") + require.LogsContain(t, hook, "Requesting blocks by root") } func TestProcessPendingAtts_HasBlockSaveUnaggregatedAtt(t *testing.T) { @@ -911,17 +911,17 @@ func Test_pendingAggregatesAreEqual(t *testing.T) { }, AggregationBits: bitfield.Bitlist{0b1111}, }}} - assert.Equal(t, true, pendingAggregatesAreEqual(a, b)) + assert.Equal(t, true, pendingAggregatesAreEqual(a, b, includeAggregatorIndex)) }) t.Run("different version", func(t *testing.T) { a := ðpb.SignedAggregateAttestationAndProof{Message: ðpb.AggregateAttestationAndProof{AggregatorIndex: 1}} b := ðpb.SignedAggregateAttestationAndProofElectra{Message: ðpb.AggregateAttestationAndProofElectra{AggregatorIndex: 1}} - assert.Equal(t, false, pendingAggregatesAreEqual(a, b)) + assert.Equal(t, false, pendingAggregatesAreEqual(a, b, includeAggregatorIndex)) }) t.Run("different aggregator index", func(t *testing.T) { a := ðpb.SignedAggregateAttestationAndProof{Message: ðpb.AggregateAttestationAndProof{AggregatorIndex: 1}} b := ðpb.SignedAggregateAttestationAndProof{Message: ðpb.AggregateAttestationAndProof{AggregatorIndex: 2}} - assert.Equal(t, false, pendingAggregatesAreEqual(a, b)) + assert.Equal(t, false, pendingAggregatesAreEqual(a, b, includeAggregatorIndex)) }) t.Run("different slot", func(t *testing.T) { a := ðpb.SignedAggregateAttestationAndProof{ @@ -942,7 +942,7 @@ func Test_pendingAggregatesAreEqual(t *testing.T) { }, AggregationBits: bitfield.Bitlist{0b1111}, }}} - assert.Equal(t, false, pendingAggregatesAreEqual(a, b)) + assert.Equal(t, false, pendingAggregatesAreEqual(a, b, includeAggregatorIndex)) }) t.Run("different committee index", func(t *testing.T) { a := ðpb.SignedAggregateAttestationAndProof{ @@ -963,7 +963,7 @@ func Test_pendingAggregatesAreEqual(t *testing.T) { }, AggregationBits: bitfield.Bitlist{0b1111}, }}} - assert.Equal(t, false, pendingAggregatesAreEqual(a, b)) + assert.Equal(t, false, pendingAggregatesAreEqual(a, b, includeAggregatorIndex)) }) t.Run("different aggregation bits", func(t *testing.T) { a := ðpb.SignedAggregateAttestationAndProof{ @@ -984,7 +984,30 @@ func Test_pendingAggregatesAreEqual(t *testing.T) { }, AggregationBits: bitfield.Bitlist{0b1000}, }}} - assert.Equal(t, false, pendingAggregatesAreEqual(a, b)) + assert.Equal(t, false, pendingAggregatesAreEqual(a, b, includeAggregatorIndex)) + }) + t.Run("different aggregator index should be equal while ignoring aggregator index", func(t *testing.T) { + a := ðpb.SignedAggregateAttestationAndProof{ + Message: ðpb.AggregateAttestationAndProof{ + AggregatorIndex: 1, + Aggregate: ðpb.Attestation{ + Data: ðpb.AttestationData{ + Slot: 1, + CommitteeIndex: 1, + }, + AggregationBits: bitfield.Bitlist{0b1111}, + }}} + b := ðpb.SignedAggregateAttestationAndProof{ + Message: ðpb.AggregateAttestationAndProof{ + AggregatorIndex: 2, + Aggregate: ðpb.Attestation{ + Data: ðpb.AttestationData{ + Slot: 1, + CommitteeIndex: 1, + }, + AggregationBits: bitfield.Bitlist{0b1111}, + }}} + assert.Equal(t, true, pendingAggregatesAreEqual(a, b, ignoreAggregatorIndex)) }) } diff --git a/beacon-chain/sync/pending_blocks_queue.go b/beacon-chain/sync/pending_blocks_queue.go index b1ab64119b..28778efc77 100644 --- a/beacon-chain/sync/pending_blocks_queue.go +++ b/beacon-chain/sync/pending_blocks_queue.go @@ -2,7 +2,6 @@ package sync import ( "context" - "encoding/hex" "fmt" "slices" "sync" @@ -44,11 +43,13 @@ func (s *Service) processPendingBlocksQueue() { if !s.chainIsStarted() { return } + locker.Lock() + defer locker.Unlock() + if err := s.processPendingBlocks(s.ctx); err != nil { log.WithError(err).Debug("Could not process pending blocks") } - locker.Unlock() }) } @@ -73,8 +74,10 @@ func (s *Service) processPendingBlocks(ctx context.Context) error { randGen := rand.NewGenerator() var parentRoots [][32]byte + blkRoots := make([][32]byte, 0, len(sortedSlots)*maxBlocksPerSlot) + // Iterate through sorted slots. - for _, slot := range sortedSlots { + for i, slot := range sortedSlots { // Skip processing if slot is in the future. if slot > s.cfg.clock.CurrentSlot() { continue @@ -91,6 +94,9 @@ func (s *Service) processPendingBlocks(ctx context.Context) error { // Process each block in the queue. for _, b := range blocksInCache { + start := time.Now() + totalDuration := time.Duration(0) + if err := blocks.BeaconBlockIsNil(b); err != nil { continue } @@ -147,19 +153,34 @@ func (s *Service) processPendingBlocks(ctx context.Context) error { } cancelFunction() - // Process pending attestations for this block. - if err := s.processPendingAttsForBlock(ctx, blkRoot); err != nil { - log.WithError(err).Debug("Failed to process pending attestations for block") - } + blkRoots = append(blkRoots, blkRoot) // Remove the processed block from the queue. if err := s.removeBlockFromQueue(b, blkRoot); err != nil { return err } - log.WithFields(logrus.Fields{"slot": slot, "blockRoot": hex.EncodeToString(bytesutil.Trunc(blkRoot[:]))}).Debug("Processed pending block and cleared it in cache") + + duration := time.Since(start) + totalDuration += duration + log.WithFields(logrus.Fields{ + "slotIndex": fmt.Sprintf("%d/%d", i+1, len(sortedSlots)), + "slot": slot, + "root": fmt.Sprintf("%#x", blkRoot), + "duration": duration, + "totalDuration": totalDuration, + }).Debug("Processed pending block and cleared it in cache") } + span.End() } + + for _, blkRoot := range blkRoots { + // Process pending attestations for this block. + if err := s.processPendingAttsForBlock(ctx, blkRoot); err != nil { + log.WithError(err).Debug("Failed to process pending attestations for block") + } + } + return s.sendBatchRootRequest(ctx, parentRoots, randGen) } @@ -379,6 +400,19 @@ func (s *Service) sendBatchRootRequest(ctx context.Context, roots [][32]byte, ra req = roots[:maxReqBlock] } + if logrus.GetLevel() >= logrus.DebugLevel { + rootsStr := make([]string, 0, len(roots)) + for _, req := range roots { + rootsStr = append(rootsStr, fmt.Sprintf("%#x", req)) + } + + log.WithFields(logrus.Fields{ + "peer": pid, + "count": len(req), + "roots": rootsStr, + }).Debug("Requesting blocks by root") + } + // Send the request to the peer. if err := s.sendBeaconBlocksRequest(ctx, &req, pid); err != nil { tracing.AnnotateError(span, err) @@ -438,8 +472,6 @@ func (s *Service) filterOutPendingAndSynced(roots [][fieldparams.RootLength]byte roots = append(roots[:i], roots[i+1:]...) continue } - - log.WithField("blockRoot", fmt.Sprintf("%#x", r)).Debug("Requesting block by root") } return roots } diff --git a/beacon-chain/sync/subscriber_beacon_blocks.go b/beacon-chain/sync/subscriber_beacon_blocks.go index 0425c5acdc..14798b2fc7 100644 --- a/beacon-chain/sync/subscriber_beacon_blocks.go +++ b/beacon-chain/sync/subscriber_beacon_blocks.go @@ -189,12 +189,30 @@ func (s *Service) processDataColumnSidecarsFromExecution(ctx context.Context, so ctx, cancel := context.WithTimeout(ctx, secondsPerHalfSlot) defer cancel() + log := log.WithFields(logrus.Fields{ + "root": fmt.Sprintf("%#x", source.Root()), + "slot": source.Slot(), + "proposerIndex": source.ProposerIndex(), + "type": source.Type(), + }) + + var constructedSidecarCount uint64 for iteration := uint64(0); ; /*no stop condition*/ iteration++ { + log = log.WithField("iteration", iteration) + // Exit early if all sidecars to sample have been seen. if s.haveAllSidecarsBeenSeen(source.Slot(), source.ProposerIndex(), columnIndicesToSample) { + if iteration > 0 && constructedSidecarCount == 0 { + log.Debug("No data column sidecars constructed from the execution client") + } + return nil, nil } + if iteration == 0 { + dataColumnsRecoveredFromELAttempts.Inc() + } + // Try to reconstruct data column constructedSidecars from the execution client. constructedSidecars, err := s.cfg.executionReconstructor.ConstructDataColumnSidecars(ctx, source) if err != nil { @@ -202,8 +220,8 @@ func (s *Service) processDataColumnSidecarsFromExecution(ctx context.Context, so } // No sidecars are retrieved from the EL, retry later - sidecarCount := uint64(len(constructedSidecars)) - if sidecarCount == 0 { + constructedSidecarCount = uint64(len(constructedSidecars)) + if constructedSidecarCount == 0 { if ctx.Err() != nil { return nil, ctx.Err() } @@ -212,9 +230,11 @@ func (s *Service) processDataColumnSidecarsFromExecution(ctx context.Context, so continue } + dataColumnsRecoveredFromELTotal.Inc() + // Boundary check. - if sidecarCount != fieldparams.NumberOfColumns { - return nil, errors.Errorf("reconstruct data column sidecars returned %d sidecars, expected %d - should never happen", sidecarCount, fieldparams.NumberOfColumns) + if constructedSidecarCount != fieldparams.NumberOfColumns { + return nil, errors.Errorf("reconstruct data column sidecars returned %d sidecars, expected %d - should never happen", constructedSidecarCount, fieldparams.NumberOfColumns) } unseenIndices, err := s.broadcastAndReceiveUnseenDataColumnSidecars(ctx, source.Slot(), source.ProposerIndex(), columnIndicesToSample, constructedSidecars) @@ -222,19 +242,12 @@ func (s *Service) processDataColumnSidecarsFromExecution(ctx context.Context, so return nil, errors.Wrap(err, "broadcast and receive unseen data column sidecars") } - if len(unseenIndices) > 0 { - dataColumnsRecoveredFromELTotal.Inc() + log.WithFields(logrus.Fields{ + "count": len(unseenIndices), + "indices": helpers.SortedPrettySliceFromMap(unseenIndices), + }).Debug("Constructed data column sidecars from the execution client") - log.WithFields(logrus.Fields{ - "root": fmt.Sprintf("%#x", source.Root()), - "slot": source.Slot(), - "proposerIndex": source.ProposerIndex(), - "iteration": iteration, - "type": source.Type(), - "count": len(unseenIndices), - "indices": helpers.SortedPrettySliceFromMap(unseenIndices), - }).Debug("Constructed data column sidecars from the execution client") - } + dataColumnSidecarsObtainedViaELCount.Observe(float64(len(unseenIndices))) return nil, nil } diff --git a/beacon-chain/sync/validate_data_column.go b/beacon-chain/sync/validate_data_column.go index 2e3695d009..b303a01598 100644 --- a/beacon-chain/sync/validate_data_column.go +++ b/beacon-chain/sync/validate_data_column.go @@ -3,11 +3,12 @@ package sync import ( "context" "fmt" - "math" + "slices" "time" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/feed" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/feed/operation" + "github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers" "github.com/OffchainLabs/prysm/v7/beacon-chain/p2p" "github.com/OffchainLabs/prysm/v7/beacon-chain/verification" fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams" @@ -51,14 +52,12 @@ func (s *Service) validateDataColumn(ctx context.Context, pid peer.ID, msg *pubs // Decode the message, reject if it fails. m, err := s.decodePubsubMessage(msg) if err != nil { - log.WithError(err).Error("Failed to decode message") return pubsub.ValidationReject, err } // Reject messages that are not of the expected type. dcsc, ok := m.(*eth.DataColumnSidecar) if !ok { - log.WithField("message", m).Error("Message is not of type *eth.DataColumnSidecar") return pubsub.ValidationReject, errWrongMessage } @@ -194,19 +193,13 @@ func (s *Service) validateDataColumn(ctx context.Context, pid peer.ID, msg *pubs dataColumnSidecarArrivalGossipSummary.Observe(float64(sinceSlotStartTime.Milliseconds())) dataColumnSidecarVerificationGossipHistogram.Observe(float64(validationTime.Milliseconds())) - peerGossipScore := s.cfg.p2p.Peers().Scorers().GossipScorer().Score(pid) - select { case s.dataColumnLogCh <- dataColumnLogEntry{ - Slot: roDataColumn.Slot(), - ColIdx: roDataColumn.Index, - PropIdx: roDataColumn.ProposerIndex(), - BlockRoot: roDataColumn.BlockRoot(), - ParentRoot: roDataColumn.ParentRoot(), - PeerSuffix: pid.String()[len(pid.String())-6:], - PeerGossipScore: peerGossipScore, - validationTime: validationTime, - sinceStartTime: sinceSlotStartTime, + slot: roDataColumn.Slot(), + index: roDataColumn.Index, + root: roDataColumn.BlockRoot(), + validationTime: validationTime, + sinceStartTime: sinceSlotStartTime, }: default: log.WithField("slot", roDataColumn.Slot()).Warn("Failed to send data column log entry") @@ -251,68 +244,69 @@ func computeCacheKey(slot primitives.Slot, proposerIndex primitives.ValidatorInd } type dataColumnLogEntry struct { - Slot primitives.Slot - ColIdx uint64 - PropIdx primitives.ValidatorIndex - BlockRoot [32]byte - ParentRoot [32]byte - PeerSuffix string - PeerGossipScore float64 - validationTime time.Duration - sinceStartTime time.Duration + slot primitives.Slot + index uint64 + root [32]byte + validationTime time.Duration + sinceStartTime time.Duration } func (s *Service) processDataColumnLogs() { ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - slotStats := make(map[primitives.Slot][fieldparams.NumberOfColumns]dataColumnLogEntry) + slotStats := make(map[[fieldparams.RootLength]byte][]dataColumnLogEntry) for { select { - case entry := <-s.dataColumnLogCh: - cols := slotStats[entry.Slot] - cols[entry.ColIdx] = entry - slotStats[entry.Slot] = cols + case col := <-s.dataColumnLogCh: + cols := slotStats[col.root] + cols = append(cols, col) + slotStats[col.root] = cols case <-ticker.C: - for slot, columns := range slotStats { - var ( - colIndices = make([]uint64, 0, fieldparams.NumberOfColumns) - peers = make([]string, 0, fieldparams.NumberOfColumns) - gossipScores = make([]float64, 0, fieldparams.NumberOfColumns) - validationTimes = make([]string, 0, fieldparams.NumberOfColumns) - sinceStartTimes = make([]string, 0, fieldparams.NumberOfColumns) - ) + for root, columns := range slotStats { + indices := make([]uint64, 0, fieldparams.NumberOfColumns) + minValidationTime, maxValidationTime, sumValidationTime := time.Duration(0), time.Duration(0), time.Duration(0) + minSinceStartTime, maxSinceStartTime, sumSinceStartTime := time.Duration(0), time.Duration(0), time.Duration(0) totalReceived := 0 - for _, entry := range columns { - if entry.PeerSuffix == "" { + for _, column := range columns { + indices = append(indices, column.index) + + sumValidationTime += column.validationTime + sumSinceStartTime += column.sinceStartTime + + if totalReceived == 0 { + minValidationTime, maxValidationTime = column.validationTime, column.validationTime + minSinceStartTime, maxSinceStartTime = column.sinceStartTime, column.sinceStartTime + totalReceived++ continue } - colIndices = append(colIndices, entry.ColIdx) - peers = append(peers, entry.PeerSuffix) - gossipScores = append(gossipScores, roundFloat(entry.PeerGossipScore, 2)) - validationTimes = append(validationTimes, fmt.Sprintf("%.2fms", float64(entry.validationTime.Milliseconds()))) - sinceStartTimes = append(sinceStartTimes, fmt.Sprintf("%.2fms", float64(entry.sinceStartTime.Milliseconds()))) + + minValidationTime, maxValidationTime = min(minValidationTime, column.validationTime), max(maxValidationTime, column.validationTime) + minSinceStartTime, maxSinceStartTime = min(minSinceStartTime, column.sinceStartTime), max(maxSinceStartTime, column.sinceStartTime) totalReceived++ } - log.WithFields(logrus.Fields{ - "slot": slot, - "receivedCount": totalReceived, - "columnIndices": colIndices, - "peers": peers, - "gossipScores": gossipScores, - "validationTimes": validationTimes, - "sinceStartTimes": sinceStartTimes, - }).Debug("Accepted data column sidecars summary") + if totalReceived > 0 { + slices.Sort(indices) + avgValidationTime := sumValidationTime / time.Duration(totalReceived) + avgSinceStartTime := sumSinceStartTime / time.Duration(totalReceived) + + log.WithFields(logrus.Fields{ + "slot": columns[0].slot, + "root": fmt.Sprintf("%#x", root), + "count": totalReceived, + "indices": helpers.PrettySlice(indices), + "validationTime": prettyMinMaxAverage(minValidationTime, maxValidationTime, avgValidationTime), + "sinceStartTime": prettyMinMaxAverage(minSinceStartTime, maxSinceStartTime, avgSinceStartTime), + }).Debug("Accepted data column sidecars summary") + } } - slotStats = make(map[primitives.Slot][fieldparams.NumberOfColumns]dataColumnLogEntry) + + slotStats = make(map[[fieldparams.RootLength]byte][]dataColumnLogEntry) } } } -func roundFloat(f float64, decimals int) float64 { - mult := math.Pow(10, float64(decimals)) - return math.Round(f*mult) / mult +func prettyMinMaxAverage(min, max, average time.Duration) string { + return fmt.Sprintf("[min: %v, avg: %v, max: %v]", min, average, max) } diff --git a/beacon-chain/sync/validate_light_client_test.go b/beacon-chain/sync/validate_light_client_test.go index c979ddff47..5607d91d65 100644 --- a/beacon-chain/sync/validate_light_client_test.go +++ b/beacon-chain/sync/validate_light_client_test.go @@ -54,11 +54,13 @@ func TestValidateLightClientOptimisticUpdate(t *testing.T) { cfg.CapellaForkEpoch = 3 cfg.DenebForkEpoch = 4 cfg.ElectraForkEpoch = 5 + cfg.FuluForkEpoch = 6 cfg.ForkVersionSchedule[[4]byte{1, 0, 0, 0}] = 1 cfg.ForkVersionSchedule[[4]byte{2, 0, 0, 0}] = 2 cfg.ForkVersionSchedule[[4]byte{3, 0, 0, 0}] = 3 cfg.ForkVersionSchedule[[4]byte{4, 0, 0, 0}] = 4 cfg.ForkVersionSchedule[[4]byte{5, 0, 0, 0}] = 5 + cfg.ForkVersionSchedule[[4]byte{6, 0, 0, 0}] = 6 params.OverrideBeaconConfig(cfg) secondsPerSlot := int(params.BeaconConfig().SecondsPerSlot) @@ -101,7 +103,10 @@ func TestValidateLightClientOptimisticUpdate(t *testing.T) { } for _, test := range tests { - for v := 1; v < 6; v++ { + for v := range version.All() { + if v == version.Phase0 { + continue + } t.Run(test.name+"_"+version.String(v), func(t *testing.T) { ctx := t.Context() p := p2ptest.NewTestP2P(t) @@ -180,11 +185,13 @@ func TestValidateLightClientFinalityUpdate(t *testing.T) { cfg.CapellaForkEpoch = 3 cfg.DenebForkEpoch = 4 cfg.ElectraForkEpoch = 5 + cfg.FuluForkEpoch = 6 cfg.ForkVersionSchedule[[4]byte{1, 0, 0, 0}] = 1 cfg.ForkVersionSchedule[[4]byte{2, 0, 0, 0}] = 2 cfg.ForkVersionSchedule[[4]byte{3, 0, 0, 0}] = 3 cfg.ForkVersionSchedule[[4]byte{4, 0, 0, 0}] = 4 cfg.ForkVersionSchedule[[4]byte{5, 0, 0, 0}] = 5 + cfg.ForkVersionSchedule[[4]byte{6, 0, 0, 0}] = 6 params.OverrideBeaconConfig(cfg) secondsPerSlot := int(params.BeaconConfig().SecondsPerSlot) @@ -227,7 +234,10 @@ func TestValidateLightClientFinalityUpdate(t *testing.T) { } for _, test := range tests { - for v := 1; v < 6; v++ { + for v := range version.All() { + if v == version.Phase0 { + continue + } t.Run(test.name+"_"+version.String(v), func(t *testing.T) { ctx := t.Context() p := p2ptest.NewTestP2P(t) diff --git a/beacon-chain/verification/blob_test.go b/beacon-chain/verification/blob_test.go index 441dda9a54..d73919568b 100644 --- a/beacon-chain/verification/blob_test.go +++ b/beacon-chain/verification/blob_test.go @@ -687,6 +687,12 @@ func sbrNotFound(t *testing.T, expectedRoot [32]byte) *mockStateByRooter { }} } +func sbrReturnsState(st state.BeaconState) *mockStateByRooter { + return &mockStateByRooter{sbr: func(_ context.Context, _ [32]byte) (state.BeaconState, error) { + return st, nil + }} +} + func sbrForValOverride(idx primitives.ValidatorIndex, val *ethpb.Validator) *mockStateByRooter { return sbrForValOverrideWithT(nil, idx, val) } diff --git a/beacon-chain/verification/data_column.go b/beacon-chain/verification/data_column.go index 9d350b4fc0..de0f8a33bd 100644 --- a/beacon-chain/verification/data_column.go +++ b/beacon-chain/verification/data_column.go @@ -11,12 +11,10 @@ import ( "github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/peerdas" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/transition" - forkchoicetypes "github.com/OffchainLabs/prysm/v7/beacon-chain/forkchoice/types" "github.com/OffchainLabs/prysm/v7/beacon-chain/state" fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams" "github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/consensus-types/blocks" - "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" "github.com/OffchainLabs/prysm/v7/runtime/logging" "github.com/OffchainLabs/prysm/v7/time/slots" @@ -361,7 +359,7 @@ func (dv *RODataColumnsVerifier) SidecarParentSeen(parentSeen func([fieldparams. } if !dv.fc.HasNode(parentRoot) { - return columnErrBuilder(errSidecarParentNotSeen) + return columnErrBuilder(errors.Wrapf(errSidecarParentNotSeen, "parent root: %#x", parentRoot)) } } @@ -484,88 +482,19 @@ func (dv *RODataColumnsVerifier) SidecarProposerExpected(ctx context.Context) (e defer dv.recordResult(RequireSidecarProposerExpected, &err) - type slotParentRoot struct { - slot primitives.Slot - parentRoot [fieldparams.RootLength]byte - } - - targetRootBySlotParentRoot := make(map[slotParentRoot][fieldparams.RootLength]byte) - - var targetRootFromCache = func(slot primitives.Slot, parentRoot [fieldparams.RootLength]byte) ([fieldparams.RootLength]byte, error) { - // Use cached values if available. - slotParentRoot := slotParentRoot{slot: slot, parentRoot: parentRoot} - if root, ok := targetRootBySlotParentRoot[slotParentRoot]; ok { - return root, nil - } - - // Compute the epoch of the data column slot. - dataColumnEpoch := slots.ToEpoch(slot) - if dataColumnEpoch > 0 { - dataColumnEpoch = dataColumnEpoch - 1 - } - - // Compute the target root for the epoch. - targetRoot, err := dv.fc.TargetRootForEpoch(parentRoot, dataColumnEpoch) - if err != nil { - return [fieldparams.RootLength]byte{}, columnErrBuilder(errors.Wrap(err, "target root from epoch")) - } - - // Store the target root in the cache. - targetRootBySlotParentRoot[slotParentRoot] = targetRoot - - return targetRoot, nil - } - for _, dataColumn := range dv.dataColumns { - // Extract the slot of the data column. dataColumnSlot := dataColumn.Slot() - // Extract the root of the parent block corresponding to the data column. - parentRoot := dataColumn.ParentRoot() - - // Compute the target root for the data column. - targetRoot, err := targetRootFromCache(dataColumnSlot, parentRoot) + // Get the verifying state, it is guaranteed to have the correct proposer in the lookahead. + verifyingState, err := dv.getVerifyingState(ctx, dataColumn) if err != nil { - return columnErrBuilder(errors.Wrap(err, "target root")) + return columnErrBuilder(errors.Wrap(err, "verifying state")) } - // Compute the epoch of the data column slot. - dataColumnEpoch := slots.ToEpoch(dataColumnSlot) - if dataColumnEpoch > 0 { - dataColumnEpoch = dataColumnEpoch - 1 - } - - // Create a checkpoint for the target root. - checkpoint := &forkchoicetypes.Checkpoint{Root: targetRoot, Epoch: dataColumnEpoch} - - // Try to extract the proposer index from the data column in the cache. - idx, cached := dv.pc.Proposer(checkpoint, dataColumnSlot) - - if !cached { - parentRoot := dataColumn.ParentRoot() - // Ensure the expensive index computation is only performed once for - // concurrent requests for the same signature data. - idxAny, err, _ := dv.sg.Do(concatRootSlot(parentRoot, dataColumnSlot), func() (any, error) { - verifyingState, err := dv.getVerifyingState(ctx, dataColumn) - if err != nil { - return nil, columnErrBuilder(errors.Wrap(err, "verifying state")) - } - - idx, err = helpers.BeaconProposerIndexAtSlot(ctx, verifyingState, dataColumnSlot) - if err != nil { - return nil, columnErrBuilder(errors.Wrap(err, "compute proposer")) - } - - return idx, nil - }) - if err != nil { - return err - } - - var ok bool - if idx, ok = idxAny.(primitives.ValidatorIndex); !ok { - return columnErrBuilder(errors.New("type assertion to ValidatorIndex failed")) - } + // Use proposer lookahead directly + idx, err := helpers.BeaconProposerIndexAtSlot(ctx, verifyingState, dataColumnSlot) + if err != nil { + return columnErrBuilder(errors.Wrap(err, "proposer from lookahead")) } if idx != dataColumn.ProposerIndex() { @@ -626,7 +555,3 @@ func inclusionProofKey(c blocks.RODataColumn) ([32]byte, error) { return sha256.Sum256(unhashedKey), nil } - -func concatRootSlot(root [fieldparams.RootLength]byte, slot primitives.Slot) string { - return string(root[:]) + fmt.Sprintf("%d", slot) -} diff --git a/beacon-chain/verification/data_column_test.go b/beacon-chain/verification/data_column_test.go index ab943520c9..05f1f72adf 100644 --- a/beacon-chain/verification/data_column_test.go +++ b/beacon-chain/verification/data_column_test.go @@ -2,7 +2,6 @@ package verification import ( "reflect" - "sync" "testing" "time" @@ -795,87 +794,90 @@ func TestDataColumnsSidecarProposerExpected(t *testing.T) { blobCount = 1 ) - parentRoot := [fieldparams.RootLength]byte{} - columns := GenerateTestDataColumns(t, parentRoot, columnSlot, blobCount) - firstColumn := columns[0] ctx := t.Context() - testCases := []struct { - name string - stateByRooter StateByRooter - proposerCache proposerCache - columns []blocks.RODataColumn - error string - }{ - { - name: "Cached, matches", - stateByRooter: nil, - proposerCache: &mockProposerCache{ - ProposerCB: pcReturnsIdx(firstColumn.ProposerIndex()), - }, - columns: columns, - }, - { - name: "Cached, does not match", - stateByRooter: nil, - proposerCache: &mockProposerCache{ - ProposerCB: pcReturnsIdx(firstColumn.ProposerIndex() + 1), - }, - columns: columns, - error: errSidecarUnexpectedProposer.Error(), - }, - { - name: "Not cached, state lookup failure", - stateByRooter: sbrNotFound(t, firstColumn.ParentRoot()), - proposerCache: &mockProposerCache{ - ProposerCB: pcReturnsNotFound(), - }, - columns: columns, - error: "verifying state", - }, - } + parentRoot := [fieldparams.RootLength]byte{} - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - initializer := Initializer{ - shared: &sharedResources{ - sr: tc.stateByRooter, - pc: tc.proposerCache, - hsp: &mockHeadStateProvider{}, - fc: &mockForkchoicer{ - TargetRootForEpochCB: fcReturnsTargetRoot([fieldparams.RootLength]byte{}), - }, + // Create a Fulu state to get the expected proposer from the lookahead. + fuluState, _ := util.DeterministicGenesisStateFulu(t, 32) + expectedProposer, err := fuluState.ProposerLookahead() + require.NoError(t, err) + expectedProposerIdx := primitives.ValidatorIndex(expectedProposer[columnSlot]) + + // Generate data columns with the expected proposer index. + matchingColumns := generateTestDataColumnsWithProposer(t, parentRoot, columnSlot, blobCount, expectedProposerIdx) + // Generate data columns with wrong proposer index. + wrongColumns := generateTestDataColumnsWithProposer(t, parentRoot, columnSlot, blobCount, expectedProposerIdx+1) + + t.Run("Proposer matches", func(t *testing.T) { + initializer := Initializer{ + shared: &sharedResources{ + sr: sbrReturnsState(fuluState), + hsp: &mockHeadStateProvider{ + headRoot: parentRoot[:], + headSlot: columnSlot, // Same epoch so HeadStateReadOnly is used + headStateReadOnly: fuluState, }, - } + fc: &mockForkchoicer{}, + }, + } - verifier := initializer.NewDataColumnsVerifier(tc.columns, GossipDataColumnSidecarRequirements) - var wg sync.WaitGroup + verifier := initializer.NewDataColumnsVerifier(matchingColumns, GossipDataColumnSidecarRequirements) + err := verifier.SidecarProposerExpected(ctx) + require.NoError(t, err) + require.Equal(t, true, verifier.results.executed(RequireSidecarProposerExpected)) + require.NoError(t, verifier.results.result(RequireSidecarProposerExpected)) + }) - var err1, err2 error - wg.Go(func() { - err1 = verifier.SidecarProposerExpected(ctx) - }) - wg.Go(func() { - err2 = verifier.SidecarProposerExpected(ctx) - }) - wg.Wait() + t.Run("Proposer does not match", func(t *testing.T) { + initializer := Initializer{ + shared: &sharedResources{ + sr: sbrReturnsState(fuluState), + hsp: &mockHeadStateProvider{ + headRoot: parentRoot[:], + headSlot: columnSlot, // Same epoch so HeadStateReadOnly is used + headStateReadOnly: fuluState, + }, + fc: &mockForkchoicer{}, + }, + } - require.Equal(t, true, verifier.results.executed(RequireSidecarProposerExpected)) + verifier := initializer.NewDataColumnsVerifier(wrongColumns, GossipDataColumnSidecarRequirements) + err := verifier.SidecarProposerExpected(ctx) + require.ErrorContains(t, errSidecarUnexpectedProposer.Error(), err) + require.Equal(t, true, verifier.results.executed(RequireSidecarProposerExpected)) + require.NotNil(t, verifier.results.result(RequireSidecarProposerExpected)) + }) - if len(tc.error) > 0 { - require.ErrorContains(t, tc.error, err1) - require.ErrorContains(t, tc.error, err2) - require.NotNil(t, verifier.results.result(RequireSidecarProposerExpected)) - return - } + t.Run("State lookup failure", func(t *testing.T) { + columns := GenerateTestDataColumns(t, parentRoot, columnSlot, blobCount) + initializer := Initializer{ + shared: &sharedResources{ + sr: sbrNotFound(t, columns[0].ParentRoot()), + hsp: &mockHeadStateProvider{}, + fc: &mockForkchoicer{}, + }, + } - require.NoError(t, err1) - require.NoError(t, err2) - require.NoError(t, verifier.results.result(RequireSidecarProposerExpected)) + verifier := initializer.NewDataColumnsVerifier(columns, GossipDataColumnSidecarRequirements) + err := verifier.SidecarProposerExpected(ctx) + require.ErrorContains(t, "verifying state", err) + require.Equal(t, true, verifier.results.executed(RequireSidecarProposerExpected)) + require.NotNil(t, verifier.results.result(RequireSidecarProposerExpected)) + }) +} - err := verifier.SidecarProposerExpected(ctx) - require.NoError(t, err) - }) +func generateTestDataColumnsWithProposer(t *testing.T, parent [fieldparams.RootLength]byte, slot primitives.Slot, blobCount int, proposer primitives.ValidatorIndex) []blocks.RODataColumn { + roBlock, roBlobs := util.GenerateTestDenebBlockWithSidecar(t, parent, slot, blobCount, util.WithProposer(proposer)) + blobs := make([]kzg.Blob, 0, len(roBlobs)) + for i := range roBlobs { + blobs = append(blobs, kzg.Blob(roBlobs[i].Blob)) } + + cellsPerBlob, proofsPerBlob := util.GenerateCellsAndProofs(t, blobs) + roDataColumnSidecars, err := peerdas.DataColumnSidecars(cellsPerBlob, proofsPerBlob, peerdas.PopulateFromBlock(roBlock)) + require.NoError(t, err) + + return roDataColumnSidecars } func TestColumnRequirementSatisfaction(t *testing.T) { @@ -922,12 +924,3 @@ func TestColumnRequirementSatisfaction(t *testing.T) { require.NoError(t, err) } -func TestConcatRootSlot(t *testing.T) { - root := [fieldparams.RootLength]byte{1, 2, 3} - const slot = primitives.Slot(3210) - - const expected = "\x01\x02\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003210" - - actual := concatRootSlot(root, slot) - require.Equal(t, expected, actual) -} diff --git a/beacon-chain/verification/log.go b/beacon-chain/verification/log.go index d49834803f..d9d7ae0327 100644 --- a/beacon-chain/verification/log.go +++ b/beacon-chain/verification/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package verification import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "verification") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "beacon-chain/verification") diff --git a/changelog/avoid_kzg_send_after_context_cancel.md b/changelog/avoid_kzg_send_after_context_cancel.md new file mode 100644 index 0000000000..ac5d5549e5 --- /dev/null +++ b/changelog/avoid_kzg_send_after_context_cancel.md @@ -0,0 +1,3 @@ +### Fixed + +- Prevent blocked sends to the KZG batch verifier when the caller context is already canceled, avoiding useless queueing and potential hangs. diff --git a/changelog/bastin_fix-lcp2p-bug.md b/changelog/bastin_fix-lcp2p-bug.md new file mode 100644 index 0000000000..2278b78c9a --- /dev/null +++ b/changelog/bastin_fix-lcp2p-bug.md @@ -0,0 +1,3 @@ +### Fixed + +- Fix the missing fork version object mapping for Fulu in light client p2p. \ No newline at end of file diff --git a/changelog/bastin_logrus-hooks-add.md b/changelog/bastin_logrus-hooks-add.md new file mode 100644 index 0000000000..4bc52321af --- /dev/null +++ b/changelog/bastin_logrus-hooks-add.md @@ -0,0 +1,4 @@ +### Added + +- Added separate logrus hooks for handling the formatting and output of terminal logs vs log-file logs, instead of the + default logrus output. \ No newline at end of file diff --git a/changelog/bastin_switch-logging-to-packaga-path.md b/changelog/bastin_switch-logging-to-packaga-path.md new file mode 100644 index 0000000000..c148c4b2b6 --- /dev/null +++ b/changelog/bastin_switch-logging-to-packaga-path.md @@ -0,0 +1,6 @@ +### Changed + +- Added a log.go file for every important package with a logger variable containing a `package` field set to the package + path. +- Added a CI check to ensure every important package has a log.go file with the correct `package` field. +- Changed the log formatter to use this `package` field instead of the previous `prefix` field. \ No newline at end of file diff --git a/changelog/builder-index.md b/changelog/builder-index.md new file mode 100644 index 0000000000..32dfa896a3 --- /dev/null +++ b/changelog/builder-index.md @@ -0,0 +1,3 @@ +### Added + +- `primitives.BuilderIndex`: SSZ `uint64` wrapper for builder registry indices. \ No newline at end of file diff --git a/changelog/james-prysm_align-atter-pool-apis.md b/changelog/james-prysm_align-atter-pool-apis.md new file mode 100644 index 0000000000..53de89b44b --- /dev/null +++ b/changelog/james-prysm_align-atter-pool-apis.md @@ -0,0 +1,3 @@ +### Changed + +- the /eth/v2/beacon/pool/attestations and /eth/v1/beacon/pool/sync_committees now returns a 503 error if the node is still syncing, the rest api is also working in a similar process to gRPC broadcasting immediately now. \ No newline at end of file diff --git a/changelog/james-prysm_skip-e2e-slot1-check.md b/changelog/james-prysm_skip-e2e-slot1-check.md new file mode 100644 index 0000000000..c40b16a7dc --- /dev/null +++ b/changelog/james-prysm_skip-e2e-slot1-check.md @@ -0,0 +1,3 @@ +### Changed + +- e2e sync committee evaluator now skips the first slot after startup, we already skip the fork epoch for checks here, this skip only applies on startup, due to altair always from 0 and validators need to warm up. \ No newline at end of file diff --git a/changelog/kasey_fix-backfill-flag.md b/changelog/kasey_fix-backfill-flag.md new file mode 100644 index 0000000000..4cb4e74216 --- /dev/null +++ b/changelog/kasey_fix-backfill-flag.md @@ -0,0 +1,2 @@ +#### Fixed +- Fix validation logic for `--backfill-oldest-slot`, which was rejecting slots newer than 1056767. diff --git a/changelog/manu-agg.md b/changelog/manu-agg.md new file mode 100644 index 0000000000..131dd2c895 --- /dev/null +++ b/changelog/manu-agg.md @@ -0,0 +1,3 @@ +### Changed + +- Pending aggregates: When multiple aggregated attestations only differing by the aggregator index are in the pending queue, only process one of them. \ No newline at end of file diff --git a/changelog/manu-cache-warmup.md b/changelog/manu-cache-warmup.md new file mode 100644 index 0000000000..c6cbfdb40a --- /dev/null +++ b/changelog/manu-cache-warmup.md @@ -0,0 +1,3 @@ +### Changed + +- Data column sidecars cache warmup: Process in parallel all sidecars for a given epoch. \ No newline at end of file diff --git a/changelog/manu-log.md b/changelog/manu-log.md new file mode 100644 index 0000000000..6ab27fdaaf --- /dev/null +++ b/changelog/manu-log.md @@ -0,0 +1,3 @@ +### Changed + +- Summarize DEBUG log corresponding to incoming via gossip data column sidecar. \ No newline at end of file diff --git a/changelog/manu-remove-error-logs.md b/changelog/manu-remove-error-logs.md new file mode 100644 index 0000000000..d9a2dc25c9 --- /dev/null +++ b/changelog/manu-remove-error-logs.md @@ -0,0 +1,2 @@ +### Changed +- `validateDataColumn`: Remove error logs. \ No newline at end of file diff --git a/changelog/manu_reconstruct-metrics.md b/changelog/manu_reconstruct-metrics.md new file mode 100644 index 0000000000..d061e29284 --- /dev/null +++ b/changelog/manu_reconstruct-metrics.md @@ -0,0 +1,7 @@ +### Added +- prometheus histogram `cells_and_proofs_from_structured_computation_milliseconds` to track computation time for cells and proofs from structured blobs. +- prometheus histogram `get_blobs_v2_latency_milliseconds` to track RPC latency for `getBlobsV2` calls to the execution layer. + +### Changed +- Run `ComputeCellsAndProofsFromFlat` in parallel to improve performance when computing cells and proofs. +- Run `ComputeCellsAndProofsFromStructured` in parallel to improve performance when computing cells and proofs. diff --git a/changelog/potuz_dcs_pc_removal.md b/changelog/potuz_dcs_pc_removal.md new file mode 100644 index 0000000000..96fd9b8864 --- /dev/null +++ b/changelog/potuz_dcs_pc_removal.md @@ -0,0 +1,2 @@ +### Changed +- Use lookahead to validate data column sidecar proposer index. diff --git a/changelog/potuz_dont_lock_fcu.md b/changelog/potuz_dont_lock_fcu.md new file mode 100644 index 0000000000..8b3303bb31 --- /dev/null +++ b/changelog/potuz_dont_lock_fcu.md @@ -0,0 +1,3 @@ +### Changed + +- Notify the engine about forkchoice updates in the background. diff --git a/changelog/potuz_fcu_ctx.md b/changelog/potuz_fcu_ctx.md new file mode 100644 index 0000000000..a6fbf66f26 --- /dev/null +++ b/changelog/potuz_fcu_ctx.md @@ -0,0 +1,2 @@ +### Changed +- Use a separate context when updating the slot cache. diff --git a/changelog/potuz_next_epoch_attributes.md b/changelog/potuz_next_epoch_attributes.md new file mode 100644 index 0000000000..83862eb391 --- /dev/null +++ b/changelog/potuz_next_epoch_attributes.md @@ -0,0 +1,3 @@ +### Fixed + +- Do not process slots and copy states for next epoch proposers after Fulu diff --git a/changelog/potuz_no_fcu_on_batches.md b/changelog/potuz_no_fcu_on_batches.md new file mode 100644 index 0000000000..3eac4a81a7 --- /dev/null +++ b/changelog/potuz_no_fcu_on_batches.md @@ -0,0 +1,2 @@ +### Ignored +- D not send FCU on block batches. diff --git a/changelog/potuz_remove_signature_check.md b/changelog/potuz_remove_signature_check.md new file mode 100644 index 0000000000..32a7dcf004 --- /dev/null +++ b/changelog/potuz_remove_signature_check.md @@ -0,0 +1,3 @@ +### Changed + +- Do not check block signature on state transition. \ No newline at end of file diff --git a/changelog/potuz_use_head_previous_epoch.md b/changelog/potuz_use_head_previous_epoch.md new file mode 100644 index 0000000000..278c652d3b --- /dev/null +++ b/changelog/potuz_use_head_previous_epoch.md @@ -0,0 +1,3 @@ +### Added + +- Use the head state to validate attestations for the previous epoch if head is compatible with the target checkpoint. diff --git a/changelog/radek_extend-http-analyzer.md b/changelog/radek_extend-http-analyzer.md new file mode 100644 index 0000000000..adc823d4ac --- /dev/null +++ b/changelog/radek_extend-http-analyzer.md @@ -0,0 +1,3 @@ +### Changed + +- Extend `httperror` analyzer to more functions. \ No newline at end of file diff --git a/changelog/sashass1315_fix-panic.md b/changelog/sashass1315_fix-panic.md new file mode 100644 index 0000000000..d3b2771869 --- /dev/null +++ b/changelog/sashass1315_fix-panic.md @@ -0,0 +1,3 @@ +### Fixed + +- avoid panic when fork schedule is empty [#16175](https://github.com/OffchainLabs/prysm/pull/16175) diff --git a/changelog/satushh-consolidation.md b/changelog/satushh-consolidation.md new file mode 100644 index 0000000000..a8f0d3e4b8 --- /dev/null +++ b/changelog/satushh-consolidation.md @@ -0,0 +1,3 @@ +### Changed + +- Performance improvement in ProcessConsolidationRequests: Use more performance HasPendingBalanceToWithdraw instead of PendingBalanceToWithdraw as no need to calculate full total pending balance. \ No newline at end of file diff --git a/cmd/beacon-chain/main.go b/cmd/beacon-chain/main.go index df25adde48..d11489ed84 100644 --- a/cmd/beacon-chain/main.go +++ b/cmd/beacon-chain/main.go @@ -4,6 +4,7 @@ package main import ( "context" "fmt" + "io" "os" "path/filepath" runtimeDebug "runtime/debug" @@ -172,14 +173,20 @@ func before(ctx *cli.Context) error { switch format { case "text": + // disabling logrus default output so we can control it via different hooks + logrus.SetOutput(io.Discard) + + // create a custom formatter and hook for terminal output formatter := new(prefixed.TextFormatter) formatter.TimestampFormat = "2006-01-02 15:04:05.00" formatter.FullTimestamp = true + formatter.ForceFormatting = true + formatter.ForceColors = true - // If persistent log files are written - we disable the log messages coloring because - // the colors are ANSI codes and seen as gibberish in the log files. - formatter.DisableColors = ctx.String(cmd.LogFileName.Name) != "" - logrus.SetFormatter(formatter) + logrus.AddHook(&logs.WriterHook{ + Formatter: formatter, + Writer: os.Stderr, + }) case "fluentd": f := joonix.NewFormatter() @@ -202,7 +209,7 @@ func before(ctx *cli.Context) error { logFileName := ctx.String(cmd.LogFileName.Name) if logFileName != "" { - if err := logs.ConfigurePersistentLogging(logFileName); err != nil { + if err := logs.ConfigurePersistentLogging(logFileName, format); err != nil { log.WithError(err).Error("Failed to configuring logging to disk.") } } diff --git a/cmd/client-stats/main.go b/cmd/client-stats/main.go index 4c5b582ff6..4b749c9f1e 100644 --- a/cmd/client-stats/main.go +++ b/cmd/client-stats/main.go @@ -86,7 +86,7 @@ func main() { logFileName := ctx.String(cmd.LogFileName.Name) if logFileName != "" { - if err := logs.ConfigurePersistentLogging(logFileName); err != nil { + if err := logs.ConfigurePersistentLogging(logFileName, format); err != nil { log.WithError(err).Error("Failed to configuring logging to disk.") } } diff --git a/cmd/validator/main.go b/cmd/validator/main.go index 284df48efd..35f61d7cc3 100644 --- a/cmd/validator/main.go +++ b/cmd/validator/main.go @@ -5,6 +5,7 @@ package main import ( "fmt" + "io" "os" "path/filepath" runtimeDebug "runtime/debug" @@ -151,13 +152,20 @@ func main() { format := ctx.String(cmd.LogFormat.Name) switch format { case "text": + // disabling logrus default output so we can control it via different hooks + logrus.SetOutput(io.Discard) + + // create a custom formatter and hook for terminal output formatter := new(prefixed.TextFormatter) formatter.TimestampFormat = "2006-01-02 15:04:05.00" formatter.FullTimestamp = true - // If persistent log files are written - we disable the log messages coloring because - // the colors are ANSI codes and seen as gibberish in the log files. - formatter.DisableColors = logFileName != "" - logrus.SetFormatter(formatter) + formatter.ForceFormatting = true + formatter.ForceColors = true + + logrus.AddHook(&logs.WriterHook{ + Formatter: formatter, + Writer: os.Stderr, + }) case "fluentd": f := joonix.NewFormatter() if err := joonix.DisableTimestampFormat(f); err != nil { @@ -177,7 +185,7 @@ func main() { } if logFileName != "" { - if err := logs.ConfigurePersistentLogging(logFileName); err != nil { + if err := logs.ConfigurePersistentLogging(logFileName, format); err != nil { log.WithError(err).Error("Failed to configuring logging to disk.") } } diff --git a/config/BUILD.bazel b/config/BUILD.bazel index e2baca572f..c8bfdb7e2c 100644 --- a/config/BUILD.bazel +++ b/config/BUILD.bazel @@ -16,7 +16,10 @@ config_setting( go_library( name = "go_default_library", - srcs = ["util.go"], + srcs = [ + "log.go", + "util.go", + ], importpath = "github.com/OffchainLabs/prysm/v7/config", visibility = ["//visibility:public"], deps = [ diff --git a/config/features/BUILD.bazel b/config/features/BUILD.bazel index 93a4d9dbc7..4fe901ebfc 100644 --- a/config/features/BUILD.bazel +++ b/config/features/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "deprecated_flags.go", "filter_flags.go", "flags.go", + "log.go", ], importpath = "github.com/OffchainLabs/prysm/v7/config/features", visibility = ["//visibility:public"], diff --git a/config/features/config.go b/config/features/config.go index bae484dc29..d16da9cee3 100644 --- a/config/features/config.go +++ b/config/features/config.go @@ -28,12 +28,9 @@ import ( "github.com/OffchainLabs/prysm/v7/cmd" "github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" - "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) -var log = logrus.WithField("prefix", "flags") - const enabledFeatureFlag = "Enabled feature flag" const disabledFeatureFlag = "Disabled feature flag" diff --git a/config/features/log.go b/config/features/log.go new file mode 100644 index 0000000000..a5f25ffa8a --- /dev/null +++ b/config/features/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package features + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "config/features") diff --git a/config/log.go b/config/log.go new file mode 100644 index 0000000000..7c615b8800 --- /dev/null +++ b/config/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package config + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "config") diff --git a/config/params/log.go b/config/params/log.go index 355f415c38..56323bd19c 100644 --- a/config/params/log.go +++ b/config/params/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package params import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "params") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "config/params") diff --git a/config/proposer/loader/BUILD.bazel b/config/proposer/loader/BUILD.bazel index ef18044bba..d694155637 100644 --- a/config/proposer/loader/BUILD.bazel +++ b/config/proposer/loader/BUILD.bazel @@ -26,7 +26,10 @@ go_test( go_library( name = "go_default_library", - srcs = ["loader.go"], + srcs = [ + "loader.go", + "log.go", + ], importpath = "github.com/OffchainLabs/prysm/v7/config/proposer/loader", visibility = ["//visibility:public"], deps = [ diff --git a/config/proposer/loader/loader.go b/config/proposer/loader/loader.go index bb5d015fb4..96c94d08d9 100644 --- a/config/proposer/loader/loader.go +++ b/config/proposer/loader/loader.go @@ -14,7 +14,6 @@ import ( "github.com/OffchainLabs/prysm/v7/validator/db/iface" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) diff --git a/config/proposer/loader/log.go b/config/proposer/loader/log.go new file mode 100644 index 0000000000..52be1f26fb --- /dev/null +++ b/config/proposer/loader/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package loader + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "config/proposer/loader") diff --git a/config/util.go b/config/util.go index 54eb90d16a..3781f26235 100644 --- a/config/util.go +++ b/config/util.go @@ -12,7 +12,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/yaml" ) diff --git a/consensus-types/hdiff/BUILD.bazel b/consensus-types/hdiff/BUILD.bazel index da7b3201eb..cb5babad0d 100644 --- a/consensus-types/hdiff/BUILD.bazel +++ b/consensus-types/hdiff/BUILD.bazel @@ -2,7 +2,10 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = ["state_diff.go"], + srcs = [ + "log.go", + "state_diff.go", + ], importpath = "github.com/OffchainLabs/prysm/v7/consensus-types/hdiff", visibility = ["//visibility:public"], deps = [ diff --git a/consensus-types/hdiff/log.go b/consensus-types/hdiff/log.go new file mode 100644 index 0000000000..de91eb3c15 --- /dev/null +++ b/consensus-types/hdiff/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package hdiff + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "consensus-types/hdiff") diff --git a/consensus-types/primitives/BUILD.bazel b/consensus-types/primitives/BUILD.bazel index 295326cc2f..8a8a7089f1 100644 --- a/consensus-types/primitives/BUILD.bazel +++ b/consensus-types/primitives/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "basis_points.go", + "builder_index.go", "committee_bits_mainnet.go", "committee_bits_minimal.go", # keep "committee_index.go", @@ -31,6 +32,7 @@ go_library( go_test( name = "go_default_test", srcs = [ + "builder_index_test.go", "committee_index_test.go", "domain_test.go", "epoch_test.go", diff --git a/consensus-types/primitives/builder_index.go b/consensus-types/primitives/builder_index.go new file mode 100644 index 0000000000..4685838a10 --- /dev/null +++ b/consensus-types/primitives/builder_index.go @@ -0,0 +1,54 @@ +package primitives + +import ( + "fmt" + + fssz "github.com/prysmaticlabs/fastssz" +) + +var _ fssz.HashRoot = (BuilderIndex)(0) +var _ fssz.Marshaler = (*BuilderIndex)(nil) +var _ fssz.Unmarshaler = (*BuilderIndex)(nil) + +// BuilderIndex is an index into the builder registry. +type BuilderIndex uint64 + +// HashTreeRoot returns the SSZ hash tree root of the index. +func (b BuilderIndex) HashTreeRoot() ([32]byte, error) { + return fssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith appends the SSZ uint64 representation of the index to the given hasher. +func (b BuilderIndex) HashTreeRootWith(hh *fssz.Hasher) error { + hh.PutUint64(uint64(b)) + return nil +} + +// UnmarshalSSZ decodes the SSZ-encoded uint64 index from buf. +func (b *BuilderIndex) UnmarshalSSZ(buf []byte) error { + if len(buf) != b.SizeSSZ() { + return fmt.Errorf("expected buffer of length %d received %d", b.SizeSSZ(), len(buf)) + } + *b = BuilderIndex(fssz.UnmarshallUint64(buf)) + return nil +} + +// MarshalSSZTo appends the SSZ-encoded index to dst and returns the extended buffer. +func (b *BuilderIndex) MarshalSSZTo(dst []byte) ([]byte, error) { + marshalled, err := b.MarshalSSZ() + if err != nil { + return nil, err + } + return append(dst, marshalled...), nil +} + +// MarshalSSZ encodes the index as an SSZ uint64. +func (b *BuilderIndex) MarshalSSZ() ([]byte, error) { + marshalled := fssz.MarshalUint64([]byte{}, uint64(*b)) + return marshalled, nil +} + +// SizeSSZ returns the size of the SSZ-encoded index in bytes. +func (b *BuilderIndex) SizeSSZ() int { + return 8 +} diff --git a/consensus-types/primitives/builder_index_test.go b/consensus-types/primitives/builder_index_test.go new file mode 100644 index 0000000000..c2a67a38a3 --- /dev/null +++ b/consensus-types/primitives/builder_index_test.go @@ -0,0 +1,86 @@ +package primitives_test + +import ( + "encoding/binary" + "slices" + "strconv" + "testing" + + "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" + "github.com/OffchainLabs/prysm/v7/testing/require" +) + +func TestBuilderIndex_SSZRoundTripAndHashRoot(t *testing.T) { + cases := []uint64{ + 0, + 1, + 42, + (1 << 32) - 1, + 1 << 32, + ^uint64(0), + } + + for _, v := range cases { + t.Run("v="+u64name(v), func(t *testing.T) { + t.Parallel() + + val := primitives.BuilderIndex(v) + require.Equal(t, 8, (&val).SizeSSZ()) + + enc, err := (&val).MarshalSSZ() + require.NoError(t, err) + require.Equal(t, 8, len(enc)) + + wantEnc := make([]byte, 8) + binary.LittleEndian.PutUint64(wantEnc, v) + require.DeepEqual(t, wantEnc, enc) + + dstPrefix := []byte("prefix:") + dst, err := (&val).MarshalSSZTo(slices.Clone(dstPrefix)) + require.NoError(t, err) + wantDst := append(dstPrefix, wantEnc...) + require.DeepEqual(t, wantDst, dst) + + var decoded primitives.BuilderIndex + require.NoError(t, (&decoded).UnmarshalSSZ(enc)) + require.Equal(t, val, decoded) + + root, err := val.HashTreeRoot() + require.NoError(t, err) + + var wantRoot [32]byte + binary.LittleEndian.PutUint64(wantRoot[:8], v) + require.Equal(t, wantRoot, root) + }) + } +} + +func TestBuilderIndex_UnmarshalSSZRejectsWrongSize(t *testing.T) { + for _, size := range []int{7, 9} { + t.Run("size="+strconv.Itoa(size), func(t *testing.T) { + t.Parallel() + var v primitives.BuilderIndex + err := (&v).UnmarshalSSZ(make([]byte, size)) + require.ErrorContains(t, "expected buffer of length 8", err) + }) + } +} + +func u64name(v uint64) string { + switch v { + case 0: + return "0" + case 1: + return "1" + case 42: + return "42" + case (1 << 32) - 1: + return "2^32-1" + case 1 << 32: + return "2^32" + case ^uint64(0): + return "max" + default: + return "custom" + } +} diff --git a/crypto/keystore/BUILD.bazel b/crypto/keystore/BUILD.bazel index 53ebdeb785..007e737d87 100644 --- a/crypto/keystore/BUILD.bazel +++ b/crypto/keystore/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "keccak256.go", "key.go", "keystore.go", + "log.go", "utils.go", ], importpath = "github.com/OffchainLabs/prysm/v7/crypto/keystore", diff --git a/crypto/keystore/keystore.go b/crypto/keystore/keystore.go index 9fb01d9efb..de273b17b7 100644 --- a/crypto/keystore/keystore.go +++ b/crypto/keystore/keystore.go @@ -35,7 +35,6 @@ import ( "github.com/OffchainLabs/prysm/v7/crypto/bls" "github.com/minio/sha256-simd" "github.com/pborman/uuid" - log "github.com/sirupsen/logrus" "golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/scrypt" ) diff --git a/crypto/keystore/log.go b/crypto/keystore/log.go new file mode 100644 index 0000000000..4a204eb64f --- /dev/null +++ b/crypto/keystore/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package keystore + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "crypto/keystore") diff --git a/crypto/random/BUILD.bazel b/crypto/random/BUILD.bazel index cd4a615a24..95822eb2c4 100644 --- a/crypto/random/BUILD.bazel +++ b/crypto/random/BUILD.bazel @@ -2,7 +2,10 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = ["random.go"], + srcs = [ + "log.go", + "random.go", + ], importpath = "github.com/OffchainLabs/prysm/v7/crypto/random", visibility = ["//visibility:public"], deps = [ diff --git a/crypto/random/log.go b/crypto/random/log.go new file mode 100644 index 0000000000..e45ca9d850 --- /dev/null +++ b/crypto/random/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package random + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "crypto/random") diff --git a/genesis/log.go b/genesis/log.go index 5240aa2b10..05f12c8176 100644 --- a/genesis/log.go +++ b/genesis/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package genesis import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "genesis") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "genesis") diff --git a/hack/check-logs.sh b/hack/check-logs.sh new file mode 100755 index 0000000000..2fb69bb1d0 --- /dev/null +++ b/hack/check-logs.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +cd "$ROOT_DIR" + +# Regenerate all log.go files +./hack/gen-logs.sh + +# Fail if that changed anything +if ! git diff --quiet -- ./; then + echo "ERROR: log.go files are out of date. Please run:" + echo " ./hack/gen-logs.sh" + echo "and commit the changes." + echo + git diff --stat -- ./ || true + exit 1 +fi + +echo "log.go files are up to date." diff --git a/hack/gen-logs.sh b/hack/gen-logs.sh new file mode 100755 index 0000000000..4b88dd1ddc --- /dev/null +++ b/hack/gen-logs.sh @@ -0,0 +1,148 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ---------- config ---------- +# Paths (relative to repo root) to exclude. +# Each entry excludes that directory AND all its subdirectories. +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" + ".git" + ".github" + ".jj" + ".idea" + ".vscode" +) + +# The logrus import path +LOGRUS_IMPORT="github.com/sirupsen/logrus" +# ---------------------------- + +# Require ripgrep +if ! command -v rg >/dev/null 2>&1; then + echo "Error: ripgrep (rg) is required but not installed." >&2 + exit 1 +fi + +# Find project root (git repo root if available, else current dir) +ROOT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +cd "$ROOT_DIR" + +# Helper: return 0 if path starts with any excluded prefix +is_excluded() { + local rel="$1" + rel="${rel#./}" # strip leading "./" if present + + for ex in "${EXCLUDED_PATH_PREFIXES[@]}"; do + if [[ "$rel" == "$ex" || "$rel" == "$ex"/* ]]; then + return 0 + fi + done + return 1 +} + +# Build rg command: +# - respects .gitignore automatically +# - searches only *.go, excluding *_test.go +# - excludes EXCLUDED_PATH_PREFIXES via negative globs so rg doesn't even enter them +rg_args=( + rg -F "$LOGRUS_IMPORT" + --glob '*.go' + --glob '!*_test.go' + -l # list matching files + -0 # NUL-delimited output +) + +for ex in "${EXCLUDED_PATH_PREFIXES[@]}"; do + rg_args+=( --glob "!$ex/**" ) +done + +# 1) Use ripgrep to find all non-test .go files that import logrus. +mapfile -d '' -t FILES < <( + "${rg_args[@]}" . || true +) + +# 2) Collect unique directories containing such files (is_excluded is now redundant but harmless) +declare -A DIRS=() +for f in "${FILES[@]}"; do + dir="$(dirname "$f")" + if is_excluded "$dir"; then + continue + fi + DIRS["$dir"]=1 +done + +# 3) For each directory, (re)generate log.go +for dir in "${!DIRS[@]}"; do + # Collect Go files in this directory + shopt -s nullglob + gofiles=( "$dir"/*.go ) + shopt -u nullglob + if [[ ${#gofiles[@]} -eq 0 ]]; then + continue + fi + + # Prefer non-log.go, non-test files to determine package name + src_files=() + for gf in "${gofiles[@]}"; do + base="$(basename "$gf")" + if [[ "$base" == "log.go" ]]; then + continue + fi + if [[ "$base" == *_test.go ]]; then + continue + fi + src_files+=( "$gf" ) + done + + # Fallback: if there are no such files, use whatever .go files exist (e.g. only log.go) + if [[ ${#src_files[@]} -eq 0 ]]; then + src_files=( "${gofiles[@]}" ) + fi + + pkg_name="$( + grep -h '^package ' "${src_files[@]}" \ + | head -n 1 \ + | awk '{print $2}' + )" + + if [[ -z "$pkg_name" ]]; then + echo "Could not determine package name for $dir, skipping" + continue + fi + + # Path relative to project root (no project name) + rel_path="${dir#./}" + + cat > "$dir/log.go" < 0 { - prefix = colorScheme.PrefixColor(" " + prefixValue + ":") - message = trimmedMsg - } + prefix := "" + prefixValue, message := getPrefixAndMessage(entry) + if len(prefixValue) > 0 { + prefix = colorScheme.PrefixColor(" " + prefixValue + ":") } messageFormat := "%s" @@ -293,7 +289,7 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *logrus.Entry, keys _, err = fmt.Fprintf(b, "%s %s%s "+messageFormat, colorScheme.TimestampColor(timestamp), level, prefix, message) } for _, k := range keys { - if k != "prefix" { + if k != "package" { v := entry.Data[k] format := "%+v" @@ -333,9 +329,39 @@ func (f *TextFormatter) needsQuoting(text string) bool { return false } +// getPrefixAndMessage extracts the prefix and the message from the entry by the following order: +// 1. If the "prefix" field is set in entry.Data, use that as prefix. +// 2. If the "package" field is set in entry.Data, use that to determine the prefix. +// If a replacement is found in prefixReplacements, use that. Otherwise, use the package name. +// 3. Try to extract the prefix from the message itself by looking for a pattern like "[prefix] message". +// 4. If none of the above methods yield a prefix, return an empty prefix and the original message. +func getPrefixAndMessage(entry *logrus.Entry) (string, string) { + prefix := "" + msg := entry.Message + + if prefixOldMethod, ok := entry.Data["prefix"]; ok { + return prefixOldMethod.(string), msg + } + + if packagePath, ok := entry.Data["package"]; ok { + if prefixReplacement, ok := prefixReplacements[packagePath.(string)]; ok { + return prefixReplacement, msg + } + pathSplit := strings.Split(packagePath.(string), "/") + prefix = pathSplit[len(pathSplit)-1] + return prefix, msg + } + + if prefixExtracted, trimmedMsg := extractPrefix(msg); len(prefixExtracted) > 0 { + return prefixExtracted, trimmedMsg + } + + return "", msg +} + func extractPrefix(msg string) (string, string) { prefix := "" - regex := regexp.MustCompile(`^\\[(.*?)\\]`) + if regex.MatchString(msg) { match := regex.FindString(msg) prefix, msg = match[1:len(match)-1], strings.TrimSpace(msg[len(match):]) diff --git a/runtime/logging/logrus-prefixed-formatter/prefix-replacements.go b/runtime/logging/logrus-prefixed-formatter/prefix-replacements.go new file mode 100644 index 0000000000..c2a315193a --- /dev/null +++ b/runtime/logging/logrus-prefixed-formatter/prefix-replacements.go @@ -0,0 +1,24 @@ +package prefixed + +var prefixReplacements = map[string]string{ + "beacon-chain/cache/depositsnapshot": "cache", + "beacon-chain/core/transition": "state", + "beacon-chain/db/kv": "db", + "beacon-chain/db/slasherkv": "slasherdb", + "beacon-chain/db/pruner": "db-pruner", + "beacon-chain/rpc/core": "rpc/core", + "beacon-chain/rpc/eth/beacon": "rpc/beacon", + "beacon-chain/rpc/eth/validator": "beacon-api", + "beacon-chain/rpc/prysm/v1alpha1/beacon": "rpc", + "beacon-chain/rpc/prysm/v1alpha1/validator": "rpc/validator", + "beacon-chain/sync/checkpoint": "checkpoint-sync", + "config/features": "flags", + "proto/prysm/v1alpha1": "protobuf", + "validator/db/kv": "db", + "validator/db/filesystem": "db", + "validator/keymanager/derived": "derived-keymanager", + "validator/keymanager/local": "local-keymanager", + "validator/keymanager/remote-web3signer": "remote-keymanager", + "validator/keymanager/remote-web3signer/internal": "remote-keymanager-internal", + "beacon-chain/forkchoice/doubly-linked-tree": "forkchoice-doublylinkedtree", +} diff --git a/testing/endtoend/evaluators/validator.go b/testing/endtoend/evaluators/validator.go index aed605ba59..8f782c11d3 100644 --- a/testing/endtoend/evaluators/validator.go +++ b/testing/endtoend/evaluators/validator.go @@ -262,6 +262,11 @@ func validatorsSyncParticipation(_ *types.EvaluationContext, conns ...*grpc.Clie // Skip fork slot. continue } + // Skip slot 1 at genesis - validators need time to ramp up after chain start. + // This is a startup timing issue, not a fork transition issue. + if b.Block().Slot() == 1 { + continue + } expectedParticipation := expectedSyncParticipation switch slots.ToEpoch(b.Block().Slot()) { case params.BeaconConfig().AltairForkEpoch: diff --git a/testing/util/deneb.go b/testing/util/deneb.go index 787fbce359..762d2fef65 100644 --- a/testing/util/deneb.go +++ b/testing/util/deneb.go @@ -44,6 +44,13 @@ func WithProposerSigning(idx primitives.ValidatorIndex, sk bls.SecretKey, valRoo } } +// WithProposer sets the proposer index for the generated block without signing. +func WithProposer(idx primitives.ValidatorIndex) DenebBlockGeneratorOption { + return func(g *denebBlockGenerator) { + g.proposer = idx + } +} + func WithPayloadSetter(p *enginev1.ExecutionPayloadDeneb) DenebBlockGeneratorOption { return func(g *denebBlockGenerator) { g.payload = p diff --git a/time/slots/BUILD.bazel b/time/slots/BUILD.bazel index 45289a08db..7688bd0709 100644 --- a/time/slots/BUILD.bazel +++ b/time/slots/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "countdown.go", + "log.go", "slotticker.go", "slottime.go", ], diff --git a/time/slots/countdown.go b/time/slots/countdown.go index 46a5c2a787..1df8eb84cf 100644 --- a/time/slots/countdown.go +++ b/time/slots/countdown.go @@ -10,8 +10,6 @@ import ( "github.com/sirupsen/logrus" ) -var log = logrus.WithField("prefix", "slotutil") - // CountdownToGenesis starts a ticker at the specified duration // logging the remaining minutes until the genesis chainstart event // along with important genesis state metadata such as number diff --git a/time/slots/log.go b/time/slots/log.go new file mode 100644 index 0000000000..3655984991 --- /dev/null +++ b/time/slots/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package slots + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "time/slots") diff --git a/tools/analyzers/httperror/BUILD.bazel b/tools/analyzers/httpwriter/BUILD.bazel similarity index 96% rename from tools/analyzers/httperror/BUILD.bazel rename to tools/analyzers/httpwriter/BUILD.bazel index 5df2bb292e..2b363d99cb 100644 --- a/tools/analyzers/httperror/BUILD.bazel +++ b/tools/analyzers/httpwriter/BUILD.bazel @@ -3,7 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["analyzer.go"], - importpath = "github.com/OffchainLabs/prysm/v7/tools/analyzers/httperror", + importpath = "github.com/OffchainLabs/prysm/v7/tools/analyzers/httpwriter", visibility = ["//visibility:public"], deps = [ "@org_golang_x_tools//go/analysis:go_default_library", diff --git a/tools/analyzers/httperror/analyzer.go b/tools/analyzers/httpwriter/analyzer.go similarity index 85% rename from tools/analyzers/httperror/analyzer.go rename to tools/analyzers/httpwriter/analyzer.go index ed8dfa5046..c292367515 100644 --- a/tools/analyzers/httperror/analyzer.go +++ b/tools/analyzers/httpwriter/analyzer.go @@ -1,4 +1,4 @@ -package httperror +package httpwriter import ( "go/ast" @@ -9,8 +9,8 @@ import ( ) var Analyzer = &analysis.Analyzer{ - Name: "httperror", - Doc: "Ensures calls to httputil.HandleError are immediately followed by a return statement.", + Name: "httpwriter", + Doc: "Ensures that httputil functions which make use of the writer are immediately followed by a return statement.", Requires: []*analysis.Analyzer{ inspect.Analyzer, }, @@ -99,7 +99,7 @@ func checkBlock(pass *analysis.Pass, fn *ast.FuncDecl, block *ast.BlockStmt, nex // Now check the current statement itself: is it (or does it contain) a direct call to httputil.HandleError? // We only consider ExprStmt that are direct CallExpr to httputil.HandleError. - call := findHandleErrorCall(stmt) + call, name := findHandleErrorCall(stmt) if call == nil { continue } @@ -121,7 +121,7 @@ func checkBlock(pass *analysis.Pass, fn *ast.FuncDecl, block *ast.BlockStmt, nex continue } // otherwise it's not a return (even if it's an if/for etc) -> violation - pass.Reportf(stmt.Pos(), "call to httputil.HandleError must be immediately followed by a return statement") + pass.Reportf(stmt.Pos(), "call to httputil.%s must be immediately followed by a return statement", name) continue } @@ -133,31 +133,33 @@ func checkBlock(pass *analysis.Pass, fn *ast.FuncDecl, block *ast.BlockStmt, nex } // Non-void function and it's the last statement → violation - pass.Reportf(stmt.Pos(), "call to httputil.HandleError must be followed by return because function has return values") + pass.Reportf(stmt.Pos(), "call to httputil.%s must be immediately followed by a return statement", name) } } // findHandleErrorCall returns the call expression if stmt is a direct call to httputil.HandleError(...), // otherwise nil. We only match direct ExprStmt -> CallExpr -> SelectorExpr where selector is httputil.HandleError. -func findHandleErrorCall(stmt ast.Stmt) *ast.CallExpr { +func findHandleErrorCall(stmt ast.Stmt) (*ast.CallExpr, string) { es, ok := stmt.(*ast.ExprStmt) if !ok { - return nil + return nil, "" } call, ok := es.X.(*ast.CallExpr) if !ok { - return nil + return nil, "" } sel, ok := call.Fun.(*ast.SelectorExpr) if !ok { - return nil + return nil, "" } pkgIdent, ok := sel.X.(*ast.Ident) if !ok { - return nil + return nil, "" } - if pkgIdent.Name == "httputil" && sel.Sel.Name == "HandleError" { - return call + selectorName := sel.Sel.Name + if pkgIdent.Name == "httputil" && + (selectorName == "HandleError" || selectorName == "WriteError" || selectorName == "WriteJson" || selectorName == "WriteSSZ") { + return call, selectorName } - return nil + return nil, "" } diff --git a/tools/bootnode/bootnode.go b/tools/bootnode/bootnode.go index c64646aced..a602a9b312 100644 --- a/tools/bootnode/bootnode.go +++ b/tools/bootnode/bootnode.go @@ -71,7 +71,7 @@ func main() { flag.Parse() if *logFileName != "" { - if err := logs.ConfigurePersistentLogging(*logFileName); err != nil { + if err := logs.ConfigurePersistentLogging(*logFileName, "text"); err != nil { log.WithError(err).Error("Failed to configuring logging to disk.") } } diff --git a/validator/accounts/log.go b/validator/accounts/log.go index 21a541d77d..139e230d7f 100644 --- a/validator/accounts/log.go +++ b/validator/accounts/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package accounts import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "accounts") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/accounts") diff --git a/validator/accounts/userprompt/log.go b/validator/accounts/userprompt/log.go index 044a03d8fb..1f683f4476 100644 --- a/validator/accounts/userprompt/log.go +++ b/validator/accounts/userprompt/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package userprompt import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "userprompt") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/accounts/userprompt") diff --git a/validator/accounts/wallet/log.go b/validator/accounts/wallet/log.go index ff6bb92eab..bc5f41500f 100644 --- a/validator/accounts/wallet/log.go +++ b/validator/accounts/wallet/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package wallet import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "wallet") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/accounts/wallet") diff --git a/validator/client/BUILD.bazel b/validator/client/BUILD.bazel index 3a26a17e2b..9e74d9cb18 100644 --- a/validator/client/BUILD.bazel +++ b/validator/client/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "health_monitor.go", "key_reload.go", "log.go", + "log_helpers.go", "metrics.go", "multiple_endpoints_grpc_resolver.go", "propose.go", diff --git a/validator/client/beacon-api/log.go b/validator/client/beacon-api/log.go index b087cf2194..aadedf1d2e 100644 --- a/validator/client/beacon-api/log.go +++ b/validator/client/beacon-api/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package beacon_api import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "beacon-api") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/client/beacon-api") diff --git a/validator/client/grpc-api/BUILD.bazel b/validator/client/grpc-api/BUILD.bazel index d116021ec9..adc82fdc8c 100644 --- a/validator/client/grpc-api/BUILD.bazel +++ b/validator/client/grpc-api/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "grpc_node_client.go", "grpc_prysm_beacon_chain_client.go", "grpc_validator_client.go", + "log.go", ], importpath = "github.com/OffchainLabs/prysm/v7/validator/client/grpc-api", visibility = ["//validator:__subpackages__"], diff --git a/validator/client/grpc-api/grpc_node_client.go b/validator/client/grpc-api/grpc_node_client.go index 983fd4f55c..ff472a8fde 100644 --- a/validator/client/grpc-api/grpc_node_client.go +++ b/validator/client/grpc-api/grpc_node_client.go @@ -6,7 +6,6 @@ import ( ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v7/validator/client/iface" "github.com/golang/protobuf/ptypes/empty" - log "github.com/sirupsen/logrus" "google.golang.org/grpc" ) diff --git a/validator/client/grpc-api/grpc_validator_client.go b/validator/client/grpc-api/grpc_validator_client.go index 85663483b3..490c43ff2b 100644 --- a/validator/client/grpc-api/grpc_validator_client.go +++ b/validator/client/grpc-api/grpc_validator_client.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/golang/protobuf/ptypes/empty" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/validator/client/grpc-api/log.go b/validator/client/grpc-api/log.go new file mode 100644 index 0000000000..4b0608b815 --- /dev/null +++ b/validator/client/grpc-api/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package grpc_api + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/client/grpc-api") diff --git a/validator/client/log.go b/validator/client/log.go index 952831aed1..fe41f5f654 100644 --- a/validator/client/log.go +++ b/validator/client/log.go @@ -1,147 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package client -import ( - "fmt" - "strconv" +import "github.com/sirupsen/logrus" - "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" - "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" - ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -var log = logrus.WithField("prefix", "client") - -type submittedAttData struct { - beaconBlockRoot []byte - source *ethpb.Checkpoint - target *ethpb.Checkpoint -} - -type submittedAtt struct { - data submittedAttData - pubkeys [][]byte - committees []primitives.CommitteeIndex -} - -// submittedAttKey is defined as a concatenation of: -// - AttestationData.BeaconBlockRoot -// - AttestationData.Source.HashTreeRoot() -// - AttestationData.Target.HashTreeRoot() -type submittedAttKey [96]byte - -func (k submittedAttKey) FromAttData(data *ethpb.AttestationData) error { - sourceRoot, err := data.Source.HashTreeRoot() - if err != nil { - return err - } - targetRoot, err := data.Target.HashTreeRoot() - if err != nil { - return err - } - copy(k[0:], data.BeaconBlockRoot) - copy(k[32:], sourceRoot[:]) - copy(k[64:], targetRoot[:]) - return nil -} - -// saveSubmittedAtt saves the submitted attestation data along with the attester's pubkey. -// The purpose of this is to display combined attesting logs for all keys managed by the validator client. -func (v *validator) saveSubmittedAtt(att ethpb.Att, pubkey []byte, isAggregate bool) error { - v.attLogsLock.Lock() - defer v.attLogsLock.Unlock() - data := att.GetData() - key := submittedAttKey{} - if err := key.FromAttData(data); err != nil { - return errors.Wrapf(err, "could not create submitted attestation key") - } - d := submittedAttData{ - beaconBlockRoot: data.BeaconBlockRoot, - source: data.Source, - target: data.Target, - } - - var submittedAtts map[submittedAttKey]*submittedAtt - if isAggregate { - submittedAtts = v.submittedAggregates - } else { - submittedAtts = v.submittedAtts - } - - if submittedAtts[key] == nil { - submittedAtts[key] = &submittedAtt{ - d, - [][]byte{}, - []primitives.CommitteeIndex{}, - } - } - submittedAtts[key] = &submittedAtt{ - d, - append(submittedAtts[key].pubkeys, pubkey), - append(submittedAtts[key].committees, att.GetCommitteeIndex()), - } - - return nil -} - -// LogSubmittedAtts logs info about submitted attestations. -func (v *validator) LogSubmittedAtts(slot primitives.Slot) { - v.attLogsLock.Lock() - defer v.attLogsLock.Unlock() - - for _, attLog := range v.submittedAtts { - pubkeys := make([]string, len(attLog.pubkeys)) - for i, p := range attLog.pubkeys { - pubkeys[i] = fmt.Sprintf("%#x", bytesutil.Trunc(p)) - } - committees := make([]string, len(attLog.committees)) - for i, c := range attLog.committees { - committees[i] = strconv.FormatUint(uint64(c), 10) - } - log.WithFields(logrus.Fields{ - "slot": slot, - "committeeIndices": committees, - "pubkeys": pubkeys, - "blockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.beaconBlockRoot)), - "sourceEpoch": attLog.data.source.Epoch, - "sourceRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.source.Root)), - "targetEpoch": attLog.data.target.Epoch, - "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.target.Root)), - }).Info("Submitted new attestations") - } - for _, attLog := range v.submittedAggregates { - pubkeys := make([]string, len(attLog.pubkeys)) - for i, p := range attLog.pubkeys { - pubkeys[i] = fmt.Sprintf("%#x", bytesutil.Trunc(p)) - } - committees := make([]string, len(attLog.committees)) - for i, c := range attLog.committees { - committees[i] = strconv.FormatUint(uint64(c), 10) - } - log.WithFields(logrus.Fields{ - "slot": slot, - "committeeIndices": committees, - "pubkeys": pubkeys, - "blockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.beaconBlockRoot)), - "sourceEpoch": attLog.data.source.Epoch, - "sourceRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.source.Root)), - "targetEpoch": attLog.data.target.Epoch, - "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.target.Root)), - }).Info("Submitted new aggregate attestations") - } - - v.submittedAtts = make(map[submittedAttKey]*submittedAtt) - v.submittedAggregates = make(map[submittedAttKey]*submittedAtt) -} - -// LogSubmittedSyncCommitteeMessages logs info about submitted sync committee messages. -func (v *validator) LogSubmittedSyncCommitteeMessages() { - if count := v.syncCommitteeStats.totalMessagesSubmitted.Load(); count > 0 { - log.WithField("messages", count). - Debug("Submitted sync committee messages successfully to beacon node") - - // Reset the amount. - v.syncCommitteeStats.totalMessagesSubmitted.Store(0) - } -} +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/client") diff --git a/validator/client/log_helpers.go b/validator/client/log_helpers.go new file mode 100644 index 0000000000..dcb4a2f6f4 --- /dev/null +++ b/validator/client/log_helpers.go @@ -0,0 +1,145 @@ +package client + +import ( + "fmt" + "strconv" + + "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" + "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" + ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +type submittedAttData struct { + beaconBlockRoot []byte + source *ethpb.Checkpoint + target *ethpb.Checkpoint +} + +type submittedAtt struct { + data submittedAttData + pubkeys [][]byte + committees []primitives.CommitteeIndex +} + +// submittedAttKey is defined as a concatenation of: +// - AttestationData.BeaconBlockRoot +// - AttestationData.Source.HashTreeRoot() +// - AttestationData.Target.HashTreeRoot() +type submittedAttKey [96]byte + +func (k submittedAttKey) FromAttData(data *ethpb.AttestationData) error { + sourceRoot, err := data.Source.HashTreeRoot() + if err != nil { + return err + } + targetRoot, err := data.Target.HashTreeRoot() + if err != nil { + return err + } + copy(k[0:], data.BeaconBlockRoot) + copy(k[32:], sourceRoot[:]) + copy(k[64:], targetRoot[:]) + return nil +} + +// saveSubmittedAtt saves the submitted attestation data along with the attester's pubkey. +// The purpose of this is to display combined attesting logs for all keys managed by the validator client. +func (v *validator) saveSubmittedAtt(att ethpb.Att, pubkey []byte, isAggregate bool) error { + v.attLogsLock.Lock() + defer v.attLogsLock.Unlock() + data := att.GetData() + key := submittedAttKey{} + if err := key.FromAttData(data); err != nil { + return errors.Wrapf(err, "could not create submitted attestation key") + } + d := submittedAttData{ + beaconBlockRoot: data.BeaconBlockRoot, + source: data.Source, + target: data.Target, + } + + var submittedAtts map[submittedAttKey]*submittedAtt + if isAggregate { + submittedAtts = v.submittedAggregates + } else { + submittedAtts = v.submittedAtts + } + + if submittedAtts[key] == nil { + submittedAtts[key] = &submittedAtt{ + d, + [][]byte{}, + []primitives.CommitteeIndex{}, + } + } + submittedAtts[key] = &submittedAtt{ + d, + append(submittedAtts[key].pubkeys, pubkey), + append(submittedAtts[key].committees, att.GetCommitteeIndex()), + } + + return nil +} + +// LogSubmittedAtts logs info about submitted attestations. +func (v *validator) LogSubmittedAtts(slot primitives.Slot) { + v.attLogsLock.Lock() + defer v.attLogsLock.Unlock() + + for _, attLog := range v.submittedAtts { + pubkeys := make([]string, len(attLog.pubkeys)) + for i, p := range attLog.pubkeys { + pubkeys[i] = fmt.Sprintf("%#x", bytesutil.Trunc(p)) + } + committees := make([]string, len(attLog.committees)) + for i, c := range attLog.committees { + committees[i] = strconv.FormatUint(uint64(c), 10) + } + log.WithFields(logrus.Fields{ + "slot": slot, + "committeeIndices": committees, + "pubkeys": pubkeys, + "blockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.beaconBlockRoot)), + "sourceEpoch": attLog.data.source.Epoch, + "sourceRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.source.Root)), + "targetEpoch": attLog.data.target.Epoch, + "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.target.Root)), + }).Info("Submitted new attestations") + } + for _, attLog := range v.submittedAggregates { + pubkeys := make([]string, len(attLog.pubkeys)) + for i, p := range attLog.pubkeys { + pubkeys[i] = fmt.Sprintf("%#x", bytesutil.Trunc(p)) + } + committees := make([]string, len(attLog.committees)) + for i, c := range attLog.committees { + committees[i] = strconv.FormatUint(uint64(c), 10) + } + log.WithFields(logrus.Fields{ + "slot": slot, + "committeeIndices": committees, + "pubkeys": pubkeys, + "blockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.beaconBlockRoot)), + "sourceEpoch": attLog.data.source.Epoch, + "sourceRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.source.Root)), + "targetEpoch": attLog.data.target.Epoch, + "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(attLog.data.target.Root)), + }).Info("Submitted new aggregate attestations") + } + + v.submittedAtts = make(map[submittedAttKey]*submittedAtt) + v.submittedAggregates = make(map[submittedAttKey]*submittedAtt) +} + +// LogSubmittedSyncCommitteeMessages logs info about submitted sync committee messages. +func (v *validator) LogSubmittedSyncCommitteeMessages() { + if count := v.syncCommitteeStats.totalMessagesSubmitted.Load(); count > 0 { + log.WithField("messages", count). + Debug("Submitted sync committee messages successfully to beacon node") + + // Reset the amount. + v.syncCommitteeStats.totalMessagesSubmitted.Store(0) + } +} diff --git a/validator/client/metrics_test.go b/validator/client/metrics_test.go index 7f1bc252e0..51409b6fa3 100644 --- a/validator/client/metrics_test.go +++ b/validator/client/metrics_test.go @@ -83,7 +83,7 @@ func TestUpdateLogAggregateStats(t *testing.T) { "correctlyVotedHeadPct=\"100%\" correctlyVotedSourcePct=\"100%\" correctlyVotedTargetPct=\"50%\" epoch=2") require.LogsContain(t, hook, "msg=\"Vote summary since launch\" attestationsInclusionPct=\"78%\" "+ "averageInclusionDistance=\"0.00 slots\" correctlyVotedHeadPct=\"86%\" correctlyVotedSourcePct=\"100%\" "+ - "correctlyVotedTargetPct=\"86%\" numberOfEpochs=3 pctChangeCombinedBalance=\"0.20555%\"") + "correctlyVotedTargetPct=\"86%\" numberOfEpochs=3 package=validator/client pctChangeCombinedBalance=\"0.20555%\"") } @@ -161,5 +161,5 @@ func TestUpdateLogAltairAggregateStats(t *testing.T) { "averageInactivityScore=0 correctlyVotedHeadPct=\"100%\" correctlyVotedSourcePct=\"100%\" correctlyVotedTargetPct=\"50%\" epoch=74242") require.LogsContain(t, hook, "msg=\"Vote summary since launch\" attestationsInclusionPct=\"78%\" "+ "correctlyVotedHeadPct=\"86%\" correctlyVotedSourcePct=\"100%\" "+ - "correctlyVotedTargetPct=\"71%\" numberOfEpochs=3 pctChangeCombinedBalance=\"0.20555%\"") + "correctlyVotedTargetPct=\"71%\" numberOfEpochs=3 package=validator/client pctChangeCombinedBalance=\"0.20555%\"") } diff --git a/validator/client/validator_test.go b/validator/client/validator_test.go index 92e214ce7c..605dbf4b04 100644 --- a/validator/client/validator_test.go +++ b/validator/client/validator_test.go @@ -775,7 +775,7 @@ func TestCheckAndLogValidatorStatus_OK(t *testing.T) { PositionInActivationQueue: 30, }, }, - log: "Validator deposited, entering activation queue after finalization\" prefix=client pubkey=0x000000000000 status=DEPOSITED validatorIndex=30", + log: "Validator deposited, entering activation queue after finalization\" package=validator/client pubkey=0x000000000000 status=DEPOSITED validatorIndex=30", active: false, }, { @@ -789,7 +789,7 @@ func TestCheckAndLogValidatorStatus_OK(t *testing.T) { PositionInActivationQueue: 6, }, }, - log: "Waiting for activation... Check validator queue status in a block explorer\" prefix=client pubkey=0x000000000000 status=PENDING validatorIndex=50", + log: "Waiting for activation... Check validator queue status in a block explorer\" package=validator/client pubkey=0x000000000000 status=PENDING validatorIndex=50", active: false, }, { diff --git a/validator/db/filesystem/BUILD.bazel b/validator/db/filesystem/BUILD.bazel index 7d5f1e81b3..e09134c5dc 100644 --- a/validator/db/filesystem/BUILD.bazel +++ b/validator/db/filesystem/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "genesis.go", "graffiti.go", "import.go", + "log.go", "migration.go", "proposer_protection.go", "proposer_settings.go", diff --git a/validator/db/filesystem/db.go b/validator/db/filesystem/db.go index 1b39352842..1ec43f30a2 100644 --- a/validator/db/filesystem/db.go +++ b/validator/db/filesystem/db.go @@ -73,9 +73,6 @@ type ( // Ensure the filesystem store implements the interface. var _ = iface.ValidatorDB(&Store{}) -// Logging. -var log = logrus.WithField("prefix", "db") - // NewStore creates a new filesystem store. func NewStore(databaseParentPath string, config *Config) (*Store, error) { s := &Store{ diff --git a/validator/db/filesystem/log.go b/validator/db/filesystem/log.go new file mode 100644 index 0000000000..aa7eac814c --- /dev/null +++ b/validator/db/filesystem/log.go @@ -0,0 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. +package filesystem + +import "github.com/sirupsen/logrus" + +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/db/filesystem") diff --git a/validator/db/kv/log.go b/validator/db/kv/log.go index 5c1d80880c..cdba98d278 100644 --- a/validator/db/kv/log.go +++ b/validator/db/kv/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package kv import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "db") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/db/kv") diff --git a/validator/db/log.go b/validator/db/log.go index f320f2fe6a..d71321985d 100644 --- a/validator/db/log.go +++ b/validator/db/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package db import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "db") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/db") diff --git a/validator/graffiti/log.go b/validator/graffiti/log.go index b689212ba4..5d032e92ea 100644 --- a/validator/graffiti/log.go +++ b/validator/graffiti/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package graffiti import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "graffiti") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/graffiti") diff --git a/validator/keymanager/derived/log.go b/validator/keymanager/derived/log.go index a4b39d299a..d41f15a71b 100644 --- a/validator/keymanager/derived/log.go +++ b/validator/keymanager/derived/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package derived import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "derived-keymanager") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/keymanager/derived") diff --git a/validator/keymanager/local/log.go b/validator/keymanager/local/log.go index 2a39bc2bf5..9c7f4199fd 100644 --- a/validator/keymanager/local/log.go +++ b/validator/keymanager/local/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package local import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "local-keymanager") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/keymanager/local") diff --git a/validator/keymanager/remote-web3signer/internal/log.go b/validator/keymanager/remote-web3signer/internal/log.go index b96e4ca4f6..614f02203b 100644 --- a/validator/keymanager/remote-web3signer/internal/log.go +++ b/validator/keymanager/remote-web3signer/internal/log.go @@ -1,7 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package internal -import ( - "github.com/sirupsen/logrus" -) +import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "remote-web3signer-internal") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/keymanager/remote-web3signer/internal") diff --git a/validator/keymanager/remote-web3signer/log.go b/validator/keymanager/remote-web3signer/log.go index f579bdb7ae..1859e37e28 100644 --- a/validator/keymanager/remote-web3signer/log.go +++ b/validator/keymanager/remote-web3signer/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package remote_web3signer import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "remote-keymanager") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/keymanager/remote-web3signer") diff --git a/validator/node/log.go b/validator/node/log.go index 2c3b06e822..f493c0c527 100644 --- a/validator/node/log.go +++ b/validator/node/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package node import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "node") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/node") diff --git a/validator/rpc/log.go b/validator/rpc/log.go index 5c2ea5ccf3..d48eeb26e0 100644 --- a/validator/rpc/log.go +++ b/validator/rpc/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package rpc import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "rpc") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/rpc") diff --git a/validator/web/log.go b/validator/web/log.go index cea59bae0a..6a9403a3ca 100644 --- a/validator/web/log.go +++ b/validator/web/log.go @@ -1,5 +1,9 @@ +// Code generated by hack/gen-logs.sh; DO NOT EDIT. +// This file is created and regenerated automatically. Anything added here might get removed. package web import "github.com/sirupsen/logrus" -var log = logrus.WithField("prefix", "web") +// The prefix for logs from this package will be the text after the last slash in the package path. +// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file. +var log = logrus.WithField("package", "validator/web")