mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 13:58:09 -05:00
Compare commits
15 Commits
deneb-test
...
blockPropo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dbc6ef309 | ||
|
|
29df5a0c9a | ||
|
|
c3f5844679 | ||
|
|
2a4441762e | ||
|
|
401fccc723 | ||
|
|
c80f88fc07 | ||
|
|
faa0a2c4cf | ||
|
|
c45cb7e188 | ||
|
|
0b10263dd5 | ||
|
|
3bc808352f | ||
|
|
d0c740f477 | ||
|
|
cbe67f1970 | ||
|
|
5bb482e5d6 | ||
|
|
83494c5b23 | ||
|
|
a10ffa9c0e |
4
.bazelrc
4
.bazelrc
@@ -43,3 +43,7 @@ build:debug -s
|
||||
|
||||
# Set bazel gotag
|
||||
build --define gotags=bazel
|
||||
|
||||
# Abseil requires c++14 or greater.
|
||||
build --cxxopt=-std=c++20
|
||||
build --host_cxxopt=-std=c++20
|
||||
|
||||
@@ -3,7 +3,6 @@ load("@com_github_atlassian_bazel_tools//gometalinter:def.bzl", "gometalinter")
|
||||
load("@com_github_atlassian_bazel_tools//goimports:def.bzl", "goimports")
|
||||
load("@io_kubernetes_build//defs:run_in_workspace.bzl", "workspace_binary")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "nogo")
|
||||
load("@vaticle_bazel_distribution//common:rules.bzl", "assemble_targz", "assemble_versioned")
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "string_setting")
|
||||
|
||||
prefix = "github.com/prysmaticlabs/prysm"
|
||||
|
||||
10
WORKSPACE
10
WORKSPACE
@@ -321,11 +321,13 @@ http_archive(
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/f2aed9ee205d62d45c55cfabbfd26342f8526862.zip",
|
||||
)
|
||||
|
||||
git_repository(
|
||||
http_archive(
|
||||
name = "com_google_protobuf",
|
||||
commit = "436bd7880e458532901c58f4d9d1ea23fa7edd52",
|
||||
remote = "https://github.com/protocolbuffers/protobuf",
|
||||
shallow_since = "1617835118 -0700",
|
||||
sha256 = "4e176116949be52b0408dfd24f8925d1eb674a781ae242a75296b17a1c721395",
|
||||
strip_prefix = "protobuf-23.3",
|
||||
urls = [
|
||||
"https://github.com/protocolbuffers/protobuf/archive/v23.3.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
# Group the sources of the library so that CMake rule have access to it
|
||||
|
||||
@@ -128,6 +128,7 @@ func TestDownloadWeakSubjectivityCheckpoint(t *testing.T) {
|
||||
wst, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
fork, err := forkForEpoch(cfg, epoch)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, wst.SetFork(fork))
|
||||
|
||||
// set up checkpoint block
|
||||
@@ -226,6 +227,7 @@ func TestDownloadBackwardsCompatibleCombined(t *testing.T) {
|
||||
wst, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
fork, err := forkForEpoch(cfg, cfg.GenesisEpoch)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, wst.SetFork(fork))
|
||||
|
||||
// set up checkpoint block
|
||||
@@ -399,6 +401,7 @@ func TestDownloadFinalizedData(t *testing.T) {
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
fork, err := forkForEpoch(cfg, epoch)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, st.SetFork(fork))
|
||||
require.NoError(t, st.SetSlot(slot))
|
||||
|
||||
|
||||
@@ -41,13 +41,15 @@ var (
|
||||
type invalidBlock struct {
|
||||
invalidAncestorRoots [][32]byte
|
||||
error
|
||||
root [32]byte
|
||||
root [32]byte
|
||||
lastValidHash [32]byte
|
||||
}
|
||||
|
||||
type invalidBlockError interface {
|
||||
Error() string
|
||||
InvalidAncestorRoots() [][32]byte
|
||||
BlockRoot() [32]byte
|
||||
LastValidHash() [32]byte
|
||||
}
|
||||
|
||||
// BlockRoot returns the invalid block root.
|
||||
@@ -55,6 +57,11 @@ func (e invalidBlock) BlockRoot() [32]byte {
|
||||
return e.root
|
||||
}
|
||||
|
||||
// LastValidHash returns the last valid hash root.
|
||||
func (e invalidBlock) LastValidHash() [32]byte {
|
||||
return e.lastValidHash
|
||||
}
|
||||
|
||||
// InvalidAncestorRoots returns an optional list of invalid roots of the invalid block which leads up last valid root.
|
||||
func (e invalidBlock) InvalidAncestorRoots() [][32]byte {
|
||||
return e.invalidAncestorRoots
|
||||
@@ -72,6 +79,19 @@ func IsInvalidBlock(e error) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// InvalidBlockLVH returns the invalid block last valid hash root. If the error
|
||||
// doesn't have a last valid hash, [32]byte{} is returned.
|
||||
func InvalidBlockLVH(e error) [32]byte {
|
||||
if e == nil {
|
||||
return [32]byte{}
|
||||
}
|
||||
d, ok := e.(invalidBlockError)
|
||||
if !ok {
|
||||
return [32]byte{}
|
||||
}
|
||||
return d.LastValidHash()
|
||||
}
|
||||
|
||||
// InvalidBlockRoot returns the invalid block root. If the error
|
||||
// doesn't have an invalid blockroot. [32]byte{} is returned.
|
||||
func InvalidBlockRoot(e error) [32]byte {
|
||||
|
||||
@@ -220,35 +220,37 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
|
||||
}).Info("Called new payload with optimistic block")
|
||||
return false, nil
|
||||
case execution.ErrInvalidPayloadStatus:
|
||||
newPayloadInvalidNodeCount.Inc()
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
invalidRoots, err := s.cfg.ForkChoiceStore.SetOptimisticToInvalid(ctx, root, blk.Block().ParentRoot(), bytesutil.ToBytes32(lastValidHash))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := s.removeInvalidBlockAndState(ctx, invalidRoots); err != nil {
|
||||
return false, err
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": blk.Block().Slot(),
|
||||
"blockRoot": fmt.Sprintf("%#x", root),
|
||||
"invalidChildrenCount": len(invalidRoots),
|
||||
}).Warn("Pruned invalid blocks")
|
||||
lvh := bytesutil.ToBytes32(lastValidHash)
|
||||
return false, invalidBlock{
|
||||
invalidAncestorRoots: invalidRoots,
|
||||
error: ErrInvalidPayload,
|
||||
error: ErrInvalidPayload,
|
||||
lastValidHash: lvh,
|
||||
}
|
||||
case execution.ErrInvalidBlockHashPayloadStatus:
|
||||
newPayloadInvalidNodeCount.Inc()
|
||||
return false, ErrInvalidBlockHashPayloadStatus
|
||||
default:
|
||||
return false, errors.WithMessage(ErrUndefinedExecutionEngineError, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// reportInvalidBlock deals with the event that an invalid block was detected by the execution layer
|
||||
func (s *Service) reportInvalidBlock(ctx context.Context, root, parentRoot, lvh [32]byte) error {
|
||||
newPayloadInvalidNodeCount.Inc()
|
||||
invalidRoots, err := s.cfg.ForkChoiceStore.SetOptimisticToInvalid(ctx, root, parentRoot, lvh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.removeInvalidBlockAndState(ctx, invalidRoots); err != nil {
|
||||
return err
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"blockRoot": fmt.Sprintf("%#x", root),
|
||||
"invalidChildrenCount": len(invalidRoots),
|
||||
}).Warn("Pruned invalid blocks")
|
||||
return invalidBlock{
|
||||
invalidAncestorRoots: invalidRoots,
|
||||
error: ErrInvalidPayload,
|
||||
lastValidHash: lvh,
|
||||
}
|
||||
}
|
||||
|
||||
// getPayloadAttributes returns the payload attributes for the given state and slot.
|
||||
// The attribute is required to initiate a payload build process in the context of an `engine_forkchoiceUpdated` call.
|
||||
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot primitives.Slot, headRoot []byte) (bool, payloadattribute.Attributer, primitives.ValidatorIndex) {
|
||||
|
||||
@@ -743,6 +743,37 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
|
||||
require.Equal(t, true, validated)
|
||||
}
|
||||
|
||||
func Test_reportInvalidBlock(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
params.OverrideBeaconConfig(params.MainnetConfig())
|
||||
service, tr := minimalTestService(t)
|
||||
ctx, _, fcs := tr.ctx, tr.db, tr.fcs
|
||||
jcp := ðpb.Checkpoint{}
|
||||
st, root, err := prepareForkchoiceState(ctx, 0, [32]byte{'A'}, [32]byte{}, [32]byte{'a'}, jcp, jcp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
st, root, err = prepareForkchoiceState(ctx, 1, [32]byte{'B'}, [32]byte{'A'}, [32]byte{'b'}, jcp, jcp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
st, root, err = prepareForkchoiceState(ctx, 2, [32]byte{'C'}, [32]byte{'B'}, [32]byte{'c'}, jcp, jcp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
|
||||
st, root, err = prepareForkchoiceState(ctx, 3, [32]byte{'D'}, [32]byte{'C'}, [32]byte{'d'}, jcp, jcp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertNode(ctx, st, root))
|
||||
|
||||
require.NoError(t, fcs.SetOptimisticToValid(ctx, [32]byte{'A'}))
|
||||
err = service.reportInvalidBlock(ctx, [32]byte{'D'}, [32]byte{'C'}, [32]byte{'a'})
|
||||
require.Equal(t, IsInvalidBlock(err), true)
|
||||
require.Equal(t, InvalidBlockLVH(err), [32]byte{'a'})
|
||||
invalidRoots := InvalidAncestorRoots(err)
|
||||
require.Equal(t, 3, len(invalidRoots))
|
||||
require.Equal(t, [32]byte{'D'}, invalidRoots[0])
|
||||
require.Equal(t, [32]byte{'C'}, invalidRoots[1])
|
||||
require.Equal(t, [32]byte{'B'}, invalidRoots[2])
|
||||
}
|
||||
|
||||
func Test_GetPayloadAttribute(t *testing.T) {
|
||||
service, tr := minimalTestService(t, WithProposerIdsCache(cache.NewProposerPayloadIDsCache()))
|
||||
ctx := tr.ctx
|
||||
|
||||
@@ -107,7 +107,8 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.ReadOnlySignedB
|
||||
}
|
||||
|
||||
// Verify that the parent block is in forkchoice
|
||||
if !s.cfg.ForkChoiceStore.HasNode(b.ParentRoot()) {
|
||||
parentRoot := b.ParentRoot()
|
||||
if !s.cfg.ForkChoiceStore.HasNode(parentRoot) {
|
||||
return ErrNotDescendantOfFinalized
|
||||
}
|
||||
|
||||
@@ -134,6 +135,9 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.ReadOnlySignedB
|
||||
}
|
||||
isValidPayload, err := s.notifyNewPayload(ctx, postStateVersion, postStateHeader, signed)
|
||||
if err != nil {
|
||||
if IsInvalidBlock(err) && InvalidBlockLVH(err) != [32]byte{} {
|
||||
return s.reportInvalidBlock(ctx, blockRoot, parentRoot, InvalidBlockLVH(err))
|
||||
}
|
||||
return errors.Wrap(err, "could not validate new payload")
|
||||
}
|
||||
if signed.Version() < version.Capella && isValidPayload {
|
||||
@@ -492,9 +496,20 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState state.Beaco
|
||||
if err := helpers.UpdateCommitteeCache(ctx, copied, coreTime.CurrentEpoch(copied)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, copied); err != nil {
|
||||
e := coreTime.CurrentEpoch(copied)
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, copied, e); err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
// Use a custom deadline here, since this method runs asynchronously.
|
||||
// We ignore the parent method's context and instead create a new one
|
||||
// with a custom deadline, therefore using the background context instead.
|
||||
slotCtx, cancel := context.WithTimeout(context.Background(), slotDeadline)
|
||||
defer cancel()
|
||||
if err := helpers.UpdateProposerIndicesInCache(slotCtx, copied, e+1); err != nil {
|
||||
log.WithError(err).Warn("Failed to cache next epoch proposers")
|
||||
}
|
||||
}()
|
||||
} else if postState.Slot() >= s.nextEpochBoundarySlot {
|
||||
s.nextEpochBoundarySlot, err = slots.EpochStart(coreTime.NextEpoch(postState))
|
||||
if err != nil {
|
||||
@@ -506,7 +521,7 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState state.Beaco
|
||||
if err := helpers.UpdateCommitteeCache(ctx, postState, coreTime.CurrentEpoch(postState)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, postState); err != nil {
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, postState, coreTime.CurrentEpoch(postState)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -518,7 +533,6 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState state.Beaco
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
||||
mathutil "github.com/prysmaticlabs/prysm/v4/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v4/time"
|
||||
"github.com/prysmaticlabs/prysm/v4/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -213,6 +214,7 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa
|
||||
func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.insertFinalizedDeposits")
|
||||
defer span.End()
|
||||
startTime := time.Now()
|
||||
|
||||
// Update deposit cache.
|
||||
finalizedState, err := s.cfg.StateGen.StateByRoot(ctx, fRoot)
|
||||
@@ -237,6 +239,7 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e
|
||||
if err = s.cfg.DepositCache.PruneProofs(ctx, int64(eth1DepositIndex)); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
log.WithField("duration", time.Since(startTime).String()).Debug("Finalized deposit insertion completed")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
|
||||
coreTime "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/execution"
|
||||
@@ -408,7 +409,7 @@ func (s *Service) initializeBeaconChain(
|
||||
if err := helpers.UpdateCommitteeCache(ctx, genesisState, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, genesisState); err != nil {
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, genesisState, coreTime.CurrentEpoch(genesisState)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -336,20 +336,21 @@ func UpdateCommitteeCache(ctx context.Context, state state.ReadOnlyBeaconState,
|
||||
}
|
||||
|
||||
// UpdateProposerIndicesInCache updates proposer indices entry of the committee cache.
|
||||
func UpdateProposerIndicesInCache(ctx context.Context, state state.ReadOnlyBeaconState) error {
|
||||
// Input state is used to retrieve active validator indices.
|
||||
// Input epoch is the epoch to retrieve proposer indices for.
|
||||
func UpdateProposerIndicesInCache(ctx context.Context, state state.ReadOnlyBeaconState, epoch primitives.Epoch) error {
|
||||
// The cache uses the state root at the (current epoch - 1)'s slot as key. (e.g. for epoch 2, the key is root at slot 63)
|
||||
// Which is the reason why we skip genesis epoch.
|
||||
if time.CurrentEpoch(state) <= params.BeaconConfig().GenesisEpoch+params.BeaconConfig().MinSeedLookahead {
|
||||
if epoch <= params.BeaconConfig().GenesisEpoch+params.BeaconConfig().MinSeedLookahead {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use state root from (current_epoch - 1))
|
||||
wantedEpoch := time.PrevEpoch(state)
|
||||
s, err := slots.EpochEnd(wantedEpoch)
|
||||
s, err := slots.EpochEnd(epoch - 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r, err := StateRootAtSlot(state, s)
|
||||
r, err := state.StateRootAtIndex(uint64(s % params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -366,11 +367,11 @@ func UpdateProposerIndicesInCache(ctx context.Context, state state.ReadOnlyBeaco
|
||||
return nil
|
||||
}
|
||||
|
||||
indices, err := ActiveValidatorIndices(ctx, state, time.CurrentEpoch(state))
|
||||
indices, err := ActiveValidatorIndices(ctx, state, epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
proposerIndices, err := precomputeProposerIndices(state, indices)
|
||||
proposerIndices, err := precomputeProposerIndices(state, indices, epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -432,11 +433,10 @@ func computeCommittee(
|
||||
|
||||
// This computes proposer indices of the current epoch and returns a list of proposer indices,
|
||||
// the index of the list represents the slot number.
|
||||
func precomputeProposerIndices(state state.ReadOnlyBeaconState, activeIndices []primitives.ValidatorIndex) ([]primitives.ValidatorIndex, error) {
|
||||
func precomputeProposerIndices(state state.ReadOnlyBeaconState, activeIndices []primitives.ValidatorIndex, e primitives.Epoch) ([]primitives.ValidatorIndex, error) {
|
||||
hashFunc := hash.CustomSHA256Hasher()
|
||||
proposerIndices := make([]primitives.ValidatorIndex, params.BeaconConfig().SlotsPerEpoch)
|
||||
|
||||
e := time.CurrentEpoch(state)
|
||||
seed, err := Seed(state, e, params.BeaconConfig().DomainBeaconProposer)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not generate seed")
|
||||
|
||||
@@ -639,7 +639,7 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
|
||||
indices, err := ActiveValidatorIndices(context.Background(), state, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerIndices, err := precomputeProposerIndices(state, indices)
|
||||
proposerIndices, err := precomputeProposerIndices(state, indices, time.CurrentEpoch(state))
|
||||
require.NoError(t, err)
|
||||
|
||||
var wantedProposerIndices []primitives.ValidatorIndex
|
||||
|
||||
@@ -262,7 +262,7 @@ func BeaconProposerIndex(ctx context.Context, state state.ReadOnlyBeaconState) (
|
||||
}
|
||||
return proposerIndices[state.Slot()%params.BeaconConfig().SlotsPerEpoch], nil
|
||||
}
|
||||
if err := UpdateProposerIndicesInCache(ctx, state); err != nil {
|
||||
if err := UpdateProposerIndicesInCache(ctx, state, time.CurrentEpoch(state)); err != nil {
|
||||
return 0, errors.Wrap(err, "could not update committee cache")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
)
|
||||
|
||||
func (s *Store) setOptimisticToInvalid(ctx context.Context, root, parentRoot, payloadHash [32]byte) ([][32]byte, error) {
|
||||
func (s *Store) setOptimisticToInvalid(ctx context.Context, root, parentRoot, lastValidHash [32]byte) ([][32]byte, error) {
|
||||
invalidRoots := make([][32]byte, 0)
|
||||
node, ok := s.nodeByRoot[root]
|
||||
if !ok {
|
||||
@@ -16,7 +16,7 @@ func (s *Store) setOptimisticToInvalid(ctx context.Context, root, parentRoot, pa
|
||||
return invalidRoots, errors.Wrap(ErrNilNode, "could not set node to invalid")
|
||||
}
|
||||
// return early if the parent is LVH
|
||||
if node.payloadHash == payloadHash {
|
||||
if node.payloadHash == lastValidHash {
|
||||
return invalidRoots, nil
|
||||
}
|
||||
} else {
|
||||
@@ -28,7 +28,7 @@ func (s *Store) setOptimisticToInvalid(ctx context.Context, root, parentRoot, pa
|
||||
}
|
||||
}
|
||||
firstInvalid := node
|
||||
for ; firstInvalid.parent != nil && firstInvalid.parent.payloadHash != payloadHash; firstInvalid = firstInvalid.parent {
|
||||
for ; firstInvalid.parent != nil && firstInvalid.parent.payloadHash != lastValidHash; firstInvalid = firstInvalid.parent {
|
||||
if ctx.Err() != nil {
|
||||
return invalidRoots, ctx.Err()
|
||||
}
|
||||
|
||||
@@ -987,7 +987,8 @@ func (b *BeaconNode) registerBuilderService(cliCtx *cli.Context) error {
|
||||
opts := append(b.serviceFlagOpts.builderOpts,
|
||||
builder.WithHeadFetcher(chainService),
|
||||
builder.WithDatabase(b.db))
|
||||
if cliCtx.Bool(flags.EnableRegistrationCache.Name) {
|
||||
// make cache the default.
|
||||
if !cliCtx.Bool(features.DisableRegistrationCache.Name) {
|
||||
opts = append(opts, builder.WithRegistrationCache())
|
||||
}
|
||||
svc, err := builder.NewService(b.ctx, opts...)
|
||||
|
||||
@@ -71,6 +71,8 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
blockchain.LateBlockAttemptedReorgCount.Inc()
|
||||
}
|
||||
|
||||
log.Infof("Updated head at %s", time.Since(t))
|
||||
|
||||
// An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain).
|
||||
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch {
|
||||
if err := vs.optimisticStatus(ctx); err != nil {
|
||||
@@ -91,6 +93,8 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
return nil, status.Errorf(codes.Internal, "Could not process slots up to %d: %v", req.Slot, err)
|
||||
}
|
||||
|
||||
log.Infof("Processed slots at %s", time.Since(t))
|
||||
|
||||
// Set slot, graffiti, randao reveal, and parent root.
|
||||
sBlk.SetSlot(req.Slot)
|
||||
sBlk.SetGraffiti(req.Graffiti)
|
||||
@@ -104,8 +108,10 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
}
|
||||
sBlk.SetProposerIndex(idx)
|
||||
|
||||
log.Infof("Retrieved proposer index at %s", time.Since(t))
|
||||
|
||||
if features.Get().BuildBlockParallel {
|
||||
if err := vs.BuildBlockParallel(ctx, sBlk, head); err != nil {
|
||||
if err := vs.BuildBlockParallel(ctx, sBlk, head, t); err != nil {
|
||||
return nil, errors.Wrap(err, "could not build block in parallel")
|
||||
}
|
||||
} else {
|
||||
@@ -162,6 +168,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err)
|
||||
}
|
||||
sBlk.SetStateRoot(sr)
|
||||
log.Infof("Computed state root at %s", time.Since(t))
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": req.Slot,
|
||||
@@ -191,7 +198,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: pb.(*ethpb.BeaconBlock)}}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.SignedBeaconBlock, head state.BeaconState) error {
|
||||
func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.SignedBeaconBlock, head state.BeaconState, startTime time.Time) error {
|
||||
// Build consensus fields in background
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
@@ -205,6 +212,7 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed
|
||||
log.WithError(err).Error("Could not get eth1data")
|
||||
}
|
||||
sBlk.SetEth1Data(eth1Data)
|
||||
log.Infof("checked eth1data majority at %s", time.Since(startTime))
|
||||
|
||||
// Set deposit and attestation.
|
||||
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits
|
||||
@@ -216,20 +224,27 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed
|
||||
sBlk.SetDeposits(deposits)
|
||||
sBlk.SetAttestations(atts)
|
||||
}
|
||||
log.Infof("packed deposits and attestations at %s", time.Since(startTime))
|
||||
|
||||
// Set slashings.
|
||||
validProposerSlashings, validAttSlashings := vs.getSlashings(ctx, head)
|
||||
sBlk.SetProposerSlashings(validProposerSlashings)
|
||||
sBlk.SetAttesterSlashings(validAttSlashings)
|
||||
|
||||
log.Infof("got slashings at %s", time.Since(startTime))
|
||||
|
||||
// Set exits.
|
||||
sBlk.SetVoluntaryExits(vs.getExits(head, sBlk.Block().Slot()))
|
||||
log.Infof("set voluntary exits at %s", time.Since(startTime))
|
||||
|
||||
// Set sync aggregate. New in Altair.
|
||||
vs.setSyncAggregate(ctx, sBlk)
|
||||
log.Infof("set sync aggregate at %s", time.Since(startTime))
|
||||
|
||||
// Set bls to execution change. New in Capella.
|
||||
vs.setBlsToExecData(sBlk, head)
|
||||
log.Infof("set bls data at %s", time.Since(startTime))
|
||||
|
||||
}()
|
||||
|
||||
localPayload, err := vs.getLocalPayload(ctx, sBlk.Block(), head)
|
||||
@@ -246,6 +261,7 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed
|
||||
if err := setExecutionData(ctx, sBlk, localPayload, builderPayload); err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not set execution data: %v", err)
|
||||
}
|
||||
log.Infof("set execution data at %s", time.Since(startTime))
|
||||
|
||||
wg.Wait() // Wait until block is built via consensus and execution fields.
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
@@ -23,6 +24,7 @@ func (vs *Server) packDepositsAndAttestations(ctx context.Context, head state.Be
|
||||
var atts []*ethpb.Attestation
|
||||
|
||||
eg.Go(func() error {
|
||||
stTime := time.Now()
|
||||
// Pack ETH1 deposits which have not been included in the beacon chain.
|
||||
localDeposits, err := vs.deposits(egctx, head, eth1Data)
|
||||
if err != nil {
|
||||
@@ -35,10 +37,13 @@ func (vs *Server) packDepositsAndAttestations(ctx context.Context, head state.Be
|
||||
default:
|
||||
}
|
||||
deposits = localDeposits
|
||||
log.Infof("took %s to retrieve deposits", time.Since(stTime))
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
eg.Go(func() error {
|
||||
stTime := time.Now()
|
||||
// Pack aggregated attestations which have not been included in the beacon chain.
|
||||
localAtts, err := vs.packAttestations(egctx, head)
|
||||
if err != nil {
|
||||
@@ -51,6 +56,7 @@ func (vs *Server) packDepositsAndAttestations(ctx context.Context, head state.Be
|
||||
default:
|
||||
}
|
||||
atts = localAtts
|
||||
log.Infof("took %s to retrieve attestations", time.Since(stTime))
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ func handle32ByteArrays(val [][32]byte, indices []uint64, convertAll bool) ([][3
|
||||
func handleValidatorSlice(val []*ethpb.Validator, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
if convertAll {
|
||||
length = len(val)
|
||||
return stateutil.OptimizedValidatorRoots(val)
|
||||
}
|
||||
roots := make([][32]byte, 0, length)
|
||||
rootCreator := func(input *ethpb.Validator) error {
|
||||
@@ -218,15 +218,6 @@ func handleValidatorSlice(val []*ethpb.Validator, indices []uint64, convertAll b
|
||||
roots = append(roots, newRoot)
|
||||
return nil
|
||||
}
|
||||
if convertAll {
|
||||
for i := range val {
|
||||
err := rootCreator(val[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
if len(val) > 0 {
|
||||
for _, idx := range indices {
|
||||
if idx > uint64(len(val))-1 {
|
||||
|
||||
@@ -155,6 +155,20 @@ func (e *epochBoundaryState) put(blockRoot [32]byte, s state.BeaconState) error
|
||||
func (e *epochBoundaryState) delete(blockRoot [32]byte) error {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
rInfo, ok, err := e.getByBlockRootLockFree(blockRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
slotInfo := &slotRootInfo{
|
||||
slot: rInfo.state.Slot(),
|
||||
blockRoot: blockRoot,
|
||||
}
|
||||
if err = e.slotRootCache.Delete(slotInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.rootStateCache.Delete(&rootStateInfo{
|
||||
root: blockRoot,
|
||||
})
|
||||
|
||||
@@ -36,12 +36,12 @@ func (_ *State) replayBlocks(
|
||||
var err error
|
||||
|
||||
start := time.Now()
|
||||
log = log.WithFields(logrus.Fields{
|
||||
rLog := log.WithFields(logrus.Fields{
|
||||
"startSlot": state.Slot(),
|
||||
"endSlot": targetSlot,
|
||||
"diff": targetSlot - state.Slot(),
|
||||
})
|
||||
log.Debug("Replaying state")
|
||||
rLog.Debug("Replaying state")
|
||||
// The input block list is sorted in decreasing slots order.
|
||||
if len(signed) > 0 {
|
||||
for i := len(signed) - 1; i >= 0; i-- {
|
||||
@@ -71,7 +71,7 @@ func (_ *State) replayBlocks(
|
||||
}
|
||||
|
||||
duration := time.Since(start)
|
||||
log.WithFields(logrus.Fields{
|
||||
rLog.WithFields(logrus.Fields{
|
||||
"duration": duration,
|
||||
}).Debug("Replayed state")
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@ package stategen
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
||||
@@ -79,6 +81,41 @@ func (s *State) saveStateByRoot(ctx context.Context, blockRoot [32]byte, st stat
|
||||
if err := s.epochBoundaryStateCache.put(blockRoot, st); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Always check that the correct epoch boundary states have been saved
|
||||
// for the current epoch.
|
||||
epochStart, err := slots.EpochStart(slots.ToEpoch(st.Slot()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bRoot, err := helpers.BlockRootAtSlot(st, epochStart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, ok, err := s.epochBoundaryStateCache.getByBlockRoot([32]byte(bRoot))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We would only recover the boundary states under this condition:
|
||||
//
|
||||
// 1) Would indicate that the epoch boundary was skipped due to a missed slot, we
|
||||
// then recover by saving the state at that particular slot here.
|
||||
if !ok {
|
||||
// Only recover the state if it is in our hot state cache, otherwise we
|
||||
// simply skip this step.
|
||||
if s.hotStateCache.has([32]byte(bRoot)) {
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": epochStart,
|
||||
"root": fmt.Sprintf("%#x", bRoot),
|
||||
}).Debug("Recovering state for epoch boundary cache")
|
||||
|
||||
hState := s.hotStateCache.get([32]byte(bRoot))
|
||||
if err := s.epochBoundaryStateCache.put([32]byte(bRoot), hState); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// On an intermediate slot, save state summary.
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
testDB "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/v4/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/util"
|
||||
@@ -137,6 +138,34 @@ func TestSaveState_NoSaveNotEpochBoundary(t *testing.T) {
|
||||
require.Equal(t, false, beaconDB.HasState(ctx, r))
|
||||
}
|
||||
|
||||
func TestSaveState_RecoverForEpochBoundary(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := New(beaconDB, doublylinkedtree.New())
|
||||
|
||||
beaconState, _ := util.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch-1))
|
||||
r := [32]byte{'A'}
|
||||
boundaryRoot := [32]byte{'B'}
|
||||
require.NoError(t, beaconState.UpdateBlockRootAtIndex(0, boundaryRoot))
|
||||
|
||||
b := util.NewBeaconBlock()
|
||||
util.SaveBlock(t, ctx, beaconDB, b)
|
||||
gRoot, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
// Save boundary state to the hot state cache.
|
||||
boundaryState, _ := util.DeterministicGenesisState(t, 32)
|
||||
service.hotStateCache.put(boundaryRoot, boundaryState)
|
||||
require.NoError(t, service.SaveState(ctx, r, beaconState))
|
||||
|
||||
rInfo, ok, err := service.epochBoundaryStateCache.getByBlockRoot(boundaryRoot)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, ok, "state does not exist in cache")
|
||||
assert.Equal(t, rInfo.root, boundaryRoot, "incorrect root of root state info")
|
||||
assert.Equal(t, rInfo.state.Slot(), primitives.Slot(0), "incorrect slot of state")
|
||||
}
|
||||
|
||||
func TestSaveState_CanSaveHotStateToDB(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -30,7 +30,7 @@ func ValidatorRegistryRoot(vals []*ethpb.Validator) ([32]byte, error) {
|
||||
}
|
||||
|
||||
func validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) {
|
||||
roots, err := optimizedValidatorRoots(validators)
|
||||
roots, err := OptimizedValidatorRoots(validators)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
@@ -51,7 +51,9 @@ func validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func optimizedValidatorRoots(validators []*ethpb.Validator) ([][32]byte, error) {
|
||||
// OptimizedValidatorRoots uses an optimized routine with gohashtree in order to
|
||||
// derive a list of validator roots from a list of validator objects.
|
||||
func OptimizedValidatorRoots(validators []*ethpb.Validator) ([][32]byte, error) {
|
||||
// Exit early if no validators are provided.
|
||||
if len(validators) == 0 {
|
||||
return [][32]byte{}, nil
|
||||
|
||||
@@ -139,7 +139,7 @@ func (s *Service) writeBlockBatchToStream(ctx context.Context, batch blockBatch,
|
||||
continue
|
||||
}
|
||||
if chunkErr := s.chunkBlockWriter(stream, b); chunkErr != nil {
|
||||
log.WithError(chunkErr).Error("Could not send a chunked response")
|
||||
log.WithError(chunkErr).Debug("Could not send a chunked response")
|
||||
return chunkErr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,11 +202,7 @@ var (
|
||||
Usage: "Sets the maximum number of headers that a deposit log query can fetch.",
|
||||
Value: uint64(1000),
|
||||
}
|
||||
// EnableRegistrationCache a temporary flag for enabling the validator registration cache instead of db.
|
||||
EnableRegistrationCache = &cli.BoolFlag{
|
||||
Name: "enable-registration-cache",
|
||||
Usage: "A temporary flag for enabling the validator registration cache instead of persisting in db. The cache will clear on restart.",
|
||||
}
|
||||
|
||||
// WeakSubjectivityCheckpoint defines the weak subjectivity checkpoint the node must sync through to defend against long range attacks.
|
||||
WeakSubjectivityCheckpoint = &cli.StringFlag{
|
||||
Name: "weak-subjectivity-checkpoint",
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
runtimeDebug "runtime/debug"
|
||||
|
||||
gethlog "github.com/ethereum/go-ethereum/log"
|
||||
@@ -58,7 +59,6 @@ var appFlags = []cli.Flag{
|
||||
flags.InteropGenesisTimeFlag,
|
||||
flags.SlotsPerArchivedPoint,
|
||||
flags.EnableDebugRPCEndpoints,
|
||||
flags.EnableRegistrationCache,
|
||||
flags.SubscribeToAllSubnets,
|
||||
flags.HistoricalSlasherNode,
|
||||
flags.ChainID,
|
||||
@@ -204,6 +204,7 @@ func main() {
|
||||
if err := fdlimits.SetMaxFdLimits(); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime.GOMAXPROCS(2)
|
||||
return cmd.ValidateNoArgs(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,6 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.BlockBatchLimit,
|
||||
flags.BlockBatchLimitBurstFactor,
|
||||
flags.EnableDebugRPCEndpoints,
|
||||
flags.EnableRegistrationCache,
|
||||
flags.SubscribeToAllSubnets,
|
||||
flags.HistoricalSlasherNode,
|
||||
flags.ChainID,
|
||||
|
||||
@@ -32,6 +32,12 @@ var (
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
deprecatedEnableRegistrationCache = &cli.BoolFlag{
|
||||
Name: "enable-registration-cache",
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
|
||||
// Deprecated flags for both the beacon node and validator client.
|
||||
@@ -41,6 +47,7 @@ var deprecatedFlags = []cli.Flag{
|
||||
deprecatedEnableReorgLateBlocks,
|
||||
deprecatedDisableGossipBatchAggregation,
|
||||
deprecatedBuildBlockParallel,
|
||||
deprecatedEnableRegistrationCache,
|
||||
}
|
||||
|
||||
// deprecatedBeaconFlags contains flags that are still used by other components
|
||||
|
||||
@@ -148,6 +148,13 @@ var (
|
||||
Name: "disable-resource-manager",
|
||||
Usage: "Disables running the libp2p resource manager",
|
||||
}
|
||||
|
||||
// DisableRegistrationCache a flag for disabling the validator registration cache and use db instead.
|
||||
DisableRegistrationCache = &cli.BoolFlag{
|
||||
Name: "diable-registration-cache",
|
||||
Usage: "A temporary flag for disabling the validator registration cache instead of using the db. note: registrations do not clear on restart while using the db",
|
||||
}
|
||||
|
||||
aggregateParallel = &cli.BoolFlag{
|
||||
Name: "aggregate-parallel",
|
||||
Usage: "Enables parallel aggregation of attestations",
|
||||
@@ -204,6 +211,7 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c
|
||||
aggregateSecondInterval,
|
||||
aggregateThirdInterval,
|
||||
disableResourceManager,
|
||||
DisableRegistrationCache,
|
||||
aggregateParallel,
|
||||
}...)...)
|
||||
|
||||
|
||||
@@ -84,6 +84,15 @@ type ProposerSettings struct {
|
||||
DefaultConfig *ProposerOption
|
||||
}
|
||||
|
||||
// ShouldBeSaved goes through checks to see if the value should be saveable
|
||||
// Pseudocode: conditions for being saved into the database
|
||||
// 1. settings are not nil
|
||||
// 2. proposeconfig is not nil (this defines specific settings for each validator key), default config can be nil in this case and fall back to beacon node settings
|
||||
// 3. defaultconfig is not nil, meaning it has at least fee recipient settings (this defines general settings for all validator keys but keys will use settings from propose config if available), propose config can be nil in this case
|
||||
func (settings *ProposerSettings) ShouldBeSaved() bool {
|
||||
return settings != nil && (settings.ProposeConfig != nil || settings.DefaultConfig != nil && settings.DefaultConfig.FeeRecipientConfig != nil)
|
||||
}
|
||||
|
||||
// ToPayload converts struct to ProposerSettingsPayload
|
||||
func (ps *ProposerSettings) ToPayload() *validatorpb.ProposerSettingsPayload {
|
||||
if ps == nil {
|
||||
|
||||
@@ -98,3 +98,117 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestProposerSettings_ShouldBeSaved(t *testing.T) {
|
||||
key1hex := "0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a"
|
||||
key1, err := hexutil.Decode(key1hex)
|
||||
require.NoError(t, err)
|
||||
type fields struct {
|
||||
ProposeConfig map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption
|
||||
DefaultConfig *ProposerOption
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "Should be saved, proposeconfig populated and no default config",
|
||||
fields: fields{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
BuilderConfig: &BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(40000000),
|
||||
Relays: []string{"https://example-relay.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: nil,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "Should be saved, default populated and no proposeconfig ",
|
||||
fields: fields{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &ProposerOption{
|
||||
FeeRecipientConfig: &FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
BuilderConfig: &BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(40000000),
|
||||
Relays: []string{"https://example-relay.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "Should be saved, all populated",
|
||||
fields: fields{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
BuilderConfig: &BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(40000000),
|
||||
Relays: []string{"https://example-relay.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &ProposerOption{
|
||||
FeeRecipientConfig: &FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
BuilderConfig: &BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(40000000),
|
||||
Relays: []string{"https://example-relay.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "Should not be saved, proposeconfig not populated and default not populated",
|
||||
fields: fields{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: nil,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "Should not be saved, builder data only",
|
||||
fields: fields{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &ProposerOption{
|
||||
BuilderConfig: &BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(40000000),
|
||||
Relays: []string{"https://example-relay.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
settings := &ProposerSettings{
|
||||
ProposeConfig: tt.fields.ProposeConfig,
|
||||
DefaultConfig: tt.fields.DefaultConfig,
|
||||
}
|
||||
if got := settings.ShouldBeSaved(); got != tt.want {
|
||||
t.Errorf("ShouldBeSaved() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,11 @@
|
||||
package blst
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
blst "github.com/supranational/blst/bindings/go"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Reserve 1 core for general application work
|
||||
maxProcs := runtime.GOMAXPROCS(0) - 1
|
||||
if maxProcs <= 0 {
|
||||
maxProcs = 1
|
||||
}
|
||||
maxProcs := 1
|
||||
blst.SetMaxProcs(maxProcs)
|
||||
}
|
||||
|
||||
9
deps.bzl
9
deps.bzl
@@ -4867,12 +4867,3 @@ def prysm_deps():
|
||||
sum = "h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=",
|
||||
version = "v1.24.0",
|
||||
)
|
||||
|
||||
# Note: go_repository is already wrapped with maybe!
|
||||
maybe(
|
||||
git_repository,
|
||||
name = "vaticle_bazel_distribution",
|
||||
commit = "96424c85195a97dad81f69fdbbef2e1574bf8801",
|
||||
remote = "https://github.com/vaticle/bazel-distribution",
|
||||
shallow_since = "1569509514 +0300",
|
||||
)
|
||||
|
||||
@@ -134,6 +134,7 @@ func TestUnmarshalState(t *testing.T) {
|
||||
}()
|
||||
bc := params.BeaconConfig()
|
||||
altairSlot, err := slots.EpochStart(bc.AltairForkEpoch)
|
||||
require.NoError(t, err)
|
||||
bellaSlot, err := slots.EpochStart(bc.BellatrixForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
@@ -205,6 +206,7 @@ func TestUnmarshalBlock(t *testing.T) {
|
||||
altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion)
|
||||
bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion)
|
||||
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
||||
require.NoError(t, err)
|
||||
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
@@ -296,6 +298,7 @@ func TestUnmarshalBlindedBlock(t *testing.T) {
|
||||
altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion)
|
||||
bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion)
|
||||
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
||||
require.NoError(t, err)
|
||||
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
||||
require.NoError(t, err)
|
||||
cases := []struct {
|
||||
|
||||
@@ -147,11 +147,11 @@
|
||||
}
|
||||
},
|
||||
"ineffassign": {
|
||||
"only_files": {
|
||||
"beacon-chain/.*": "",
|
||||
"shared/.*": "",
|
||||
"slasher/.*": "",
|
||||
"validator/.*": ""
|
||||
"exclude_files": {
|
||||
"external/.*": "Third party code",
|
||||
"rules_go_work-.*": "Third party code",
|
||||
".*\\.pb.*.go": "Generated code is ok",
|
||||
".*generated\\.ssz\\.go": "Generated code is ok"
|
||||
}
|
||||
},
|
||||
"properpermissions": {
|
||||
|
||||
@@ -256,7 +256,7 @@ func (c *componentHandler) required() []e2etypes.ComponentRunner {
|
||||
func (c *componentHandler) printPIDs(logger func(string, ...interface{})) {
|
||||
msg := "\nPID of components. Attach a debugger... if you dare!\n\n"
|
||||
|
||||
msg = "This test PID: " + strconv.Itoa(os.Getpid()) + " (parent=" + strconv.Itoa(os.Getppid()) + ")\n"
|
||||
msg += "This test PID: " + strconv.Itoa(os.Getpid()) + " (parent=" + strconv.Itoa(os.Getppid()) + ")\n"
|
||||
|
||||
// Beacon chain nodes
|
||||
msg += fmt.Sprintf("Beacon chain nodes: %v\n", PIDsFromMultiComponentRunner(c.beaconNodes))
|
||||
|
||||
@@ -114,7 +114,7 @@ func SendTransaction(client *rpc.Client, key *ecdsa.PrivateKey, f *filler.Filler
|
||||
for i := uint64(0); i < N; i++ {
|
||||
index := i
|
||||
g.Go(func() error {
|
||||
tx, err := txfuzz.RandomValidTx(client, f, sender, nonce+index, expectedPrice, nil, al)
|
||||
tx, err := txfuzz.RandomValidTx(client, f, sender, nonce+index, gasPrice, nil, al)
|
||||
if err != nil {
|
||||
// In the event the transaction constructed is not valid, we continue with the routine
|
||||
// rather than complete stop it.
|
||||
@@ -129,9 +129,12 @@ func SendTransaction(client *rpc.Client, key *ecdsa.PrivateKey, f *filler.Filler
|
||||
return nil
|
||||
}
|
||||
err = backend.SendTransaction(context.Background(), signedTx)
|
||||
// We continue on if the constructed transaction is invalid
|
||||
// and can't be submitted on chain.
|
||||
//nolint:nilerr
|
||||
if err != nil {
|
||||
// We continue on if the constructed transaction is invalid
|
||||
// and can't be submitted on chain.
|
||||
//nolint:nilerr
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -172,11 +172,6 @@ func (v *LighthouseValidatorNode) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
_, _, index, _ := v.config, v.validatorNum, v.index, v.offset
|
||||
beaconRPCPort := e2e.TestParams.Ports.PrysmBeaconNodeRPCPort + index
|
||||
if beaconRPCPort >= e2e.TestParams.Ports.PrysmBeaconNodeRPCPort+e2e.TestParams.BeaconNodeCount {
|
||||
// Point any extra validator clients to a node we know is running.
|
||||
beaconRPCPort = e2e.TestParams.Ports.PrysmBeaconNodeRPCPort
|
||||
}
|
||||
kPath := e2e.TestParams.TestPath + fmt.Sprintf("/lighthouse-validator-%d", index)
|
||||
testNetDir := e2e.TestParams.TestPath + fmt.Sprintf("/lighthouse-testnet-%d", index)
|
||||
httpPort := e2e.TestParams.Ports.LighthouseBeaconNodeHTTPPort
|
||||
|
||||
@@ -516,7 +516,6 @@ func (r *testRunner) defaultEndToEndRun() error {
|
||||
if err := r.testCheckpointSync(ctx, g, index, conns, httpEndpoints[0], benr, menr); err != nil {
|
||||
return errors.Wrap(err, "checkpoint sync test failed")
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
|
||||
if config.ExtraEpochs > 0 {
|
||||
|
||||
@@ -92,113 +92,113 @@ type MockValidator struct {
|
||||
proposerSettings *validatorserviceconfig.ProposerSettings
|
||||
}
|
||||
|
||||
func (_ MockValidator) LogSyncCommitteeMessagesSubmitted() {}
|
||||
func (_ *MockValidator) LogSyncCommitteeMessagesSubmitted() {}
|
||||
|
||||
func (_ MockValidator) Done() {
|
||||
func (_ *MockValidator) Done() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) WaitForChainStart(_ context.Context) error {
|
||||
func (_ *MockValidator) WaitForChainStart(_ context.Context) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) WaitForSync(_ context.Context) error {
|
||||
func (_ *MockValidator) WaitForSync(_ context.Context) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) WaitForActivation(_ context.Context, _ chan [][48]byte) error {
|
||||
func (_ *MockValidator) WaitForActivation(_ context.Context, _ chan [][48]byte) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) CanonicalHeadSlot(_ context.Context) (primitives.Slot, error) {
|
||||
func (_ *MockValidator) CanonicalHeadSlot(_ context.Context) (primitives.Slot, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) NextSlot() <-chan primitives.Slot {
|
||||
func (_ *MockValidator) NextSlot() <-chan primitives.Slot {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) SlotDeadline(_ primitives.Slot) time.Time {
|
||||
func (_ *MockValidator) SlotDeadline(_ primitives.Slot) time.Time {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) LogValidatorGainsAndLosses(_ context.Context, _ primitives.Slot) error {
|
||||
func (_ *MockValidator) LogValidatorGainsAndLosses(_ context.Context, _ primitives.Slot) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) UpdateDuties(_ context.Context, _ primitives.Slot) error {
|
||||
func (_ *MockValidator) UpdateDuties(_ context.Context, _ primitives.Slot) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) RolesAt(_ context.Context, _ primitives.Slot) (map[[48]byte][]iface2.ValidatorRole, error) {
|
||||
func (_ *MockValidator) RolesAt(_ context.Context, _ primitives.Slot) (map[[48]byte][]iface2.ValidatorRole, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) SubmitAttestation(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
func (_ *MockValidator) SubmitAttestation(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) ProposeBlock(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
func (_ *MockValidator) ProposeBlock(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) SubmitAggregateAndProof(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
func (_ *MockValidator) SubmitAggregateAndProof(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) SubmitSyncCommitteeMessage(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
func (_ *MockValidator) SubmitSyncCommitteeMessage(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) SubmitSignedContributionAndProof(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
func (_ *MockValidator) SubmitSignedContributionAndProof(_ context.Context, _ primitives.Slot, _ [48]byte) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) LogAttestationsSubmitted() {
|
||||
func (_ *MockValidator) LogAttestationsSubmitted() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) UpdateDomainDataCaches(_ context.Context, _ primitives.Slot) {
|
||||
func (_ *MockValidator) UpdateDomainDataCaches(_ context.Context, _ primitives.Slot) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) WaitForKeymanagerInitialization(_ context.Context) error {
|
||||
func (_ *MockValidator) WaitForKeymanagerInitialization(_ context.Context) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m MockValidator) Keymanager() (keymanager.IKeymanager, error) {
|
||||
func (m *MockValidator) Keymanager() (keymanager.IKeymanager, error) {
|
||||
return m.Km, nil
|
||||
}
|
||||
|
||||
func (_ MockValidator) ReceiveBlocks(_ context.Context, _ chan<- error) {
|
||||
func (_ *MockValidator) ReceiveBlocks(_ context.Context, _ chan<- error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) HandleKeyReload(_ context.Context, _ [][48]byte) (bool, error) {
|
||||
func (_ *MockValidator) HandleKeyReload(_ context.Context, _ [][48]byte) (bool, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (_ MockValidator) CheckDoppelGanger(_ context.Context) error {
|
||||
func (_ *MockValidator) CheckDoppelGanger(_ context.Context) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
// HasProposerSettings for mocking
|
||||
func (MockValidator) HasProposerSettings() bool {
|
||||
func (*MockValidator) HasProposerSettings() bool {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
// PushProposerSettings for mocking
|
||||
func (_ MockValidator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager, _ primitives.Slot, _ time.Time) error {
|
||||
func (_ *MockValidator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager, _ primitives.Slot, _ time.Time) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
// SetPubKeyToValidatorIndexMap for mocking
|
||||
func (_ MockValidator) SetPubKeyToValidatorIndexMap(_ context.Context, _ keymanager.IKeymanager) error {
|
||||
func (_ *MockValidator) SetPubKeyToValidatorIndexMap(_ context.Context, _ keymanager.IKeymanager) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
// SignValidatorRegistrationRequest for mocking
|
||||
func (_ MockValidator) SignValidatorRegistrationRequest(_ context.Context, _ iface2.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) {
|
||||
func (_ *MockValidator) SignValidatorRegistrationRequest(_ context.Context, _ iface2.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
@@ -208,6 +208,7 @@ func (m *MockValidator) ProposerSettings() *validatorserviceconfig.ProposerSetti
|
||||
}
|
||||
|
||||
// SetProposerSettings for mocking
|
||||
func (m *MockValidator) SetProposerSettings(settings *validatorserviceconfig.ProposerSettings) {
|
||||
func (m *MockValidator) SetProposerSettings(_ context.Context, settings *validatorserviceconfig.ProposerSettings) error {
|
||||
m.proposerSettings = settings
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ type Validator interface {
|
||||
PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot, deadline time.Time) error
|
||||
SignValidatorRegistrationRequest(ctx context.Context, signer SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error)
|
||||
ProposerSettings() *validatorserviceconfig.ProposerSettings
|
||||
SetProposerSettings(*validatorserviceconfig.ProposerSettings)
|
||||
SetProposerSettings(context.Context, *validatorserviceconfig.ProposerSettings) error
|
||||
}
|
||||
|
||||
// SigningFunc interface defines a type for the a function that signs a message
|
||||
|
||||
@@ -58,7 +58,7 @@ func run(ctx context.Context, v iface.Validator) {
|
||||
if v.ProposerSettings() != nil {
|
||||
log.Infof("Validator client started with provided proposer settings that sets options such as fee recipient"+
|
||||
" and will periodically update the beacon node and custom builder (if --%s)", flags.EnableBuilderFlag.Name)
|
||||
deadline := time.Now().Add(time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
|
||||
deadline := time.Now().Add(5 * time.Minute)
|
||||
if err := v.PushProposerSettings(ctx, km, headSlot, deadline); err != nil {
|
||||
if errors.Is(err, ErrBuilderValidatorRegistration) {
|
||||
log.WithError(err).Warn("Push proposer settings error")
|
||||
@@ -67,7 +67,7 @@ func run(ctx context.Context, v iface.Validator) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Warnln("Validator client started without proposer settings such as fee recipient" +
|
||||
log.Warn("Validator client started without proposer settings such as fee recipient" +
|
||||
" and will continue to use settings provided in the beacon node.")
|
||||
}
|
||||
|
||||
@@ -108,9 +108,10 @@ func run(ctx context.Context, v iface.Validator) {
|
||||
continue
|
||||
}
|
||||
|
||||
if slots.IsEpochStart(slot) && v.ProposerSettings() != nil {
|
||||
// create call on a separate thread to push proposer settings from the middle of an epoch.
|
||||
if slots.SinceEpochStarts(slot) == params.BeaconConfig().SlotsPerEpoch/2 && v.ProposerSettings() != nil {
|
||||
go func() {
|
||||
// deadline set for end of epoch
|
||||
// deadline set for 1 epoch from call to not overlap.
|
||||
epochDeadline := v.SlotDeadline(slot + params.BeaconConfig().SlotsPerEpoch - 1)
|
||||
if err := v.PushProposerSettings(ctx, km, slot, epochDeadline); err != nil {
|
||||
log.WithError(err).Warn("Failed to update proposer settings")
|
||||
|
||||
@@ -225,13 +225,14 @@ func notActive(t *testing.T) [fieldparams.BLSPubkeyLength]byte {
|
||||
|
||||
func TestUpdateProposerSettingsAt_EpochStart(t *testing.T) {
|
||||
v := &testutil.FakeValidator{Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err := v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
hook := logTest.NewGlobal()
|
||||
slot := params.BeaconConfig().SlotsPerEpoch
|
||||
@@ -247,39 +248,16 @@ func TestUpdateProposerSettingsAt_EpochStart(t *testing.T) {
|
||||
assert.LogsContain(t, hook, "updated proposer settings")
|
||||
}
|
||||
|
||||
func TestUpdateProposerSettingsAt_EpochEndExceeded(t *testing.T) {
|
||||
v := &testutil.FakeValidator{Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}, ProposerSettingWait: time.Duration(params.BeaconConfig().SecondsPerSlot+1) * time.Second}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
hook := logTest.NewGlobal()
|
||||
slot := params.BeaconConfig().SlotsPerEpoch - 1 //have it set close to the end of epoch
|
||||
ticker := make(chan primitives.Slot)
|
||||
v.NextSlotRet = ticker
|
||||
go func() {
|
||||
ticker <- slot
|
||||
cancel()
|
||||
}()
|
||||
|
||||
run(ctx, v)
|
||||
// can't test "Failed to update proposer settings" because of log.fatal
|
||||
assert.LogsContain(t, hook, "deadline exceeded")
|
||||
}
|
||||
|
||||
func TestUpdateProposerSettingsAt_EpochEndOk(t *testing.T) {
|
||||
v := &testutil.FakeValidator{Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}, ProposerSettingWait: time.Duration(params.BeaconConfig().SecondsPerSlot-1) * time.Second}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err := v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
hook := logTest.NewGlobal()
|
||||
slot := params.BeaconConfig().SlotsPerEpoch - 1 //have it set close to the end of epoch
|
||||
@@ -301,13 +279,14 @@ func TestUpdateProposerSettings_ContinuesAfterValidatorRegistrationFails(t *test
|
||||
ProposerSettingsErr: errors.Wrap(ErrBuilderValidatorRegistration, errSomeotherError.Error()),
|
||||
Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}},
|
||||
}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err := v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
hook := logTest.NewGlobal()
|
||||
slot := params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
@@ -188,14 +188,6 @@ func (v *ValidatorService) Start() {
|
||||
return
|
||||
}
|
||||
|
||||
// checks db if proposer settings exist if none is provided.
|
||||
if v.proposerSettings == nil {
|
||||
settings, err := v.db.ProposerSettings(v.ctx)
|
||||
if err == nil {
|
||||
v.proposerSettings = settings
|
||||
}
|
||||
}
|
||||
|
||||
validatorClient := validatorClientFactory.NewValidatorClient(v.conn)
|
||||
beaconClient := beaconChainClientFactory.NewBeaconChainClient(v.conn)
|
||||
|
||||
@@ -283,15 +275,13 @@ func (v *ValidatorService) ProposerSettings() *validatorserviceconfig.ProposerSe
|
||||
|
||||
// SetProposerSettings sets the proposer settings on the validator service as well as the underlying validator
|
||||
func (v *ValidatorService) SetProposerSettings(ctx context.Context, settings *validatorserviceconfig.ProposerSettings) error {
|
||||
if v.db == nil {
|
||||
return errors.New("db is not set")
|
||||
}
|
||||
if err := v.db.SaveProposerSettings(ctx, settings); err != nil {
|
||||
return err
|
||||
}
|
||||
// validator service proposer settings is only used for pass through from node -> validator service -> validator.
|
||||
// in memory use of proposer settings happens on validator.
|
||||
v.proposerSettings = settings
|
||||
v.validator.SetProposerSettings(settings)
|
||||
return nil
|
||||
|
||||
// passes settings down to be updated in database and saved in memory.
|
||||
// updates to validator porposer settings will be in the validator object and not validator service.
|
||||
return v.validator.SetProposerSettings(ctx, settings)
|
||||
}
|
||||
|
||||
// ConstructDialOptions constructs a list of grpc dial options
|
||||
|
||||
@@ -281,6 +281,7 @@ func (f *FakeValidator) ProposerSettings() *validatorserviceconfig.ProposerSetti
|
||||
}
|
||||
|
||||
// SetProposerSettings for mocking
|
||||
func (f *FakeValidator) SetProposerSettings(settings *validatorserviceconfig.ProposerSettings) {
|
||||
func (f *FakeValidator) SetProposerSettings(_ context.Context, settings *validatorserviceconfig.ProposerSettings) error {
|
||||
f.proposerSettings = settings
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -953,12 +953,21 @@ func (v *validator) logDuties(slot primitives.Slot, duties []*ethpb.DutiesRespon
|
||||
}
|
||||
}
|
||||
|
||||
// ProposerSettings gets the current proposer settings saved in memory validator
|
||||
func (v *validator) ProposerSettings() *validatorserviceconfig.ProposerSettings {
|
||||
return v.proposerSettings
|
||||
}
|
||||
|
||||
func (v *validator) SetProposerSettings(settings *validatorserviceconfig.ProposerSettings) {
|
||||
// SetProposerSettings sets and saves the passed in proposer settings overriding the in memory one
|
||||
func (v *validator) SetProposerSettings(ctx context.Context, settings *validatorserviceconfig.ProposerSettings) error {
|
||||
if v.db == nil {
|
||||
return errors.New("db is not set")
|
||||
}
|
||||
if err := v.db.SaveProposerSettings(ctx, settings); err != nil {
|
||||
return err
|
||||
}
|
||||
v.proposerSettings = settings
|
||||
return nil
|
||||
}
|
||||
|
||||
// PushProposerSettings calls the prepareBeaconProposer RPC to set the fee recipient and also the register validator API if using a custom builder.
|
||||
|
||||
@@ -1403,7 +1403,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
GasLimit: 40000000,
|
||||
},
|
||||
}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1415,6 +1415,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
client.EXPECT().SubmitValidatorRegistrations(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
@@ -1484,7 +1485,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
GasLimit: 40000000,
|
||||
},
|
||||
}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1496,6 +1497,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
client.EXPECT().SubmitValidatorRegistrations(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
@@ -1557,7 +1559,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1565,6 +1567,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return &v
|
||||
},
|
||||
feeRecipientMap: map[primitives.ValidatorIndex]string{
|
||||
@@ -1599,7 +1602,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1611,6 +1614,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
|
||||
client.EXPECT().MultipleValidatorStatus(
|
||||
gomock.Any(),
|
||||
@@ -1659,7 +1663,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
}
|
||||
err := v.WaitForKeymanagerInitialization(ctx)
|
||||
require.NoError(t, err)
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1671,6 +1675,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
km, err := v.Keymanager()
|
||||
require.NoError(t, err)
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
@@ -1745,7 +1750,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
FeeRecipient: common.Address{},
|
||||
},
|
||||
}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1753,6 +1758,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return &v
|
||||
},
|
||||
},
|
||||
@@ -1787,7 +1793,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1795,6 +1801,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return &v
|
||||
},
|
||||
},
|
||||
@@ -1838,7 +1845,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
GasLimit: 40000000,
|
||||
},
|
||||
}
|
||||
v.SetProposerSettings(&validatorserviceconfig.ProposerSettings{
|
||||
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
@@ -1850,6 +1857,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},
|
||||
|
||||
@@ -121,6 +121,11 @@ func (s *Store) ProposerSettingsExists(ctx context.Context) (bool, error) {
|
||||
func (s *Store) SaveProposerSettings(ctx context.Context, settings *validatorServiceConfig.ProposerSettings) error {
|
||||
_, span := trace.StartSpan(ctx, "validator.db.SaveProposerSettings")
|
||||
defer span.End()
|
||||
// nothing to save
|
||||
if !settings.ShouldBeSaved() {
|
||||
log.Warn("proposer settings are empty, nothing has been saved")
|
||||
return nil
|
||||
}
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(proposerSettingsBucket)
|
||||
m, err := proto.Marshal(settings.ToPayload())
|
||||
|
||||
@@ -16,6 +16,7 @@ go_test(
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//validator/accounts:go_default_library",
|
||||
"//validator/db/iface:go_default_library",
|
||||
"//validator/db/testing:go_default_library",
|
||||
"//validator/keymanager:go_default_library",
|
||||
"//validator/keymanager/remote-web3signer:go_default_library",
|
||||
|
||||
@@ -227,6 +227,7 @@ func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
if dataDir == "" && c.wallet != nil {
|
||||
dataDir = c.wallet.AccountsDir()
|
||||
if dataDir == "" {
|
||||
// skipcq: RVV-A0003
|
||||
log.Fatal(
|
||||
"Could not determine your system'c HOME path, please specify a --datadir you wish " +
|
||||
"to use for your validator data",
|
||||
@@ -310,6 +311,7 @@ func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
if dataDir == "" {
|
||||
dataDir = cmd.DefaultDataDir()
|
||||
if dataDir == "" {
|
||||
// skipcq: RVV-A0003
|
||||
log.Fatal(
|
||||
"Could not determine your system'c HOME path, please specify a --datadir you wish " +
|
||||
"to use for your validator data",
|
||||
@@ -496,21 +498,20 @@ func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*validatorServ
|
||||
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) && cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
|
||||
return nil, errors.New("cannot specify both " + flags.ProposerSettingsFlag.Name + " and " + flags.ProposerSettingsURLFlag.Name)
|
||||
}
|
||||
|
||||
builderConfigFromFlag, err := BuilderSettingsFromFlags(cliCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// is overridden by file and URL flags
|
||||
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) &&
|
||||
!cliCtx.IsSet(flags.ProposerSettingsFlag.Name) &&
|
||||
!cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
|
||||
suggestedFee := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)
|
||||
builderConfig, err := BuilderSettingsFromFlags(cliCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileConfig = &validatorpb.ProposerSettingsPayload{
|
||||
ProposerConfig: nil,
|
||||
DefaultConfig: &validatorpb.ProposerOptionPayload{
|
||||
FeeRecipient: suggestedFee,
|
||||
Builder: builderConfig.ToPayload(),
|
||||
Builder: builderConfigFromFlag.ToPayload(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -526,13 +527,13 @@ func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*validatorServ
|
||||
}
|
||||
}
|
||||
|
||||
// nothing is set, so just return nil
|
||||
// this condition triggers if SuggestedFeeRecipientFlag,ProposerSettingsFlag or ProposerSettingsURLFlag did not create any settings
|
||||
if fileConfig == nil {
|
||||
if cliCtx.Bool(flags.EnableBuilderFlag.Name) {
|
||||
return nil, fmt.Errorf("%s flag can only be used when a default fee recipient is present on the validator client", flags.EnableBuilderFlag.Name)
|
||||
}
|
||||
return nil, nil
|
||||
// Checks the db or enable builder settings before starting the node without proposer settings
|
||||
// starting the node without proposer settings, will skip API calls for push proposer settings and register validator
|
||||
return handleNoProposerSettingsFlagsProvided(cliCtx, db, builderConfigFromFlag)
|
||||
}
|
||||
|
||||
// convert file config to proposer config for internal use
|
||||
vpSettings := &validatorServiceConfig.ProposerSettings{}
|
||||
|
||||
@@ -556,16 +557,13 @@ func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*validatorServ
|
||||
},
|
||||
BuilderConfig: validatorServiceConfig.ToBuilderConfig(fileConfig.DefaultConfig.Builder),
|
||||
}
|
||||
if vpSettings.DefaultConfig.BuilderConfig == nil {
|
||||
builderConfig, err := BuilderSettingsFromFlags(cliCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vpSettings.DefaultConfig.BuilderConfig = builderConfig
|
||||
}
|
||||
|
||||
if vpSettings.DefaultConfig.BuilderConfig != nil {
|
||||
vpSettings.DefaultConfig.BuilderConfig.GasLimit = reviewGasLimit(vpSettings.DefaultConfig.BuilderConfig.GasLimit)
|
||||
if builderConfigFromFlag != nil {
|
||||
config := builderConfigFromFlag
|
||||
if config.GasLimit == validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit) && vpSettings.DefaultConfig.BuilderConfig != nil {
|
||||
config.GasLimit = vpSettings.DefaultConfig.BuilderConfig.GasLimit
|
||||
}
|
||||
vpSettings.DefaultConfig.BuilderConfig = config
|
||||
}
|
||||
|
||||
if psExists {
|
||||
@@ -594,14 +592,14 @@ func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*validatorServ
|
||||
if err := warnNonChecksummedAddress(option.FeeRecipient); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if option.Builder != nil {
|
||||
option.Builder.GasLimit = reviewGasLimit(option.Builder.GasLimit)
|
||||
} else {
|
||||
builderConfig, err := BuilderSettingsFromFlags(cliCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if builderConfigFromFlag != nil {
|
||||
config := builderConfigFromFlag.ToPayload()
|
||||
if config.GasLimit == validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit) && option.Builder != nil {
|
||||
config.GasLimit = option.Builder.GasLimit
|
||||
}
|
||||
option.Builder = builderConfig.ToPayload()
|
||||
option.Builder = config
|
||||
} else if option.Builder != nil {
|
||||
option.Builder.GasLimit = reviewGasLimit(option.Builder.GasLimit)
|
||||
}
|
||||
o := &validatorServiceConfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{
|
||||
@@ -628,6 +626,49 @@ func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*validatorServ
|
||||
return vpSettings, nil
|
||||
}
|
||||
|
||||
func handleNoProposerSettingsFlagsProvided(cliCtx *cli.Context,
|
||||
db iface.ValidatorDB,
|
||||
builderConfigFromFlag *validatorServiceConfig.BuilderConfig) (*validatorServiceConfig.ProposerSettings, error) {
|
||||
log.Info("no proposer settings files have been provided, attempting to load from db.")
|
||||
// checks db if proposer settings exist if none is provided.
|
||||
settings, err := db.ProposerSettings(cliCtx.Context)
|
||||
if err == nil {
|
||||
// process any overrides to builder settings
|
||||
overrideBuilderSettings(settings, builderConfigFromFlag)
|
||||
// if settings are empty
|
||||
log.Info("successfully loaded proposer settings from db.")
|
||||
return settings, nil
|
||||
} else {
|
||||
log.WithError(err).Warn("no proposer settings will be loaded from the db")
|
||||
}
|
||||
|
||||
if cliCtx.Bool(flags.EnableBuilderFlag.Name) {
|
||||
// if there are no proposer settings provided, create a default where fee recipient is not populated, this will be skipped for validator registration on validators that don't have a fee recipient set.
|
||||
// skip saving to DB if only builder settings are provided until a trigger like keymanager API updates with fee recipient values
|
||||
return &validatorServiceConfig.ProposerSettings{
|
||||
DefaultConfig: &validatorServiceConfig.ProposerOption{
|
||||
BuilderConfig: builderConfigFromFlag,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func overrideBuilderSettings(settings *validatorServiceConfig.ProposerSettings, builderConfigFromFlag *validatorServiceConfig.BuilderConfig) {
|
||||
// override the db settings with the results based on whether the --enable-builder flag is provided.
|
||||
if builderConfigFromFlag == nil {
|
||||
log.Infof("proposer settings loaded from db. validator registration to builder is not enabled, please use the --%s flag if you wish to use a builder.", flags.EnableBuilderFlag.Name)
|
||||
}
|
||||
if settings.ProposeConfig != nil {
|
||||
for key := range settings.ProposeConfig {
|
||||
settings.ProposeConfig[key].BuilderConfig = builderConfigFromFlag
|
||||
}
|
||||
}
|
||||
if settings.DefaultConfig != nil {
|
||||
settings.DefaultConfig.BuilderConfig = builderConfigFromFlag
|
||||
}
|
||||
}
|
||||
|
||||
func BuilderSettingsFromFlags(cliCtx *cli.Context) (*validatorServiceConfig.BuilderConfig, error) {
|
||||
if cliCtx.Bool(flags.EnableBuilderFlag.Name) {
|
||||
gasLimit := validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit)
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/db/iface"
|
||||
dbTest "github.com/prysmaticlabs/prysm/v4/validator/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/keymanager"
|
||||
remoteweb3signer "github.com/prysmaticlabs/prysm/v4/validator/keymanager/remote-web3signer"
|
||||
@@ -227,6 +228,7 @@ func TestProposerSettings(t *testing.T) {
|
||||
urlResponse string
|
||||
wantErr string
|
||||
wantLog string
|
||||
withdb func(db iface.ValidatorDB) error
|
||||
validatorRegistrationEnabled bool
|
||||
}{
|
||||
{
|
||||
@@ -552,7 +554,7 @@ func TestProposerSettings(t *testing.T) {
|
||||
validatorRegistrationEnabled: true,
|
||||
},
|
||||
{
|
||||
name: "Enable Builder flag does not override completed builder config",
|
||||
name: "Enable Builder flag does override completed builder config",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
|
||||
@@ -580,7 +582,7 @@ func TestProposerSettings(t *testing.T) {
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
BuilderConfig: &validatorserviceconfig.BuilderConfig{
|
||||
Enabled: false,
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
|
||||
},
|
||||
},
|
||||
@@ -588,6 +590,185 @@ func TestProposerSettings(t *testing.T) {
|
||||
},
|
||||
validatorRegistrationEnabled: true,
|
||||
},
|
||||
{
|
||||
name: "Only Enable Builder flag",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validatorserviceconfig.ProposerSettings {
|
||||
return &validatorserviceconfig.ProposerSettings{
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
BuilderConfig: &validatorserviceconfig.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
validatorRegistrationEnabled: true,
|
||||
},
|
||||
{
|
||||
name: "No Flags but saved to DB with builder and override removed builder data",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validatorserviceconfig.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
withdb: func(db iface.ValidatorDB) error {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
settings := &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
BuilderConfig: &validatorserviceconfig.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(40000000),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
BuilderConfig: &validatorserviceconfig.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
|
||||
},
|
||||
},
|
||||
}
|
||||
return db.SaveProposerSettings(context.Background(), settings)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Enable builder flag but saved to DB without builder data now includes builder data",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validatorserviceconfig.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
BuilderConfig: &validatorserviceconfig.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
BuilderConfig: &validatorserviceconfig.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
withdb: func(db iface.ValidatorDB) error {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
settings := &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
},
|
||||
}
|
||||
return db.SaveProposerSettings(context.Background(), settings)
|
||||
},
|
||||
validatorRegistrationEnabled: true,
|
||||
},
|
||||
{
|
||||
name: "No flags, but saved to database",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validatorserviceconfig.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
withdb: func(db iface.ValidatorDB) error {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
settings := &validatorserviceconfig.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
},
|
||||
}
|
||||
return db.SaveProposerSettings(context.Background(), settings)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "No flags set means empty config",
|
||||
args: args{
|
||||
@@ -680,6 +861,10 @@ func TestProposerSettings(t *testing.T) {
|
||||
}
|
||||
cliCtx := cli.NewContext(&app, set, nil)
|
||||
validatorDB := dbTest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
if tt.withdb != nil {
|
||||
err := tt.withdb(validatorDB)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
got, err := proposerSettings(cliCtx, validatorDB)
|
||||
if tt.wantErr != "" {
|
||||
require.ErrorContains(t, tt.wantErr, err)
|
||||
@@ -692,17 +877,29 @@ func TestProposerSettings(t *testing.T) {
|
||||
}
|
||||
w := tt.want()
|
||||
require.DeepEqual(t, w, got)
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// return an error if the user is using builder settings without any default fee recipient
|
||||
func TestProposerSettings_EnableBuilder_noFeeRecipient(t *testing.T) {
|
||||
validatorDB := dbTest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
func Test_ProposerSettingsWithOnlyBuilder_DoesNotSaveInDB(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.EnableBuilderFlag.Name, true, "")
|
||||
cliCtx := cli.NewContext(&app, set, nil)
|
||||
_, err := proposerSettings(cliCtx, validatorDB)
|
||||
require.ErrorContains(t, "can only be used when a default fee recipient is present on the validator client", err)
|
||||
validatorDB := dbTest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
got, err := proposerSettings(cliCtx, validatorDB)
|
||||
require.NoError(t, err)
|
||||
_, err = validatorDB.ProposerSettings(cliCtx.Context)
|
||||
require.ErrorContains(t, "no proposer settings found in bucket", err)
|
||||
want := &validatorserviceconfig.ProposerSettings{
|
||||
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
||||
BuilderConfig: &validatorserviceconfig.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
|
||||
Relays: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.DeepEqual(t, want, got)
|
||||
}
|
||||
|
||||
@@ -600,7 +600,7 @@ func (s *Server) SetFeeRecipientByPubkey(ctx context.Context, req *ethpbservice.
|
||||
}
|
||||
case settings.ProposeConfig == nil:
|
||||
var builderConfig *validatorServiceConfig.BuilderConfig
|
||||
if settings.DefaultConfig != nil {
|
||||
if settings.DefaultConfig != nil && settings.DefaultConfig.BuilderConfig != nil {
|
||||
builderConfig = settings.DefaultConfig.BuilderConfig.Clone()
|
||||
}
|
||||
settings.ProposeConfig = map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption{
|
||||
@@ -619,7 +619,7 @@ func (s *Server) SetFeeRecipientByPubkey(ctx context.Context, req *ethpbservice.
|
||||
}
|
||||
} else {
|
||||
var builderConfig = &validatorServiceConfig.BuilderConfig{}
|
||||
if settings.DefaultConfig != nil {
|
||||
if settings.DefaultConfig != nil && settings.DefaultConfig.BuilderConfig != nil {
|
||||
builderConfig = settings.DefaultConfig.BuilderConfig.Clone()
|
||||
}
|
||||
settings.ProposeConfig[bytesutil.ToBytes48(validatorKey)] = &validatorServiceConfig.ProposerOption{
|
||||
|
||||
@@ -768,7 +768,8 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
|
||||
mockValidatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
|
||||
m := &mock.MockValidator{}
|
||||
m.SetProposerSettings(tt.args)
|
||||
err := m.SetProposerSettings(ctx, tt.args)
|
||||
require.NoError(t, err)
|
||||
|
||||
if tt.args == nil {
|
||||
mockValidatorClient.EXPECT().GetFeeRecipientByPubKey(gomock.Any(), gomock.Any()).Return(tt.cached, nil)
|
||||
@@ -1004,7 +1005,8 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &mock.MockValidator{}
|
||||
m.SetProposerSettings(tt.proposerSettings)
|
||||
err := m.SetProposerSettings(ctx, tt.proposerSettings)
|
||||
require.NoError(t, err)
|
||||
validatorDB := dbtest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
|
||||
// save a default here
|
||||
@@ -1106,7 +1108,8 @@ func TestServer_DeleteFeeRecipientByPubkey(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &mock.MockValidator{}
|
||||
m.SetProposerSettings(tt.proposerSettings)
|
||||
err := m.SetProposerSettings(ctx, tt.proposerSettings)
|
||||
require.NoError(t, err)
|
||||
validatorDB := dbtest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
vs, err := client.NewValidatorService(ctx, &client.Config{
|
||||
Validator: m,
|
||||
@@ -1202,7 +1205,8 @@ func TestServer_GetGasLimit(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &mock.MockValidator{}
|
||||
m.SetProposerSettings(tt.args)
|
||||
err := m.SetProposerSettings(ctx, tt.args)
|
||||
require.NoError(t, err)
|
||||
vs, err := client.NewValidatorService(ctx, &client.Config{
|
||||
Validator: m,
|
||||
})
|
||||
@@ -1351,7 +1355,8 @@ func TestServer_SetGasLimit(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &mock.MockValidator{}
|
||||
m.SetProposerSettings(tt.proposerSettings)
|
||||
err := m.SetProposerSettings(ctx, tt.proposerSettings)
|
||||
require.NoError(t, err)
|
||||
validatorDB := dbtest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
vs, err := client.NewValidatorService(ctx, &client.Config{
|
||||
Validator: m,
|
||||
@@ -1520,7 +1525,8 @@ func TestServer_DeleteGasLimit(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &mock.MockValidator{}
|
||||
m.SetProposerSettings(tt.proposerSettings)
|
||||
err := m.SetProposerSettings(ctx, tt.proposerSettings)
|
||||
require.NoError(t, err)
|
||||
validatorDB := dbtest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
vs, err := client.NewValidatorService(ctx, &client.Config{
|
||||
Validator: m,
|
||||
|
||||
Reference in New Issue
Block a user