Registration Cache used by default and other UX changes for Proposer settings (#12456)

* WIP

* WIP

* adding in migration function

* updating mock validator and gaz

* adding descriptive logs

* fixing mocking

* fixing tests

* fixing mock

* adding changes to handle enable builder settings

* fixing tests and edge case

* reduce cognative complexity of function

* further reducing cognative complexity on function

* WIP

* fixing unit test on migration

* adding more tests

* gaz and fix unit test

* fixing deepsource issues

* fixing more deesource issues missed previously

* removing unused reciever name

* WIP fix to migration logic

* fixing loging info

* reverting migration logic, converting logic to address issues discussed on slack, adding unit tests

* adding test for builder setting only not saved to db

* addressing comment

* fixing flag

* removing accidently missed deprecated flags

* rolling back mock on pr

* fixing fmt linting

* updating comments based on feedback

* Update config/features/flags.go

Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com>

* fixing based on feedback on PR

* Update config/validator/service/proposer_settings.go

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>

* Update validator/client/runner.go

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>

* Update validator/db/kv/proposer_settings.go

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>

* adding additional logs to clear up some steps based on feedback

* fixing log

* deepsource

* adding comments based on review feedback

---------

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com>
Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
This commit is contained in:
james-prysm
2023-06-28 21:49:21 -05:00
committed by GitHub
parent cbe67f1970
commit d0c740f477
22 changed files with 509 additions and 112 deletions

View File

@@ -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...)

View File

@@ -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",

View File

@@ -58,7 +58,6 @@ var appFlags = []cli.Flag{
flags.InteropGenesisTimeFlag,
flags.SlotsPerArchivedPoint,
flags.EnableDebugRPCEndpoints,
flags.EnableRegistrationCache,
flags.SubscribeToAllSubnets,
flags.HistoricalSlasherNode,
flags.ChainID,

View File

@@ -113,7 +113,6 @@ var appHelpFlagGroups = []flagGroup{
flags.BlockBatchLimit,
flags.BlockBatchLimitBurstFactor,
flags.EnableDebugRPCEndpoints,
flags.EnableRegistrationCache,
flags.SubscribeToAllSubnets,
flags.HistoricalSlasherNode,
flags.ChainID,

View File

@@ -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

View File

@@ -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,
}...)...)

View File

@@ -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 {

View File

@@ -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)
}
})
}
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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")

View File

@@ -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
@@ -249,13 +250,14 @@ func TestUpdateProposerSettingsAt_EpochStart(t *testing.T) {
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{
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
@@ -273,13 +275,14 @@ func TestUpdateProposerSettingsAt_EpochEndExceeded(t *testing.T) {
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 +304,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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},

View File

@@ -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())

View File

@@ -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",

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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{

View File

@@ -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,