refactoring how proposer settings load into validator client (#13645)

* refactoring how proposer settings load

* fixing tests and moving test data

* fixing linting and adding comments

* accidently removed a function, adding it back in

* fixing usage of dependency

* gaz

* fixing package visibility

* gaz

* iface config gaz

* adding visibility for db

* fix ineffectual assignment to err

* adding in log for when the builder is set but ignored due to no fee recipient

* Update config/validator/service/proposer_settings.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/validator/service/proposer_settings.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update validator/client/validator.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/validator/service/proposer_settings.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/proposer/loader.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/proposer/loader.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/proposer/loader.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/proposer/loader.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/proposer/loader.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/validator/service/proposer_settings.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update config/util.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* some of the review feedback

* more review comments

* adding more test coverage

* Update config/proposer/loader.go

Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>

* Update config/proposer/loader.go

Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>

* Update config/proposer/loader.go

Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>

* Update config/proposer/loader.go

Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>

* updating based on feedback

* renaming variable

* fixing unhandled errors

* fixing tests

* gaz

* adding in gaslimit log

* fixing log

* some more review comments

* renaming and moving proposer settings file

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>
This commit is contained in:
james-prysm
2024-03-04 09:12:11 -06:00
committed by GitHub
parent 3df7a1f067
commit d6fb8c29c9
43 changed files with 1823 additions and 1446 deletions

View File

@@ -10,6 +10,7 @@ go_library(
visibility = [ visibility = [
"//cmd/prysmctl:__subpackages__", "//cmd/prysmctl:__subpackages__",
"//cmd/validator:__subpackages__", "//cmd/validator:__subpackages__",
"//config:__subpackages__",
"//testing/endtoend:__subpackages__", "//testing/endtoend:__subpackages__",
"//validator:__subpackages__", "//validator:__subpackages__",
], ],

View File

@@ -1,3 +1,5 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
config_setting( config_setting(
name = "mainnet", name = "mainnet",
flag_values = { flag_values = {
@@ -11,3 +13,28 @@ config_setting(
"//proto:network": "minimal", "//proto:network": "minimal",
}, },
) )
go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "github.com/prysmaticlabs/prysm/v5/config",
visibility = ["//visibility:public"],
deps = [
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_k8s_apimachinery//pkg/util/yaml:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
embed = [":go_default_library"],
deps = [
"//config/params:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],
)

View File

@@ -2,10 +2,11 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["proposer_settings.go"], srcs = ["settings.go"],
importpath = "github.com/prysmaticlabs/prysm/v5/config/validator/service", importpath = "github.com/prysmaticlabs/prysm/v5/config/proposer",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//config:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//consensus-types/validator:go_default_library", "//consensus-types/validator:go_default_library",
"//encoding/bytesutil:go_default_library", "//encoding/bytesutil:go_default_library",
@@ -18,7 +19,7 @@ go_library(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = ["proposer_settings_test.go"], srcs = ["settings_test.go"],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",

View File

@@ -0,0 +1,45 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_test(
name = "go_default_test",
size = "small",
srcs = ["loader_test.go"],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = [
"//cmd/validator/flags:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//config/proposer:go_default_library",
"//consensus-types/validator:go_default_library",
"//encoding/bytesutil:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//validator/db/iface:go_default_library",
"//validator/db/testing:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["loader.go"],
importpath = "github.com/prysmaticlabs/prysm/v5/config/proposer/loader",
visibility = ["//visibility:public"],
deps = [
"//cmd/validator/flags:go_default_library",
"//config:go_default_library",
"//config/params:go_default_library",
"//config/proposer:go_default_library",
"//consensus-types/validator:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//validator/db/iface:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
],
)

View File

@@ -0,0 +1,283 @@
package loader
import (
"fmt"
"strconv"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/cmd/validator/flags"
"github.com/prysmaticlabs/prysm/v5/config"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v5/validator/db/iface"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
type settingsType int
const (
none settingsType = iota
defaultFlag
fileFlag
urlFlag
onlyDB
)
type settingsLoader struct {
loadMethods []settingsType
existsInDB bool
db iface.ValidatorDB
options *flagOptions
}
type flagOptions struct {
builderConfig *proposer.BuilderConfig
gasLimit *validator.Uint64
}
// SettingsLoaderOption sets additional options that affect the proposer settings
type SettingsLoaderOption func(cliCtx *cli.Context, psl *settingsLoader) error
// WithBuilderConfig applies the --enable-builder flag to proposer settings
func WithBuilderConfig() SettingsLoaderOption {
return func(cliCtx *cli.Context, psl *settingsLoader) error {
if cliCtx.Bool(flags.EnableBuilderFlag.Name) {
psl.options.builderConfig = &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
}
}
return nil
}
}
// WithGasLimit applies the --suggested-gas-limit flag to proposer settings
func WithGasLimit() SettingsLoaderOption {
return func(cliCtx *cli.Context, psl *settingsLoader) error {
sgl := cliCtx.String(flags.BuilderGasLimitFlag.Name)
if sgl != "" {
gl, err := strconv.ParseUint(sgl, 10, 64)
if err != nil {
return errors.Errorf("Value set by --%s is not a uint64", flags.BuilderGasLimitFlag.Name)
}
if gl == 0 {
log.Warnf("Gas limit was intentionally set to 0, this will be replaced with the default gas limit of %d", params.BeaconConfig().DefaultBuilderGasLimit)
}
rgl := reviewGasLimit(validator.Uint64(gl))
psl.options.gasLimit = &rgl
}
return nil
}
}
// NewProposerSettingsLoader returns a new proposer settings loader that can process the proposer settings based on flag options
func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts ...SettingsLoaderOption) (*settingsLoader, error) {
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) && cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
return nil, fmt.Errorf("cannot specify both --%s and --%s flags; choose one method for specifying proposer settings", flags.ProposerSettingsFlag.Name, flags.ProposerSettingsURLFlag.Name)
}
psExists, err := db.ProposerSettingsExists(cliCtx.Context)
if err != nil {
return nil, err
}
psl := &settingsLoader{db: db, existsInDB: psExists, options: &flagOptions{}}
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) {
psl.loadMethods = append(psl.loadMethods, defaultFlag)
}
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) {
psl.loadMethods = append(psl.loadMethods, fileFlag)
}
if cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
psl.loadMethods = append(psl.loadMethods, urlFlag)
}
if len(psl.loadMethods) == 0 {
method := none
if psExists {
// override with db
method = onlyDB
}
psl.loadMethods = append(psl.loadMethods, method)
}
for _, o := range opts {
if err := o(cliCtx, psl); err != nil {
return nil, err
}
}
return psl, nil
}
// Load saves the proposer settings to the database
func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) {
loadConfig := &validatorpb.ProposerSettingsPayload{}
// override settings based on other options
if psl.options.builderConfig != nil && psl.options.gasLimit != nil {
psl.options.builderConfig.GasLimit = *psl.options.gasLimit
}
// check if database has settings already
if psl.existsInDB {
dbps, err := psl.db.ProposerSettings(cliCtx.Context)
if err != nil {
return nil, err
}
loadConfig = dbps.ToConsensus()
}
// start to process based on load method
for _, method := range psl.loadMethods {
switch method {
case defaultFlag:
suggestedFeeRecipient := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)
if !common.IsHexAddress(suggestedFeeRecipient) {
return nil, errors.Errorf("--%s is not a valid Ethereum address", flags.SuggestedFeeRecipientFlag.Name)
}
if err := config.WarnNonChecksummedAddress(suggestedFeeRecipient); err != nil {
return nil, err
}
defaultConfig := &validatorpb.ProposerOptionPayload{
FeeRecipient: suggestedFeeRecipient,
}
if psl.options.builderConfig != nil {
defaultConfig.Builder = psl.options.builderConfig.ToConsensus()
}
loadConfig.DefaultConfig = defaultConfig
case fileFlag:
var settingFromFile *validatorpb.ProposerSettingsPayload
if err := config.UnmarshalFromFile(cliCtx.String(flags.ProposerSettingsFlag.Name), &settingFromFile); err != nil {
return nil, err
}
if settingFromFile == nil {
return nil, errors.Errorf("proposer settings is empty after unmarshalling from file specified by %s flag", flags.ProposerSettingsFlag.Name)
}
loadConfig = psl.processProposerSettings(settingFromFile, loadConfig)
case urlFlag:
var settingFromURL *validatorpb.ProposerSettingsPayload
if err := config.UnmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &settingFromURL); err != nil {
return nil, err
}
if settingFromURL == nil {
return nil, errors.New("proposer settings is empty after unmarshalling from url")
}
loadConfig = psl.processProposerSettings(settingFromURL, loadConfig)
case onlyDB:
loadConfig = psl.processProposerSettings(nil, loadConfig)
case none:
if psl.options.builderConfig != nil {
// 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
option := &proposer.Option{
BuilderConfig: psl.options.builderConfig.Clone(),
}
loadConfig.DefaultConfig = option.ToConsensus()
}
default:
return nil, errors.New("load method for proposer settings does not exist")
}
}
// exit early if nothing is provided
if loadConfig == nil || (loadConfig.ProposerConfig == nil && loadConfig.DefaultConfig == nil) {
log.Warn("No proposer settings were provided")
return nil, nil
}
ps, err := proposer.SettingFromConsensus(loadConfig)
if err != nil {
return nil, err
}
if err := psl.db.SaveProposerSettings(cliCtx.Context, ps); err != nil {
return nil, err
}
return ps, nil
}
func (psl *settingsLoader) processProposerSettings(loadedSettings, dbSettings *validatorpb.ProposerSettingsPayload) *validatorpb.ProposerSettingsPayload {
if loadedSettings == nil && dbSettings == nil {
return nil
}
// loaded settings have higher priority than db settings
newSettings := &validatorpb.ProposerSettingsPayload{}
var builderConfig *validatorpb.BuilderConfig
var gasLimitOnly *validator.Uint64
if psl.options != nil {
if psl.options.builderConfig != nil {
builderConfig = psl.options.builderConfig.ToConsensus()
}
if psl.options.gasLimit != nil {
gasLimitOnly = psl.options.gasLimit
}
}
if dbSettings != nil && dbSettings.DefaultConfig != nil {
if builderConfig == nil {
dbSettings.DefaultConfig.Builder = nil
}
newSettings.DefaultConfig = dbSettings.DefaultConfig
}
if loadedSettings != nil && loadedSettings.DefaultConfig != nil {
newSettings.DefaultConfig = loadedSettings.DefaultConfig
}
// process any builder overrides on defaults
if newSettings.DefaultConfig != nil {
newSettings.DefaultConfig.Builder = processBuilderConfig(newSettings.DefaultConfig.Builder, builderConfig, gasLimitOnly)
}
if dbSettings != nil && len(dbSettings.ProposerConfig) != 0 {
for _, option := range dbSettings.ProposerConfig {
if builderConfig == nil {
option.Builder = nil
}
}
newSettings.ProposerConfig = dbSettings.ProposerConfig
}
if loadedSettings != nil && len(loadedSettings.ProposerConfig) != 0 {
newSettings.ProposerConfig = loadedSettings.ProposerConfig
}
// process any overrides for proposer config
for _, option := range newSettings.ProposerConfig {
if option != nil {
option.Builder = processBuilderConfig(option.Builder, builderConfig, gasLimitOnly)
}
}
// if default and proposer configs are both missing even after db setting
if newSettings.DefaultConfig == nil && newSettings.ProposerConfig == nil {
return nil
}
return newSettings
}
func processBuilderConfig(current *validatorpb.BuilderConfig, override *validatorpb.BuilderConfig, gasLimitOnly *validator.Uint64) *validatorpb.BuilderConfig {
if current != nil {
current.GasLimit = reviewGasLimit(current.GasLimit)
if override != nil {
current.Enabled = override.Enabled
}
if gasLimitOnly != nil {
current.GasLimit = *gasLimitOnly
}
return current
}
return override
}
func reviewGasLimit(gasLimit validator.Uint64) validator.Uint64 {
// sets gas limit to default if not defined or set to 0
if gasLimit == 0 {
return validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit)
}
// TODO(10810): add in warning for ranges
return gasLimit
}

View File

@@ -0,0 +1,921 @@
package loader
import (
"context"
"flag"
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/prysmaticlabs/prysm/v5/cmd/validator/flags"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/validator/db/iface"
dbTest "github.com/prysmaticlabs/prysm/v5/validator/db/testing"
logtest "github.com/sirupsen/logrus/hooks/test"
"github.com/urfave/cli/v2"
)
func TestProposerSettingsLoader(t *testing.T) {
hook := logtest.NewGlobal()
type proposerSettingsFlag struct {
dir string
url string
defaultfee string
defaultgas string
}
type args struct {
proposerSettingsFlagValues *proposerSettingsFlag
}
tests := []struct {
name string
args args
want func() *proposer.Settings
urlResponse string
wantInitErr string
wantErr string
wantLog string
withdb func(db iface.ValidatorDB) error
validatorRegistrationEnabled bool
skipDBSavedCheck bool
}{
{
name: "db settings override file settings if file default config is missing",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/proposer-config-only.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
},
}
},
withdb: func(db iface.ValidatorDB) error {
settings := &proposer.Settings{
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
return db.SaveProposerSettings(context.Background(), settings)
},
},
{
name: "db settings override file settings if file proposer config is missing and enable builder is true",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/default-only-proposer-config.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
BuilderConfig: &proposer.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 := &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
},
},
},
}
return db.SaveProposerSettings(context.Background(), settings)
},
validatorRegistrationEnabled: true,
},
{
name: "Empty json file loaded throws a warning",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/empty.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
return nil
},
wantLog: "No proposer settings were provided",
skipDBSavedCheck: true,
},
{
name: "Happy Path default only proposer settings file with builder settings,",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/default-only-proposer-config.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
return &proposer.Settings{
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
},
{
name: "Happy Path Config file File, bad checksum",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config-badchecksum.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
},
}
},
wantErr: "",
wantLog: "is not a checksum Ethereum address",
},
{
name: "Happy Path Config file File multiple fee recipients",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config-multiple.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
key2, err := hexutil.Decode("0xb057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7b")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
bytesutil.ToBytes48(key2): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x60155530FCE8a85ec7055A5F8b2bE214B3DaeFd4"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(35000000),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Config URL File",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "./testdata/good-prepare-beacon-proposer-config.json",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Config YAML file with custom Gas Limit",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: 40000000,
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Suggested Fee ",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
},
},
want: func() *proposer.Settings {
return &proposer.Settings{
ProposeConfig: nil,
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Suggested Fee , validator registration enabled",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
},
},
want: func() *proposer.Settings {
return &proposer.Settings{
ProposeConfig: nil,
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "Happy Path Suggested Fee , validator registration enabled and default gas",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
defaultgas: "50000000",
},
},
want: func() *proposer.Settings {
return &proposer.Settings{
ProposeConfig: nil,
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: 50000000,
},
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "File with default gas that overrides",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
url: "",
defaultfee: "",
defaultgas: "50000000",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: 50000000,
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(50000000),
},
},
}
},
wantErr: "",
},
{
name: "Suggested Fee does not Override Config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89B",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
},
}
},
wantErr: "",
},
{
name: "Suggested Fee with validator registration does not Override Config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89B",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "Enable Builder flag overrides empty config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
validatorRegistrationEnabled: true,
},
{
name: "Enable Builder flag does override completed builder config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
validatorRegistrationEnabled: true,
},
{
name: "Only Enable Builder flag",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
return &proposer.Settings{
DefaultConfig: &proposer.Option{
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
validatorRegistrationEnabled: true,
skipDBSavedCheck: true,
},
{
name: "No Flags but saved to DB with builder and override removed builder data",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
},
}
},
withdb: func(db iface.ValidatorDB) error {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
settings := &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.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() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.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 := &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.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() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
},
}
},
withdb: func(db iface.ValidatorDB) error {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
settings := &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
},
}
return db.SaveProposerSettings(context.Background(), settings)
},
},
{
name: "No flags set means empty config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
return nil
},
wantErr: "",
skipDBSavedCheck: true,
},
{
name: "Bad File Path",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/bad-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
return nil
},
wantErr: "failed to unmarshal yaml file",
},
{
name: "Both URL and Dir flags used resulting in error",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "./testdata/good-prepare-beacon-proposer-config.json",
defaultfee: "",
},
},
want: func() *proposer.Settings {
return &proposer.Settings{}
},
wantInitErr: "cannot specify both",
},
{
name: "Bad Gas value in JSON",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/bad-gas-value-proposer-settings.json",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
return nil
},
wantErr: "failed to unmarshal yaml file",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
app := cli.App{}
set := flag.NewFlagSet("test", 0)
if tt.args.proposerSettingsFlagValues.dir != "" {
set.String(flags.ProposerSettingsFlag.Name, tt.args.proposerSettingsFlagValues.dir, "")
require.NoError(t, set.Set(flags.ProposerSettingsFlag.Name, tt.args.proposerSettingsFlagValues.dir))
}
if tt.args.proposerSettingsFlagValues.url != "" {
content, err := os.ReadFile(tt.args.proposerSettingsFlagValues.url)
require.NoError(t, err)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Header().Set("Content-Type", "application/json")
_, err := fmt.Fprintf(w, "%s", content)
require.NoError(t, err)
}))
defer srv.Close()
set.String(flags.ProposerSettingsURLFlag.Name, tt.args.proposerSettingsFlagValues.url, "")
require.NoError(t, set.Set(flags.ProposerSettingsURLFlag.Name, srv.URL))
}
if tt.args.proposerSettingsFlagValues.defaultfee != "" {
set.String(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee, "")
require.NoError(t, set.Set(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee))
}
if tt.args.proposerSettingsFlagValues.defaultgas != "" {
set.String(flags.BuilderGasLimitFlag.Name, tt.args.proposerSettingsFlagValues.defaultgas, "")
require.NoError(t, set.Set(flags.BuilderGasLimitFlag.Name, tt.args.proposerSettingsFlagValues.defaultgas))
}
if tt.validatorRegistrationEnabled {
set.Bool(flags.EnableBuilderFlag.Name, true, "")
}
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)
}
loader, err := NewProposerSettingsLoader(
cliCtx,
validatorDB,
WithBuilderConfig(),
WithGasLimit(),
)
if tt.wantInitErr != "" {
require.ErrorContains(t, tt.wantInitErr, err)
return
} else {
require.NoError(t, err)
}
got, err := loader.Load(cliCtx)
if tt.wantErr != "" {
require.ErrorContains(t, tt.wantErr, err)
return
}
if tt.wantLog != "" {
assert.LogsContain(t, hook,
tt.wantLog,
)
}
w := tt.want()
require.DeepEqual(t, w, got)
if !tt.skipDBSavedCheck {
dbSettings, err := validatorDB.ProposerSettings(cliCtx.Context)
require.NoError(t, err)
require.DeepEqual(t, w, dbSettings)
}
})
}
}
func Test_ProposerSettingsLoaderWithOnlyBuilder_DoesNotSaveInDB(t *testing.T) {
app := cli.App{}
set := flag.NewFlagSet("test", 0)
set.Bool(flags.EnableBuilderFlag.Name, true, "")
cliCtx := cli.NewContext(&app, set, nil)
validatorDB := dbTest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
loader, err := NewProposerSettingsLoader(
cliCtx,
validatorDB,
WithBuilderConfig(),
WithGasLimit(),
)
require.NoError(t, err)
got, err := loader.Load(cliCtx)
require.NoError(t, err)
_, err = validatorDB.ProposerSettings(cliCtx.Context)
require.ErrorContains(t, "no proposer settings found in bucket", err)
want := &proposer.Settings{
DefaultConfig: &proposer.Option{
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
Relays: nil,
},
},
}
require.DeepEqual(t, want, got)
}

View File

@@ -1,5 +1,4 @@
{ {
"proposer_config": {},
"default_config": { "default_config": {
"fee_recipient": "0xAe967917c465db8578ca9024c205720b1a3651A9", "fee_recipient": "0xAe967917c465db8578ca9024c205720b1a3651A9",
"builder": {"enabled": true} "builder": {"enabled": true}

View File

@@ -0,0 +1,3 @@
{
}

View File

@@ -0,0 +1,7 @@
{
"proposer_config": {
"0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a": {
"fee_recipient": "0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"
}
}
}

View File

@@ -1,4 +1,4 @@
package validator_service_config package proposer
import ( import (
"fmt" "fmt"
@@ -6,51 +6,77 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/config"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
) )
// ToSettings converts struct to ProposerSettings // SettingFromConsensus converts struct to Settings while verifying the fields
func ToSettings(ps *validatorpb.ProposerSettingsPayload) (*ProposerSettings, error) { func SettingFromConsensus(ps *validatorpb.ProposerSettingsPayload) (*Settings, error) {
settings := &ProposerSettings{} settings := &Settings{}
if ps.ProposerConfig != nil { if ps.ProposerConfig != nil && len(ps.ProposerConfig) != 0 {
settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption) settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*Option)
for key, optionPayload := range ps.ProposerConfig { for key, optionPayload := range ps.ProposerConfig {
if optionPayload.FeeRecipient == "" { if optionPayload.FeeRecipient == "" {
continue continue
} }
b, err := hexutil.Decode(key) decodedKey, err := hexutil.Decode(key)
if err != nil { if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("cannot decode public key %s", key)) return nil, errors.Wrap(err, fmt.Sprintf("cannot decode public key %s", key))
} }
p := &ProposerOption{ if len(decodedKey) != fieldparams.BLSPubkeyLength {
return nil, fmt.Errorf("%v is not a bls public key", key)
}
if err := verifyOption(key, optionPayload); err != nil {
return nil, err
}
p := &Option{
FeeRecipientConfig: &FeeRecipientConfig{ FeeRecipientConfig: &FeeRecipientConfig{
FeeRecipient: common.HexToAddress(optionPayload.FeeRecipient), FeeRecipient: common.HexToAddress(optionPayload.FeeRecipient),
}, },
} }
if optionPayload.Builder != nil { if optionPayload.Builder != nil {
p.BuilderConfig = ToBuilderConfig(optionPayload.Builder) p.BuilderConfig = BuilderConfigFromConsensus(optionPayload.Builder)
} }
settings.ProposeConfig[bytesutil.ToBytes48(b)] = p settings.ProposeConfig[bytesutil.ToBytes48(decodedKey)] = p
} }
} }
if ps.DefaultConfig != nil { if ps.DefaultConfig != nil {
d := &ProposerOption{} d := &Option{}
if ps.DefaultConfig.FeeRecipient != "" { if ps.DefaultConfig.FeeRecipient != "" {
if !common.IsHexAddress(ps.DefaultConfig.FeeRecipient) {
return nil, errors.New("default fee recipient is not a valid Ethereum address")
}
if err := config.WarnNonChecksummedAddress(ps.DefaultConfig.FeeRecipient); err != nil {
return nil, err
}
d.FeeRecipientConfig = &FeeRecipientConfig{ d.FeeRecipientConfig = &FeeRecipientConfig{
FeeRecipient: common.HexToAddress(ps.DefaultConfig.FeeRecipient), FeeRecipient: common.HexToAddress(ps.DefaultConfig.FeeRecipient),
} }
} }
if ps.DefaultConfig.Builder != nil { if ps.DefaultConfig.Builder != nil {
d.BuilderConfig = ToBuilderConfig(ps.DefaultConfig.Builder) d.BuilderConfig = BuilderConfigFromConsensus(ps.DefaultConfig.Builder)
} }
settings.DefaultConfig = d settings.DefaultConfig = d
} }
return settings, nil return settings, nil
} }
func verifyOption(key string, option *validatorpb.ProposerOptionPayload) error {
if option == nil {
return fmt.Errorf("fee recipient is required for proposer %s", key)
}
if !common.IsHexAddress(option.FeeRecipient) {
return errors.New("fee recipient is not a valid Ethereum address")
}
if err := config.WarnNonChecksummedAddress(option.FeeRecipient); err != nil {
return err
}
return nil
}
// BuilderConfig is the struct representation of the JSON config file set in the validator through the CLI. // BuilderConfig is the struct representation of the JSON config file set in the validator through the CLI.
// GasLimit is a number set to help the network decide on the maximum gas in each block. // GasLimit is a number set to help the network decide on the maximum gas in each block.
type BuilderConfig struct { type BuilderConfig struct {
@@ -59,29 +85,28 @@ type BuilderConfig struct {
Relays []string `json:"relays,omitempty" yaml:"relays,omitempty"` Relays []string `json:"relays,omitempty" yaml:"relays,omitempty"`
} }
// ToBuilderConfig converts protobuf to a builder config used in inmemory storage // BuilderConfigFromConsensus converts protobuf to a builder config used in in-memory storage
func ToBuilderConfig(from *validatorpb.BuilderConfig) *BuilderConfig { func BuilderConfigFromConsensus(from *validatorpb.BuilderConfig) *BuilderConfig {
if from == nil { if from == nil {
return nil return nil
} }
config := &BuilderConfig{ c := &BuilderConfig{
Enabled: from.Enabled, Enabled: from.Enabled,
GasLimit: from.GasLimit, GasLimit: from.GasLimit,
} }
if from.Relays != nil { if from.Relays != nil {
relays := make([]string, len(from.Relays)) relays := make([]string, len(from.Relays))
copy(relays, from.Relays) copy(relays, from.Relays)
config.Relays = relays c.Relays = relays
} }
return c
return config
} }
// ProposerSettings is a Prysm internal representation of the fee recipient config on the validator client. // Settings is a Prysm internal representation of the fee recipient config on the validator client.
// validatorpb.ProposerSettingsPayload maps to ProposerSettings on import through the CLI. // validatorpb.ProposerSettingsPayload maps to Settings on import through the CLI.
type ProposerSettings struct { type Settings struct {
ProposeConfig map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption ProposeConfig map[[fieldparams.BLSPubkeyLength]byte]*Option
DefaultConfig *ProposerOption DefaultConfig *Option
} }
// ShouldBeSaved goes through checks to see if the value should be saveable // ShouldBeSaved goes through checks to see if the value should be saveable
@@ -89,12 +114,12 @@ type ProposerSettings struct {
// 1. settings are not nil // 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 // 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 // 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 { func (ps *Settings) ShouldBeSaved() bool {
return settings != nil && (settings.ProposeConfig != nil || settings.DefaultConfig != nil && settings.DefaultConfig.FeeRecipientConfig != nil) return ps != nil && (ps.ProposeConfig != nil || ps.DefaultConfig != nil && ps.DefaultConfig.FeeRecipientConfig != nil)
} }
// ToPayload converts struct to ProposerSettingsPayload // ToConsensus converts struct to ProposerSettingsPayload
func (ps *ProposerSettings) ToPayload() *validatorpb.ProposerSettingsPayload { func (ps *Settings) ToConsensus() *validatorpb.ProposerSettingsPayload {
if ps == nil { if ps == nil {
return nil return nil
} }
@@ -102,25 +127,11 @@ func (ps *ProposerSettings) ToPayload() *validatorpb.ProposerSettingsPayload {
if ps.ProposeConfig != nil { if ps.ProposeConfig != nil {
payload.ProposerConfig = make(map[string]*validatorpb.ProposerOptionPayload) payload.ProposerConfig = make(map[string]*validatorpb.ProposerOptionPayload)
for key, option := range ps.ProposeConfig { for key, option := range ps.ProposeConfig {
p := &validatorpb.ProposerOptionPayload{} payload.ProposerConfig[hexutil.Encode(key[:])] = option.ToConsensus()
if option.FeeRecipientConfig != nil {
p.FeeRecipient = option.FeeRecipientConfig.FeeRecipient.Hex()
}
if option.BuilderConfig != nil {
p.Builder = option.BuilderConfig.ToPayload()
}
payload.ProposerConfig[hexutil.Encode(key[:])] = p
} }
} }
if ps.DefaultConfig != nil { if ps.DefaultConfig != nil {
p := &validatorpb.ProposerOptionPayload{} payload.DefaultConfig = ps.DefaultConfig.ToConsensus()
if ps.DefaultConfig.FeeRecipientConfig != nil {
p.FeeRecipient = ps.DefaultConfig.FeeRecipientConfig.FeeRecipient.Hex()
}
if ps.DefaultConfig.BuilderConfig != nil {
p.Builder = ps.DefaultConfig.BuilderConfig.ToPayload()
}
payload.DefaultConfig = p
} }
return payload return payload
} }
@@ -130,23 +141,52 @@ type FeeRecipientConfig struct {
FeeRecipient common.Address FeeRecipient common.Address
} }
// ProposerOption is a Prysm internal representation of the ProposerOptionPayload on the validator client in bytes format instead of hex. // Option is a Prysm internal representation of the ProposerOptionPayload on the validator client in bytes format instead of hex.
type ProposerOption struct { type Option struct {
FeeRecipientConfig *FeeRecipientConfig FeeRecipientConfig *FeeRecipientConfig
BuilderConfig *BuilderConfig BuilderConfig *BuilderConfig
} }
// Clone creates a deep copy of proposer option
func (po *Option) Clone() *Option {
if po == nil {
return nil
}
p := &Option{}
if po.FeeRecipientConfig != nil {
p.FeeRecipientConfig = po.FeeRecipientConfig.Clone()
}
if po.BuilderConfig != nil {
p.BuilderConfig = po.BuilderConfig.Clone()
}
return p
}
func (po *Option) ToConsensus() *validatorpb.ProposerOptionPayload {
if po == nil {
return nil
}
p := &validatorpb.ProposerOptionPayload{}
if po.FeeRecipientConfig != nil {
p.FeeRecipient = po.FeeRecipientConfig.FeeRecipient.Hex()
}
if po.BuilderConfig != nil {
p.Builder = po.BuilderConfig.ToConsensus()
}
return p
}
// Clone creates a deep copy of the proposer settings // Clone creates a deep copy of the proposer settings
func (ps *ProposerSettings) Clone() *ProposerSettings { func (ps *Settings) Clone() *Settings {
if ps == nil { if ps == nil {
return nil return nil
} }
clone := &ProposerSettings{} clone := &Settings{}
if ps.DefaultConfig != nil { if ps.DefaultConfig != nil {
clone.DefaultConfig = ps.DefaultConfig.Clone() clone.DefaultConfig = ps.DefaultConfig.Clone()
} }
if ps.ProposeConfig != nil { if ps.ProposeConfig != nil {
clone.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption) clone.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*Option)
for k, v := range ps.ProposeConfig { for k, v := range ps.ProposeConfig {
keyCopy := k keyCopy := k
valCopy := v.Clone() valCopy := v.Clone()
@@ -170,46 +210,31 @@ func (bc *BuilderConfig) Clone() *BuilderConfig {
if bc == nil { if bc == nil {
return nil return nil
} }
config := &BuilderConfig{} c := &BuilderConfig{}
config.Enabled = bc.Enabled c.Enabled = bc.Enabled
config.GasLimit = bc.GasLimit c.GasLimit = bc.GasLimit
var relays []string var relays []string
if bc.Relays != nil { if bc.Relays != nil {
relays = make([]string, len(bc.Relays)) relays = make([]string, len(bc.Relays))
copy(relays, bc.Relays) copy(relays, bc.Relays)
config.Relays = relays c.Relays = relays
} }
return config return c
} }
// ToPayload converts Builder Config to the protobuf object // ToConsensus converts Builder Config to the protobuf object
func (bc *BuilderConfig) ToPayload() *validatorpb.BuilderConfig { func (bc *BuilderConfig) ToConsensus() *validatorpb.BuilderConfig {
if bc == nil { if bc == nil {
return nil return nil
} }
config := &validatorpb.BuilderConfig{} c := &validatorpb.BuilderConfig{}
config.Enabled = bc.Enabled c.Enabled = bc.Enabled
var relays []string var relays []string
if bc.Relays != nil { if bc.Relays != nil {
relays = make([]string, len(bc.Relays)) relays = make([]string, len(bc.Relays))
copy(relays, bc.Relays) copy(relays, bc.Relays)
config.Relays = relays c.Relays = relays
} }
config.GasLimit = bc.GasLimit c.GasLimit = bc.GasLimit
return config return c
}
// Clone creates a deep copy of proposer option
func (po *ProposerOption) Clone() *ProposerOption {
if po == nil {
return nil
}
p := &ProposerOption{}
if po.FeeRecipientConfig != nil {
p.FeeRecipientConfig = po.FeeRecipientConfig.Clone()
}
if po.BuilderConfig != nil {
p.BuilderConfig = po.BuilderConfig.Clone()
}
return p
} }

View File

@@ -1,4 +1,4 @@
package validator_service_config package proposer
import ( import (
"testing" "testing"
@@ -16,8 +16,8 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
key1hex := "0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a" key1hex := "0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a"
key1, err := hexutil.Decode(key1hex) key1, err := hexutil.Decode(key1hex)
require.NoError(t, err) require.NoError(t, err)
settings := &ProposerSettings{ settings := &Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption{ ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*Option{
bytesutil.ToBytes48(key1): { bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &FeeRecipientConfig{ FeeRecipientConfig: &FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
@@ -29,7 +29,7 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
}, },
}, },
}, },
DefaultConfig: &ProposerOption{ DefaultConfig: &Option{
FeeRecipientConfig: &FeeRecipientConfig{ FeeRecipientConfig: &FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"), FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
}, },
@@ -59,15 +59,15 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
require.NotEqual(t, settings.DefaultConfig.BuilderConfig.GasLimit, clone.GasLimit) require.NotEqual(t, settings.DefaultConfig.BuilderConfig.GasLimit, clone.GasLimit)
}) })
t.Run("Happy Path ToBuilderConfig", func(t *testing.T) { t.Run("Happy Path BuilderConfigFromConsensus", func(t *testing.T) {
clone := settings.DefaultConfig.BuilderConfig.Clone() clone := settings.DefaultConfig.BuilderConfig.Clone()
config := ToBuilderConfig(clone.ToPayload()) config := BuilderConfigFromConsensus(clone.ToConsensus())
require.DeepEqual(t, config.Relays, clone.Relays) require.DeepEqual(t, config.Relays, clone.Relays)
require.Equal(t, config.Enabled, clone.Enabled) require.Equal(t, config.Enabled, clone.Enabled)
require.Equal(t, config.GasLimit, clone.GasLimit) require.Equal(t, config.GasLimit, clone.GasLimit)
}) })
t.Run("To Payload and ToSettings", func(t *testing.T) { t.Run("To Payload and SettingFromConsensus", func(t *testing.T) {
payload := settings.ToPayload() payload := settings.ToConsensus()
option, ok := settings.ProposeConfig[bytesutil.ToBytes48(key1)] option, ok := settings.ProposeConfig[bytesutil.ToBytes48(key1)]
require.Equal(t, true, ok) require.Equal(t, true, ok)
fee := option.FeeRecipientConfig.FeeRecipient.Hex() fee := option.FeeRecipientConfig.FeeRecipient.Hex()
@@ -77,7 +77,7 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
require.Equal(t, settings.DefaultConfig.FeeRecipientConfig.FeeRecipient.Hex(), payload.DefaultConfig.FeeRecipient) require.Equal(t, settings.DefaultConfig.FeeRecipientConfig.FeeRecipient.Hex(), payload.DefaultConfig.FeeRecipient)
require.Equal(t, settings.DefaultConfig.BuilderConfig.Enabled, payload.DefaultConfig.Builder.Enabled) require.Equal(t, settings.DefaultConfig.BuilderConfig.Enabled, payload.DefaultConfig.Builder.Enabled)
potion.FeeRecipient = "" potion.FeeRecipient = ""
newSettings, err := ToSettings(payload) newSettings, err := SettingFromConsensus(payload)
require.NoError(t, err) require.NoError(t, err)
// when converting to settings if a fee recipient is empty string then it will be skipped // when converting to settings if a fee recipient is empty string then it will be skipped
@@ -88,7 +88,7 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
// if fee recipient is set it will not skip // if fee recipient is set it will not skip
potion.FeeRecipient = fee potion.FeeRecipient = fee
newSettings, err = ToSettings(payload) newSettings, err = SettingFromConsensus(payload)
require.NoError(t, err) require.NoError(t, err)
noption, ok = newSettings.ProposeConfig[bytesutil.ToBytes48(key1)] noption, ok = newSettings.ProposeConfig[bytesutil.ToBytes48(key1)]
require.Equal(t, true, ok) require.Equal(t, true, ok)
@@ -104,8 +104,8 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
key1, err := hexutil.Decode(key1hex) key1, err := hexutil.Decode(key1hex)
require.NoError(t, err) require.NoError(t, err)
type fields struct { type fields struct {
ProposeConfig map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption ProposeConfig map[[fieldparams.BLSPubkeyLength]byte]*Option
DefaultConfig *ProposerOption DefaultConfig *Option
} }
tests := []struct { tests := []struct {
name string name string
@@ -115,7 +115,7 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
{ {
name: "Should be saved, proposeconfig populated and no default config", name: "Should be saved, proposeconfig populated and no default config",
fields: fields{ fields: fields{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption{ ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*Option{
bytesutil.ToBytes48(key1): { bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &FeeRecipientConfig{ FeeRecipientConfig: &FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
@@ -135,7 +135,7 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
name: "Should be saved, default populated and no proposeconfig ", name: "Should be saved, default populated and no proposeconfig ",
fields: fields{ fields: fields{
ProposeConfig: nil, ProposeConfig: nil,
DefaultConfig: &ProposerOption{ DefaultConfig: &Option{
FeeRecipientConfig: &FeeRecipientConfig{ FeeRecipientConfig: &FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
}, },
@@ -151,7 +151,7 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
{ {
name: "Should be saved, all populated", name: "Should be saved, all populated",
fields: fields{ fields: fields{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*ProposerOption{ ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*Option{
bytesutil.ToBytes48(key1): { bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &FeeRecipientConfig{ FeeRecipientConfig: &FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
@@ -163,7 +163,7 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
}, },
}, },
}, },
DefaultConfig: &ProposerOption{ DefaultConfig: &Option{
FeeRecipientConfig: &FeeRecipientConfig{ FeeRecipientConfig: &FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
}, },
@@ -189,7 +189,7 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
name: "Should not be saved, builder data only", name: "Should not be saved, builder data only",
fields: fields{ fields: fields{
ProposeConfig: nil, ProposeConfig: nil,
DefaultConfig: &ProposerOption{ DefaultConfig: &Option{
BuilderConfig: &BuilderConfig{ BuilderConfig: &BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: validator.Uint64(40000000), GasLimit: validator.Uint64(40000000),
@@ -202,7 +202,7 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
settings := &ProposerSettings{ settings := &Settings{
ProposeConfig: tt.fields.ProposeConfig, ProposeConfig: tt.fields.ProposeConfig,
DefaultConfig: tt.fields.DefaultConfig, DefaultConfig: tt.fields.DefaultConfig,
} }

76
config/util.go Normal file
View File

@@ -0,0 +1,76 @@
package config
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/yaml"
)
func UnmarshalFromURL(ctx context.Context, from string, to interface{}) error {
u, err := url.ParseRequestURI(from)
if err != nil {
return err
}
if u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid URL: %s", from)
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, from, nil)
if err != nil {
return errors.Wrap(err, "failed to create http request")
}
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return errors.Wrap(err, "failed to send http request")
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
log.WithError(err).Error("Failed to close response body")
}
}(resp.Body)
if resp.StatusCode != http.StatusOK {
return errors.Errorf("http request to %v failed with status code %d", from, resp.StatusCode)
}
if err := json.NewDecoder(resp.Body).Decode(&to); err != nil {
return errors.Wrap(err, "failed to decode http response")
}
return nil
}
func UnmarshalFromFile(from string, to interface{}) error {
cleanpath := filepath.Clean(from)
b, err := os.ReadFile(cleanpath)
if err != nil {
return errors.Wrap(err, "failed to open file")
}
if err := yaml.Unmarshal(b, to); err != nil {
return errors.Wrap(err, "failed to unmarshal yaml file")
}
return nil
}
func WarnNonChecksummedAddress(feeRecipient string) error {
mixedcaseAddress, err := common.NewMixedcaseAddressFromString(feeRecipient)
if err != nil {
return errors.Wrapf(err, "could not decode fee recipient %s", feeRecipient)
}
if !mixedcaseAddress.ValidChecksum() {
log.Warnf("Fee recipient %s is not a checksum Ethereum address. "+
"The checksummed address is %s and will be used as the fee recipient. "+
"We recommend using a mixed-case address (checksum) "+
"to prevent spelling mistakes in your fee recipient Ethereum address", feeRecipient, mixedcaseAddress.Address().Hex())
}
return nil
}

61
config/util_test.go Normal file
View File

@@ -0,0 +1,61 @@
package config
import (
"context"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/sirupsen/logrus/hooks/test"
)
func TestUnmarshalFromURL_Success(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, err := w.Write([]byte(`{"key":"value"}`))
require.NoError(t, err)
}))
defer server.Close()
var result map[string]string
err := UnmarshalFromURL(context.Background(), server.URL, &result)
if err != nil {
t.Errorf("UnmarshalFromURL failed: %v", err)
}
if result["key"] != "value" {
t.Errorf("Expected value to be 'value', got '%s'", result["key"])
}
}
func TestUnmarshalFromFile_Success(t *testing.T) {
// Temporarily create a YAML file
tmpFile, err := os.CreateTemp(t.TempDir(), "example.*.yaml")
require.NoError(t, err)
defer require.NoError(t, os.Remove(tmpFile.Name())) // Clean up
content := []byte("key: value")
require.NoError(t, os.WriteFile(tmpFile.Name(), content, params.BeaconIoConfig().ReadWritePermissions))
require.NoError(t, tmpFile.Close())
var result map[string]string
require.NoError(t, UnmarshalFromFile(tmpFile.Name(), &result))
require.Equal(t, result["key"], "value")
}
func TestWarnNonChecksummedAddress(t *testing.T) {
logHook := test.NewGlobal()
address := "0x967646dCD8d34F4E02204faeDcbAe0cC96fB9245"
err := WarnNonChecksummedAddress(address)
require.NoError(t, err)
assert.LogsDoNotContain(t, logHook, "is not a checksum Ethereum address")
address = strings.ToLower("0x967646dCD8d34F4E02204faeDcbAe0cC96fB9244")
err = WarnNonChecksummedAddress(address)
require.NoError(t, err)
assert.LogsContain(t, logHook, "is not a checksum Ethereum address")
}

View File

@@ -10,7 +10,7 @@ go_library(
"//validator:__subpackages__", "//validator:__subpackages__",
], ],
deps = [ deps = [
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1:go_default_library",
"//validator/accounts/iface:go_default_library", "//validator/accounts/iface:go_default_library",

View File

@@ -7,7 +7,7 @@ import (
"sync" "sync"
"time" "time"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/validator/accounts/iface" "github.com/prysmaticlabs/prysm/v5/validator/accounts/iface"
@@ -89,7 +89,7 @@ func (_ *Wallet) InitializeKeymanager(_ context.Context, _ iface.InitKeymanagerC
type Validator struct { type Validator struct {
Km keymanager.IKeymanager Km keymanager.IKeymanager
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
} }
func (_ *Validator) LogSubmittedSyncCommitteeMessages() {} func (_ *Validator) LogSubmittedSyncCommitteeMessages() {}
@@ -203,12 +203,12 @@ func (_ *Validator) SignValidatorRegistrationRequest(_ context.Context, _ iface2
} }
// ProposerSettings for mocking // ProposerSettings for mocking
func (m *Validator) ProposerSettings() *validatorserviceconfig.ProposerSettings { func (m *Validator) ProposerSettings() *proposer.Settings {
return m.proposerSettings return m.proposerSettings
} }
// SetProposerSettings for mocking // SetProposerSettings for mocking
func (m *Validator) SetProposerSettings(_ context.Context, settings *validatorserviceconfig.ProposerSettings) error { func (m *Validator) SetProposerSettings(_ context.Context, settings *proposer.Settings) error {
m.proposerSettings = settings m.proposerSettings = settings
return nil return nil
} }

View File

@@ -36,7 +36,7 @@ go_library(
"//config/features:go_default_library", "//config/features:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/blocks:go_default_library", "//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library", "//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
@@ -126,7 +126,7 @@ go_test(
"//config/features:go_default_library", "//config/features:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/blocks:go_default_library", "//consensus-types/blocks:go_default_library",
"//consensus-types/blocks/testing:go_default_library", "//consensus-types/blocks/testing:go_default_library",
"//consensus-types/interfaces:go_default_library", "//consensus-types/interfaces:go_default_library",

View File

@@ -13,7 +13,7 @@ go_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library", "//consensus-types/validator:go_default_library",
"//crypto/bls:go_default_library", "//crypto/bls:go_default_library",

View File

@@ -6,7 +6,7 @@ import (
"time" "time"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/crypto/bls"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
@@ -62,8 +62,8 @@ type Validator interface {
CheckDoppelGanger(ctx context.Context) error CheckDoppelGanger(ctx context.Context) error
PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot, deadline time.Time) error 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) SignValidatorRegistrationRequest(ctx context.Context, signer SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error)
ProposerSettings() *validatorserviceconfig.ProposerSettings ProposerSettings() *proposer.Settings
SetProposerSettings(context.Context, *validatorserviceconfig.ProposerSettings) error SetProposerSettings(context.Context, *proposer.Settings) error
StartEventStream(ctx context.Context) error StartEventStream(ctx context.Context) error
EventStreamIsRunning() bool EventStreamIsRunning() bool
NodeIsHealthy(ctx context.Context) bool NodeIsHealthy(ctx context.Context) bool

View File

@@ -11,7 +11,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/async/event" "github.com/prysmaticlabs/prysm/v5/async/event"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/require"
@@ -225,9 +225,9 @@ func notActive(t *testing.T) [fieldparams.BLSPubkeyLength]byte {
func TestUpdateProposerSettingsAt_EpochStart(t *testing.T) { func TestUpdateProposerSettingsAt_EpochStart(t *testing.T) {
v := &testutil.FakeValidator{Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}} v := &testutil.FakeValidator{Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}}
err := v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err := v.SetProposerSettings(context.Background(), &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
}, },
}, },
@@ -250,9 +250,9 @@ func TestUpdateProposerSettingsAt_EpochStart(t *testing.T) {
func TestUpdateProposerSettingsAt_EpochEndOk(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 := &testutil.FakeValidator{Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}, ProposerSettingWait: time.Duration(params.BeaconConfig().SecondsPerSlot-1) * time.Second}
err := v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err := v.SetProposerSettings(context.Background(), &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
}, },
}, },
@@ -279,9 +279,9 @@ func TestUpdateProposerSettings_ContinuesAfterValidatorRegistrationFails(t *test
ProposerSettingsErr: errors.Wrap(ErrBuilderValidatorRegistration, errSomeotherError.Error()), ProposerSettingsErr: errors.Wrap(ErrBuilderValidatorRegistration, errSomeotherError.Error()),
Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}, Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}},
} }
err := v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err := v.SetProposerSettings(context.Background(), &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
}, },
}, },

View File

@@ -17,7 +17,7 @@ import (
lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru" lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet" "github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet"
@@ -75,7 +75,7 @@ type ValidatorService struct {
grpcHeaders []string grpcHeaders []string
graffiti []byte graffiti []byte
Web3SignerConfig *remoteweb3signer.SetupConfig Web3SignerConfig *remoteweb3signer.SetupConfig
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
validatorsRegBatchSize int validatorsRegBatchSize int
} }
@@ -100,7 +100,7 @@ type Config struct {
GraffitiFlag string GraffitiFlag string
Endpoint string Endpoint string
Web3SignerConfig *remoteweb3signer.SetupConfig Web3SignerConfig *remoteweb3signer.SetupConfig
ProposerSettings *validatorserviceconfig.ProposerSettings ProposerSettings *proposer.Settings
BeaconApiEndpoint string BeaconApiEndpoint string
BeaconApiTimeout time.Duration BeaconApiTimeout time.Duration
ValidatorsRegBatchSize int ValidatorsRegBatchSize int
@@ -271,7 +271,7 @@ func (v *ValidatorService) Keymanager() (keymanager.IKeymanager, error) {
} }
// ProposerSettings returns a deep copy of the underlying proposer settings in the validator // ProposerSettings returns a deep copy of the underlying proposer settings in the validator
func (v *ValidatorService) ProposerSettings() *validatorserviceconfig.ProposerSettings { func (v *ValidatorService) ProposerSettings() *proposer.Settings {
settings := v.validator.ProposerSettings() settings := v.validator.ProposerSettings()
if settings != nil { if settings != nil {
return settings.Clone() return settings.Clone()
@@ -280,7 +280,7 @@ func (v *ValidatorService) ProposerSettings() *validatorserviceconfig.ProposerSe
} }
// SetProposerSettings sets the proposer settings on the validator service as well as the underlying validator // 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 { func (v *ValidatorService) SetProposerSettings(ctx context.Context, settings *proposer.Settings) error {
// validator service proposer settings is only used for pass through from node -> validator service -> validator. // validator service proposer settings is only used for pass through from node -> validator service -> validator.
// in memory use of proposer settings happens on validator. // in memory use of proposer settings happens on validator.
v.proposerSettings = settings v.proposerSettings = settings

View File

@@ -11,7 +11,7 @@ go_library(
visibility = ["//validator:__subpackages__"], visibility = ["//validator:__subpackages__"],
deps = [ deps = [
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library", "//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1:go_default_library",

View File

@@ -6,7 +6,7 @@ import (
"time" "time"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
prysmTime "github.com/prysmaticlabs/prysm/v5/time" prysmTime "github.com/prysmaticlabs/prysm/v5/time"
@@ -52,7 +52,7 @@ type FakeValidator struct {
IndexToPubkeyMap map[uint64][fieldparams.BLSPubkeyLength]byte IndexToPubkeyMap map[uint64][fieldparams.BLSPubkeyLength]byte
PubkeyToIndexMap map[[fieldparams.BLSPubkeyLength]byte]uint64 PubkeyToIndexMap map[[fieldparams.BLSPubkeyLength]byte]uint64
PubkeysToStatusesMap map[[fieldparams.BLSPubkeyLength]byte]ethpb.ValidatorStatus PubkeysToStatusesMap map[[fieldparams.BLSPubkeyLength]byte]ethpb.ValidatorStatus
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
ProposerSettingWait time.Duration ProposerSettingWait time.Duration
Km keymanager.IKeymanager Km keymanager.IKeymanager
} }
@@ -276,12 +276,12 @@ func (*FakeValidator) SignValidatorRegistrationRequest(_ context.Context, _ ifac
} }
// ProposerSettings for mocking // ProposerSettings for mocking
func (fv *FakeValidator) ProposerSettings() *validatorserviceconfig.ProposerSettings { func (fv *FakeValidator) ProposerSettings() *proposer.Settings {
return fv.proposerSettings return fv.proposerSettings
} }
// SetProposerSettings for mocking // SetProposerSettings for mocking
func (fv *FakeValidator) SetProposerSettings(_ context.Context, settings *validatorserviceconfig.ProposerSettings) error { func (fv *FakeValidator) SetProposerSettings(_ context.Context, settings *proposer.Settings) error {
fv.proposerSettings = settings fv.proposerSettings = settings
return nil return nil
} }

View File

@@ -26,7 +26,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/crypto/hash" "github.com/prysmaticlabs/prysm/v5/crypto/hash"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
@@ -106,7 +106,7 @@ type validator struct {
voteStats voteStats voteStats voteStats
syncCommitteeStats syncCommitteeStats syncCommitteeStats syncCommitteeStats
Web3SignerConfig *remoteweb3signer.SetupConfig Web3SignerConfig *remoteweb3signer.SetupConfig
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
walletInitializedChannel chan *wallet.Wallet walletInitializedChannel chan *wallet.Wallet
validatorsRegBatchSize int validatorsRegBatchSize int
} }
@@ -1028,12 +1028,12 @@ func (v *validator) logDuties(slot primitives.Slot, currentEpochDuties []*ethpb.
} }
// ProposerSettings gets the current proposer settings saved in memory validator // ProposerSettings gets the current proposer settings saved in memory validator
func (v *validator) ProposerSettings() *validatorserviceconfig.ProposerSettings { func (v *validator) ProposerSettings() *proposer.Settings {
return v.proposerSettings return v.proposerSettings
} }
// SetProposerSettings sets and saves the passed in proposer settings overriding the in memory one // 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 { func (v *validator) SetProposerSettings(ctx context.Context, settings *proposer.Settings) error {
if v.db == nil { if v.db == nil {
return errors.New("db is not set") return errors.New("db is not set")
} }
@@ -1196,6 +1196,10 @@ func (v *validator) buildSignedRegReqs(ctx context.Context, pubkeys [][fieldpara
gasLimit := params.BeaconConfig().DefaultBuilderGasLimit gasLimit := params.BeaconConfig().DefaultBuilderGasLimit
enabled := false enabled := false
if v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig == nil && v.ProposerSettings().DefaultConfig.BuilderConfig != nil {
log.Warn("Builder is `enabled` in default config but will be ignored because no fee recipient was provided!")
}
if v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig != nil { if v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig != nil {
defaultConfig := v.ProposerSettings().DefaultConfig defaultConfig := v.ProposerSettings().DefaultConfig
feeRecipient = defaultConfig.FeeRecipientConfig.FeeRecipient // Use cli defaultBuilderConfig for fee recipient. feeRecipient = defaultConfig.FeeRecipientConfig.FeeRecipient // Use cli defaultBuilderConfig for fee recipient.

View File

@@ -18,7 +18,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
validatorType "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" validatorType "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/crypto/bls"
@@ -1415,7 +1415,7 @@ func TestValidator_WaitForKeymanagerInitialization_Interop(t *testing.T) {
require.NotNil(t, km) require.NotNil(t, km)
} }
func TestValidator_PushProposerSettings(t *testing.T) { func TestValidator_PushSettings(t *testing.T) {
ctrl := gomock.NewController(t) ctrl := gomock.NewController(t)
ctx := context.Background() ctx := context.Background()
db := dbTest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{}) db := dbTest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
@@ -1459,7 +1459,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
} }
err := v.WaitForKeymanagerInitialization(ctx) err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err) require.NoError(t, err)
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption) config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
km, err := v.Keymanager() km, err := v.Keymanager()
require.NoError(t, err) require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx) keys, err := km.FetchValidatingPublicKeys(ctx)
@@ -1479,22 +1479,22 @@ func TestValidator_PushProposerSettings(t *testing.T) {
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2}, {FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2},
}, },
}).Return(nil, nil) }).Return(nil, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{ config[keys[0]] = &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 40000000, GasLimit: 40000000,
}, },
} }
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: config, ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 35000000, GasLimit: 35000000,
}, },
@@ -1541,7 +1541,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
} }
err := v.WaitForKeymanagerInitialization(ctx) err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err) require.NoError(t, err)
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption) config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
km, err := v.Keymanager() km, err := v.Keymanager()
require.NoError(t, err) require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx) keys, err := km.FetchValidatingPublicKeys(ctx)
@@ -1561,22 +1561,22 @@ func TestValidator_PushProposerSettings(t *testing.T) {
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2}, {FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2},
}, },
}).Return(nil, nil) }).Return(nil, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{ config[keys[0]] = &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 40000000, GasLimit: 40000000,
}, },
} }
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: config, ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: false, Enabled: false,
GasLimit: 35000000, GasLimit: 35000000,
}, },
@@ -1619,7 +1619,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
} }
err := v.WaitForKeymanagerInitialization(ctx) err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err) require.NoError(t, err)
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption) config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
km, err := v.Keymanager() km, err := v.Keymanager()
require.NoError(t, err) require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx) keys, err := km.FetchValidatingPublicKeys(ctx)
@@ -1639,15 +1639,15 @@ func TestValidator_PushProposerSettings(t *testing.T) {
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2}, {FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2},
}, },
}).Return(nil, nil) }).Return(nil, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{ config[keys[0]] = &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
}, },
} }
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: config, ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
}, },
@@ -1687,13 +1687,13 @@ func TestValidator_PushProposerSettings(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx) keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err) require.NoError(t, err)
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: nil, ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: validatorType.Uint64(params.BeaconConfig().DefaultBuilderGasLimit), GasLimit: validatorType.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
}, },
@@ -1748,13 +1748,13 @@ func TestValidator_PushProposerSettings(t *testing.T) {
} }
err := v.WaitForKeymanagerInitialization(ctx) err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err) require.NoError(t, err)
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: nil, ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 40000000, GasLimit: 40000000,
}, },
@@ -1812,7 +1812,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
} }
err := v.WaitForKeymanagerInitialization(ctx) err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err) require.NoError(t, err)
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption) config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
km, err := v.Keymanager() km, err := v.Keymanager()
require.NoError(t, err) require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx) keys, err := km.FetchValidatingPublicKeys(ctx)
@@ -1830,15 +1830,15 @@ func TestValidator_PushProposerSettings(t *testing.T) {
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1}, {FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},
}, },
}).Return(nil, nil) }).Return(nil, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{ config[keys[0]] = &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.Address{}, FeeRecipient: common.Address{},
}, },
} }
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: config, ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
}, },
@@ -1864,7 +1864,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
} }
err := v.WaitForKeymanagerInitialization(ctx) err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err) require.NoError(t, err)
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption) config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
km, err := v.Keymanager() km, err := v.Keymanager()
require.NoError(t, err) require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx) keys, err := km.FetchValidatingPublicKeys(ctx)
@@ -1873,15 +1873,15 @@ func TestValidator_PushProposerSettings(t *testing.T) {
gomock.Any(), // ctx gomock.Any(), // ctx
&ethpb.ValidatorIndexRequest{PublicKey: keys[0][:]}, &ethpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
).Return(nil, errors.New("could not find validator index for public key")) ).Return(nil, errors.New("could not find validator index for public key"))
config[keys[0]] = &validatorserviceconfig.ProposerOption{ config[keys[0]] = &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
}, },
} }
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: config, ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
}, },
@@ -1907,7 +1907,7 @@ func TestValidator_PushProposerSettings(t *testing.T) {
} }
err := v.WaitForKeymanagerInitialization(ctx) err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err) require.NoError(t, err)
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption) config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
km, err := v.Keymanager() km, err := v.Keymanager()
require.NoError(t, err) require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx) keys, err := km.FetchValidatingPublicKeys(ctx)
@@ -1921,22 +1921,22 @@ func TestValidator_PushProposerSettings(t *testing.T) {
PublicKeys: [][]byte{keys[0][:]}, PublicKeys: [][]byte{keys[0][:]},
}, nil) }, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{ config[keys[0]] = &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.Address{}, FeeRecipient: common.Address{},
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 40000000, GasLimit: 40000000,
}, },
} }
err = v.SetProposerSettings(context.Background(), &validatorserviceconfig.ProposerSettings{ err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: config, ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(defaultFeeHex), FeeRecipient: common.HexToAddress(defaultFeeHex),
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 40000000, GasLimit: 40000000,
}, },
@@ -2072,26 +2072,26 @@ func TestValidator_buildPrepProposerReqs_WithoutDefaultConfig(t *testing.T) {
}, nil) }, nil)
v := validator{ v := validator{
validatorClient: client, validatorClient: client,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
DefaultConfig: nil, DefaultConfig: nil,
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
pubkey1: { pubkey1: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient1, FeeRecipient: feeRecipient1,
}, },
}, },
pubkey2: { pubkey2: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient2, FeeRecipient: feeRecipient2,
}, },
}, },
pubkey3: { pubkey3: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient3, FeeRecipient: feeRecipient3,
}, },
}, },
pubkey4: { pubkey4: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient4, FeeRecipient: feeRecipient4,
}, },
}, },
@@ -2215,30 +2215,30 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) {
v := validator{ v := validator{
validatorClient: client, validatorClient: client,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: defaultFeeRecipient, FeeRecipient: defaultFeeRecipient,
}, },
}, },
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
pubkey1: { pubkey1: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient1, FeeRecipient: feeRecipient1,
}, },
}, },
pubkey2: { pubkey2: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient2, FeeRecipient: feeRecipient2,
}, },
}, },
pubkey3: { pubkey3: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient3, FeeRecipient: feeRecipient3,
}, },
}, },
pubkey8: { pubkey8: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient8, FeeRecipient: feeRecipient8,
}, },
}, },
@@ -2322,38 +2322,38 @@ func TestValidator_buildSignedRegReqs_DefaultConfigDisabled(t *testing.T) {
v := validator{ v := validator{
signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{}, signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{},
validatorClient: client, validatorClient: client,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: defaultFeeRecipient, FeeRecipient: defaultFeeRecipient,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: false, Enabled: false,
GasLimit: 9999, GasLimit: 9999,
}, },
}, },
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
pubkey1: { pubkey1: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient1, FeeRecipient: feeRecipient1,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 1111, GasLimit: 1111,
}, },
}, },
pubkey2: { pubkey2: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient2, FeeRecipient: feeRecipient2,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: false, Enabled: false,
GasLimit: 2222, GasLimit: 2222,
}, },
}, },
pubkey3: { pubkey3: {
FeeRecipientConfig: nil, FeeRecipientConfig: nil,
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 3333, GasLimit: 3333,
}, },
@@ -2407,38 +2407,38 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) {
v := validator{ v := validator{
signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{}, signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{},
validatorClient: client, validatorClient: client,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: defaultFeeRecipient, FeeRecipient: defaultFeeRecipient,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 9999, GasLimit: 9999,
}, },
}, },
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
pubkey1: { pubkey1: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient1, FeeRecipient: feeRecipient1,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 1111, GasLimit: 1111,
}, },
}, },
pubkey2: { pubkey2: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient2, FeeRecipient: feeRecipient2,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: false, Enabled: false,
GasLimit: 2222, GasLimit: 2222,
}, },
}, },
pubkey3: { pubkey3: {
FeeRecipientConfig: nil, FeeRecipientConfig: nil,
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 3333, GasLimit: 3333,
}, },
@@ -2485,12 +2485,12 @@ func TestValidator_buildSignedRegReqs_SignerOnError(t *testing.T) {
v := validator{ v := validator{
signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{}, signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{},
validatorClient: client, validatorClient: client,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: defaultFeeRecipient, FeeRecipient: defaultFeeRecipient,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 9999, GasLimit: 9999,
}, },
@@ -2529,22 +2529,22 @@ func TestValidator_buildSignedRegReqs_TimestampBeforeGenesis(t *testing.T) {
signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{}, signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{},
validatorClient: client, validatorClient: client,
genesisTime: uint64(time.Now().UTC().Unix() + 1000), genesisTime: uint64(time.Now().UTC().Unix() + 1000),
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: defaultFeeRecipient, FeeRecipient: defaultFeeRecipient,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 9999, GasLimit: 9999,
}, },
}, },
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
pubkey1: { pubkey1: {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient1, FeeRecipient: feeRecipient1,
}, },
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 1111, GasLimit: 1111,
}, },

View File

@@ -5,10 +5,13 @@ go_library(
srcs = ["interface.go"], srcs = ["interface.go"],
importpath = "github.com/prysmaticlabs/prysm/v5/validator/db/iface", importpath = "github.com/prysmaticlabs/prysm/v5/validator/db/iface",
# Other packages must use github.com/prysmaticlabs/prysm/v5/validator/db.Database alias. # Other packages must use github.com/prysmaticlabs/prysm/v5/validator/db.Database alias.
visibility = ["//validator:__subpackages__"], visibility = [
"//config:__subpackages__",
"//validator:__subpackages__",
],
deps = [ deps = [
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//monitoring/backup:go_default_library", "//monitoring/backup:go_default_library",
"//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1:go_default_library",

View File

@@ -6,7 +6,7 @@ import (
"io" "io"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
validatorServiceConfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/monitoring/backup" "github.com/prysmaticlabs/prysm/v5/monitoring/backup"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
@@ -65,9 +65,7 @@ type ValidatorDB interface {
GraffitiOrderedIndex(ctx context.Context, fileHash [32]byte) (uint64, error) GraffitiOrderedIndex(ctx context.Context, fileHash [32]byte) (uint64, error)
// ProposerSettings related methods // ProposerSettings related methods
ProposerSettings(context.Context) (*validatorServiceConfig.ProposerSettings, error) ProposerSettings(context.Context) (*proposer.Settings, error)
ProposerSettingsExists(ctx context.Context) (bool, error) ProposerSettingsExists(ctx context.Context) (bool, error)
UpdateProposerSettingsDefault(context.Context, *validatorServiceConfig.ProposerOption) error SaveProposerSettings(ctx context.Context, settings *proposer.Settings) error
UpdateProposerSettingsForPubkey(context.Context, [fieldparams.BLSPubkeyLength]byte, *validatorServiceConfig.ProposerOption) error
SaveProposerSettings(ctx context.Context, settings *validatorServiceConfig.ProposerSettings) error
} }

View File

@@ -30,7 +30,7 @@ go_library(
"//config/features:go_default_library", "//config/features:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library", "//encoding/bytesutil:go_default_library",
"//io/file:go_default_library", "//io/file:go_default_library",
@@ -70,7 +70,7 @@ go_test(
deps = [ deps = [
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library", "//consensus-types/validator:go_default_library",
"//crypto/hash:go_default_library", "//crypto/hash:go_default_library",

View File

@@ -2,11 +2,9 @@ package kv
import ( import (
"context" "context"
"fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/proposer"
validatorServiceConfig "github.com/prysmaticlabs/prysm/v5/config/validator/service"
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@@ -16,74 +14,9 @@ import (
// ErrNoProposerSettingsFound is an error thrown when no settings are found in bucket // ErrNoProposerSettingsFound is an error thrown when no settings are found in bucket
var ErrNoProposerSettingsFound = errors.New("no proposer settings found in bucket") var ErrNoProposerSettingsFound = errors.New("no proposer settings found in bucket")
// UpdateProposerSettingsForPubkey updates the existing settings for an internal representation of the proposers settings file at a particular public key
func (s *Store) UpdateProposerSettingsForPubkey(ctx context.Context, pubkey [fieldparams.BLSPubkeyLength]byte, options *validatorServiceConfig.ProposerOption) error {
_, span := trace.StartSpan(ctx, "validator.db.UpdateProposerSettingsForPubkey")
defer span.End()
err := s.db.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket(proposerSettingsBucket)
b := bkt.Get(proposerSettingsKey)
if len(b) == 0 {
return fmt.Errorf("no proposer settings found in bucket")
}
to := &validatorpb.ProposerSettingsPayload{}
if err := proto.Unmarshal(b, to); err != nil {
return errors.Wrap(err, "failed to unmarshal proposer settings")
}
settings, err := validatorServiceConfig.ToSettings(to)
if err != nil {
return errors.Wrap(err, "failed to convert payload to proposer settings")
}
if settings.ProposeConfig == nil {
settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption)
}
settings.ProposeConfig[pubkey] = options
m, err := proto.Marshal(settings.ToPayload())
if err != nil {
return errors.Wrap(err, "failed to marshal proposer settings")
}
return bkt.Put(proposerSettingsKey, m)
})
return err
}
// UpdateProposerSettingsDefault updates the existing default settings for proposer settings
func (s *Store) UpdateProposerSettingsDefault(ctx context.Context, options *validatorServiceConfig.ProposerOption) error {
_, span := trace.StartSpan(ctx, "validator.db.UpdateProposerSettingsDefault")
defer span.End()
if options == nil {
return errors.New("proposer settings option was empty")
}
if options.FeeRecipientConfig == nil {
return errors.New("fee recipient cannot be empty")
}
err := s.db.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket(proposerSettingsBucket)
b := bkt.Get(proposerSettingsKey)
if len(b) == 0 {
return ErrNoProposerSettingsFound
}
to := &validatorpb.ProposerSettingsPayload{}
if err := proto.Unmarshal(b, to); err != nil {
return errors.Wrap(err, "failed to unmarshal proposer settings")
}
settings, err := validatorServiceConfig.ToSettings(to)
if err != nil {
return errors.Wrap(err, "failed to convert payload to proposer settings")
}
settings.DefaultConfig = options
m, err := proto.Marshal(settings.ToPayload())
if err != nil {
return errors.Wrap(err, "failed to marshal proposer settings")
}
return bkt.Put(proposerSettingsKey, m)
})
return err
}
// ProposerSettings gets the current proposer settings // ProposerSettings gets the current proposer settings
func (s *Store) ProposerSettings(ctx context.Context) (*validatorServiceConfig.ProposerSettings, error) { func (s *Store) ProposerSettings(ctx context.Context) (*proposer.Settings, error) {
_, span := trace.StartSpan(ctx, "validator.db.ProposerSettings") _, span := trace.StartSpan(ctx, "validator.db.Settings")
defer span.End() defer span.End()
to := &validatorpb.ProposerSettingsPayload{} to := &validatorpb.ProposerSettingsPayload{}
if err := s.db.View(func(tx *bolt.Tx) error { if err := s.db.View(func(tx *bolt.Tx) error {
@@ -99,7 +32,7 @@ func (s *Store) ProposerSettings(ctx context.Context) (*validatorServiceConfig.P
}); err != nil { }); err != nil {
return nil, err return nil, err
} }
return validatorServiceConfig.ToSettings(to) return proposer.SettingFromConsensus(to)
} }
// ProposerSettingsExists returns true or false if the settings exist or not // ProposerSettingsExists returns true or false if the settings exist or not
@@ -118,7 +51,7 @@ func (s *Store) ProposerSettingsExists(ctx context.Context) (bool, error) {
} }
// SaveProposerSettings saves the entire proposer setting overriding the existing settings // SaveProposerSettings saves the entire proposer setting overriding the existing settings
func (s *Store) SaveProposerSettings(ctx context.Context, settings *validatorServiceConfig.ProposerSettings) error { func (s *Store) SaveProposerSettings(ctx context.Context, settings *proposer.Settings) error {
_, span := trace.StartSpan(ctx, "validator.db.SaveProposerSettings") _, span := trace.StartSpan(ctx, "validator.db.SaveProposerSettings")
defer span.End() defer span.End()
// nothing to save // nothing to save
@@ -128,7 +61,7 @@ func (s *Store) SaveProposerSettings(ctx context.Context, settings *validatorSer
} }
return s.db.Update(func(tx *bolt.Tx) error { return s.db.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket(proposerSettingsBucket) bkt := tx.Bucket(proposerSettingsBucket)
m, err := proto.Marshal(settings.ToPayload()) m, err := proto.Marshal(settings.ToConsensus())
if err != nil { if err != nil {
return errors.Wrap(err, "failed to marshal proposer settings") return errors.Wrap(err, "failed to marshal proposer settings")
} }

View File

@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorServiceConfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/require"
@@ -20,23 +20,23 @@ func TestStore_ProposerSettings_ReadAndWrite(t *testing.T) {
db := setupDB(t, [][fieldparams.BLSPubkeyLength]byte{}) db := setupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a") key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err) require.NoError(t, err)
settings := &validatorServiceConfig.ProposerSettings{ settings := &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption{ ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(key1): { bytesutil.ToBytes48(key1): {
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
}, },
BuilderConfig: &validatorServiceConfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: validator.Uint64(40000000), GasLimit: validator.Uint64(40000000),
}, },
}, },
}, },
DefaultConfig: &validatorServiceConfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"), FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
}, },
BuilderConfig: &validatorServiceConfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: false, Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit), GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
}, },
@@ -54,12 +54,12 @@ func TestStore_ProposerSettings_ReadAndWrite(t *testing.T) {
db := setupDB(t, [][fieldparams.BLSPubkeyLength]byte{}) db := setupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a") key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err) require.NoError(t, err)
settings := &validatorServiceConfig.ProposerSettings{ settings := &proposer.Settings{
DefaultConfig: &validatorServiceConfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"), FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
}, },
BuilderConfig: &validatorServiceConfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: false, Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit), GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
}, },
@@ -67,38 +67,41 @@ func TestStore_ProposerSettings_ReadAndWrite(t *testing.T) {
} }
err = db.SaveProposerSettings(ctx, settings) err = db.SaveProposerSettings(ctx, settings)
require.NoError(t, err) require.NoError(t, err)
upatedDefault := &validatorServiceConfig.ProposerOption{ updatedDefault := &proposer.Option{
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x9995733c5af9B61374A128e6F85f553aF09ff89B"), FeeRecipient: common.HexToAddress("0x9995733c5af9B61374A128e6F85f553aF09ff89B"),
}, },
BuilderConfig: &validatorServiceConfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit), GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
}, },
} }
err = db.UpdateProposerSettingsDefault(ctx, upatedDefault) settings.DefaultConfig = updatedDefault
err = db.SaveProposerSettings(ctx, settings)
require.NoError(t, err) require.NoError(t, err)
dbSettings, err := db.ProposerSettings(ctx) dbSettings, err := db.ProposerSettings(ctx)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, dbSettings) require.NotNil(t, dbSettings)
require.DeepEqual(t, dbSettings.DefaultConfig, upatedDefault) require.DeepEqual(t, dbSettings.DefaultConfig, updatedDefault)
option := &validatorServiceConfig.ProposerOption{ option := &proposer.Option{
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"), FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
}, },
BuilderConfig: &validatorServiceConfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: validator.Uint64(40000000), GasLimit: validator.Uint64(40000000),
}, },
} }
err = db.UpdateProposerSettingsForPubkey(ctx, bytesutil.ToBytes48(key1), option)
dbSettings.ProposeConfig = map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{bytesutil.ToBytes48(key1): option}
err = db.SaveProposerSettings(ctx, dbSettings)
require.NoError(t, err) require.NoError(t, err)
newSettings, err := db.ProposerSettings(ctx) newSettings, err := db.ProposerSettings(ctx)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, newSettings) require.NotNil(t, newSettings)
require.DeepEqual(t, newSettings.DefaultConfig, upatedDefault) require.DeepEqual(t, newSettings.DefaultConfig, updatedDefault)
op, ok := newSettings.ProposeConfig[bytesutil.ToBytes48(key1)] op, ok := newSettings.ProposeConfig[bytesutil.ToBytes48(key1)]
require.Equal(t, ok, true) require.Equal(t, ok, true)
require.DeepEqual(t, op, option) require.DeepEqual(t, op, option)

View File

@@ -6,6 +6,7 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/v5/validator/db/testing", importpath = "github.com/prysmaticlabs/prysm/v5/validator/db/testing",
visibility = [ visibility = [
"//cmd:__subpackages__", "//cmd:__subpackages__",
"//config:__subpackages__",
"//validator:__subpackages__", "//validator:__subpackages__",
], ],
deps = [ deps = [

View File

@@ -4,27 +4,19 @@ go_test(
name = "go_default_test", name = "go_default_test",
size = "small", size = "small",
srcs = ["node_test.go"], srcs = ["node_test.go"],
data = glob(["testdata/**"]),
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//cmd:go_default_library", "//cmd:go_default_library",
"//cmd/validator/flags:go_default_library", "//cmd/validator/flags:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//config/validator/service:go_default_library",
"//consensus-types/validator:go_default_library",
"//encoding/bytesutil:go_default_library", "//encoding/bytesutil:go_default_library",
"//io/file:go_default_library", "//io/file:go_default_library",
"//testing/assert:go_default_library", "//testing/assert:go_default_library",
"//testing/require:go_default_library", "//testing/require:go_default_library",
"//validator/accounts:go_default_library", "//validator/accounts:go_default_library",
"//validator/accounts/wallet:go_default_library", "//validator/accounts/wallet:go_default_library",
"//validator/db/iface:go_default_library",
"//validator/db/kv:go_default_library", "//validator/db/kv:go_default_library",
"//validator/db/testing:go_default_library",
"//validator/keymanager:go_default_library", "//validator/keymanager:go_default_library",
"//validator/keymanager/remote-web3signer:go_default_library", "//validator/keymanager/remote-web3signer:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library",
@@ -50,10 +42,9 @@ go_library(
"//cmd:go_default_library", "//cmd:go_default_library",
"//cmd/validator/flags:go_default_library", "//cmd/validator/flags:go_default_library",
"//config/features:go_default_library", "//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/validator:go_default_library", "//config/proposer/loader:go_default_library",
"//container/slice:go_default_library", "//container/slice:go_default_library",
"//encoding/bytesutil:go_default_library", "//encoding/bytesutil:go_default_library",
"//io/file:go_default_library", "//io/file:go_default_library",
@@ -61,7 +52,6 @@ go_library(
"//monitoring/prometheus:go_default_library", "//monitoring/prometheus:go_default_library",
"//monitoring/tracing:go_default_library", "//monitoring/tracing:go_default_library",
"//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//runtime:go_default_library", "//runtime:go_default_library",
"//runtime/debug:go_default_library", "//runtime/debug:go_default_library",
"//runtime/prereqs:go_default_library", "//runtime/prereqs:go_default_library",
@@ -75,7 +65,6 @@ go_library(
"//validator/keymanager/remote-web3signer:go_default_library", "//validator/keymanager/remote-web3signer:go_default_library",
"//validator/rpc:go_default_library", "//validator/rpc:go_default_library",
"//validator/web:go_default_library", "//validator/web:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_gorilla_mux//:go_default_library", "@com_github_gorilla_mux//:go_default_library",
"@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library",
@@ -83,7 +72,6 @@ go_library(
"@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library",
"@io_k8s_apimachinery//pkg/util/yaml:go_default_library",
"@org_golang_google_protobuf//encoding/protojson:go_default_library", "@org_golang_google_protobuf//encoding/protojson:go_default_library",
], ],
) )

View File

@@ -5,22 +5,18 @@ package node
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"io"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
"time" "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gorilla/mux" "github.com/gorilla/mux"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
@@ -33,10 +29,9 @@ import (
"github.com/prysmaticlabs/prysm/v5/cmd" "github.com/prysmaticlabs/prysm/v5/cmd"
"github.com/prysmaticlabs/prysm/v5/cmd/validator/flags" "github.com/prysmaticlabs/prysm/v5/cmd/validator/flags"
"github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorServiceConfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/config/proposer/loader"
"github.com/prysmaticlabs/prysm/v5/container/slice" "github.com/prysmaticlabs/prysm/v5/container/slice"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/io/file" "github.com/prysmaticlabs/prysm/v5/io/file"
@@ -44,7 +39,6 @@ import (
"github.com/prysmaticlabs/prysm/v5/monitoring/prometheus" "github.com/prysmaticlabs/prysm/v5/monitoring/prometheus"
tracing2 "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" tracing2 "github.com/prysmaticlabs/prysm/v5/monitoring/tracing"
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v5/runtime" "github.com/prysmaticlabs/prysm/v5/runtime"
"github.com/prysmaticlabs/prysm/v5/runtime/debug" "github.com/prysmaticlabs/prysm/v5/runtime/debug"
"github.com/prysmaticlabs/prysm/v5/runtime/prereqs" "github.com/prysmaticlabs/prysm/v5/runtime/prereqs"
@@ -61,7 +55,6 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
"k8s.io/apimachinery/pkg/util/yaml"
) )
// ValidatorClient defines an instance of an Ethereum validator that manages // ValidatorClient defines an instance of an Ethereum validator that manages
@@ -469,7 +462,7 @@ func (c *ValidatorClient) registerValidatorService(cliCtx *cli.Context) error {
return err return err
} }
proposerSettings, err := proposerSettings(c.cliCtx, c.db) ps, err := proposerSettings(c.cliCtx, c.db)
if err != nil { if err != nil {
return err return err
} }
@@ -492,7 +485,7 @@ func (c *ValidatorClient) registerValidatorService(cliCtx *cli.Context) error {
WalletInitializedFeed: c.walletInitialized, WalletInitializedFeed: c.walletInitialized,
GraffitiStruct: graffitiStruct, GraffitiStruct: graffitiStruct,
Web3SignerConfig: web3signerConfig, Web3SignerConfig: web3signerConfig,
ProposerSettings: proposerSettings, ProposerSettings: ps,
BeaconApiTimeout: time.Second * 30, BeaconApiTimeout: time.Second * 30,
BeaconApiEndpoint: c.cliCtx.String(flags.BeaconRESTApiProviderFlag.Name), BeaconApiEndpoint: c.cliCtx.String(flags.BeaconRESTApiProviderFlag.Name),
ValidatorsRegBatchSize: c.cliCtx.Int(flags.ValidatorsRegistrationBatchSizeFlag.Name), ValidatorsRegBatchSize: c.cliCtx.Int(flags.ValidatorsRegistrationBatchSizeFlag.Name),
@@ -553,234 +546,17 @@ func Web3SignerConfig(cliCtx *cli.Context) (*remoteweb3signer.SetupConfig, error
return web3signerConfig, nil return web3signerConfig, nil
} }
func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*validatorServiceConfig.ProposerSettings, error) { func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*proposer.Settings, error) {
var fileConfig *validatorpb.ProposerSettingsPayload l, err := loader.NewProposerSettingsLoader(
cliCtx,
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) && cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) { db,
return nil, errors.New("cannot specify both " + flags.ProposerSettingsFlag.Name + " and " + flags.ProposerSettingsURLFlag.Name) loader.WithBuilderConfig(),
} loader.WithGasLimit(),
builderConfigFromFlag, err := BuilderSettingsFromFlags(cliCtx) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
// is overridden by file and URL flags return l.Load(cliCtx)
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) &&
!cliCtx.IsSet(flags.ProposerSettingsFlag.Name) &&
!cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
suggestedFee := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)
fileConfig = &validatorpb.ProposerSettingsPayload{
ProposerConfig: nil,
DefaultConfig: &validatorpb.ProposerOptionPayload{
FeeRecipient: suggestedFee,
Builder: builderConfigFromFlag.ToPayload(),
},
}
}
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) {
if err := unmarshalFromFile(cliCtx.Context, cliCtx.String(flags.ProposerSettingsFlag.Name), &fileConfig); err != nil {
return nil, err
}
}
if cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
if err := unmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &fileConfig); err != nil {
return nil, err
}
}
// this condition triggers if SuggestedFeeRecipientFlag,ProposerSettingsFlag or ProposerSettingsURLFlag did not create any settings
if fileConfig == 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{}
// default fileConfig is mandatory
if fileConfig.DefaultConfig == nil {
return nil, errors.New("default fileConfig is required, proposer settings file is either empty or an incorrect format")
}
if !common.IsHexAddress(fileConfig.DefaultConfig.FeeRecipient) {
return nil, errors.New("default fileConfig fee recipient is not a valid eth1 address")
}
psExists, err := db.ProposerSettingsExists(cliCtx.Context)
if err != nil {
return nil, err
}
if err := warnNonChecksummedAddress(fileConfig.DefaultConfig.FeeRecipient); err != nil {
return nil, err
}
vpSettings.DefaultConfig = &validatorServiceConfig.ProposerOption{
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(fileConfig.DefaultConfig.FeeRecipient),
},
BuilderConfig: validatorServiceConfig.ToBuilderConfig(fileConfig.DefaultConfig.Builder),
}
if builderConfigFromFlag != nil {
config := builderConfigFromFlag.Clone()
if config.GasLimit == validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit) && vpSettings.DefaultConfig.BuilderConfig != nil {
config.GasLimit = vpSettings.DefaultConfig.BuilderConfig.GasLimit
}
vpSettings.DefaultConfig.BuilderConfig = config
} else if vpSettings.DefaultConfig.BuilderConfig != nil {
vpSettings.DefaultConfig.BuilderConfig.GasLimit = reviewGasLimit(vpSettings.DefaultConfig.BuilderConfig.GasLimit)
}
if psExists {
// if settings exist update the default
if err := db.UpdateProposerSettingsDefault(cliCtx.Context, vpSettings.DefaultConfig); err != nil {
return nil, err
}
}
if fileConfig.ProposerConfig != nil && len(fileConfig.ProposerConfig) != 0 {
vpSettings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption)
for key, option := range fileConfig.ProposerConfig {
decodedKey, err := hexutil.Decode(key)
if err != nil {
return nil, errors.Wrapf(err, "could not decode public key %s", key)
}
if len(decodedKey) != fieldparams.BLSPubkeyLength {
return nil, fmt.Errorf("%v is not a bls public key", key)
}
if err := verifyOption(key, option); err != nil {
return nil, err
}
currentBuilderConfig := validatorServiceConfig.ToBuilderConfig(option.Builder)
if builderConfigFromFlag != nil {
config := builderConfigFromFlag.Clone()
if config.GasLimit == validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit) && currentBuilderConfig != nil {
config.GasLimit = currentBuilderConfig.GasLimit
}
currentBuilderConfig = config
} else if currentBuilderConfig != nil {
currentBuilderConfig.GasLimit = reviewGasLimit(currentBuilderConfig.GasLimit)
}
o := &validatorServiceConfig.ProposerOption{
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress(option.FeeRecipient),
},
BuilderConfig: currentBuilderConfig,
}
pubkeyB := bytesutil.ToBytes48(decodedKey)
vpSettings.ProposeConfig[pubkeyB] = o
}
if psExists {
// override the existing saved settings if providing values via fileConfig.ProposerConfig
if err := db.SaveProposerSettings(cliCtx.Context, vpSettings); err != nil {
return nil, err
}
}
}
if !psExists {
// if no proposer settings ever existed in the db just save the settings
if err := db.SaveProposerSettings(cliCtx.Context, vpSettings); err != nil {
return nil, err
}
}
return vpSettings, nil
}
func verifyOption(key string, option *validatorpb.ProposerOptionPayload) error {
if option == nil {
return fmt.Errorf("fee recipient is required for proposer %s", key)
}
if !common.IsHexAddress(option.FeeRecipient) {
return errors.New("fee recipient is not a valid eth1 address")
}
if err := warnNonChecksummedAddress(option.FeeRecipient); err != nil {
return err
}
return 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)
sgl := cliCtx.String(flags.BuilderGasLimitFlag.Name)
if sgl != "" {
gl, err := strconv.ParseUint(sgl, 10, 64)
if err != nil {
return nil, errors.New("Gas Limit is not a uint64")
}
gasLimit = reviewGasLimit(validator.Uint64(gl))
}
return &validatorServiceConfig.BuilderConfig{
Enabled: true,
GasLimit: gasLimit,
}, nil
}
return nil, nil
}
func warnNonChecksummedAddress(feeRecipient string) error {
mixedcaseAddress, err := common.NewMixedcaseAddressFromString(feeRecipient)
if err != nil {
return errors.Wrapf(err, "could not decode fee recipient %s", feeRecipient)
}
if !mixedcaseAddress.ValidChecksum() {
log.Warnf("Fee recipient %s is not a checksum Ethereum address. "+
"The checksummed address is %s and will be used as the fee recipient. "+
"We recommend using a mixed-case address (checksum) "+
"to prevent spelling mistakes in your fee recipient Ethereum address", feeRecipient, mixedcaseAddress.Address().Hex())
}
return nil
}
func reviewGasLimit(gasLimit validator.Uint64) validator.Uint64 {
// sets gas limit to default if not defined or set to 0
if gasLimit == 0 {
return validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit)
}
// TODO(10810): add in warning for ranges
return gasLimit
} }
func (c *ValidatorClient) registerRPCService(router *mux.Router) error { func (c *ValidatorClient) registerRPCService(router *mux.Router) error {
@@ -960,55 +736,6 @@ func clearDB(ctx context.Context, dataDir string, force bool) error {
return nil return nil
} }
func unmarshalFromURL(ctx context.Context, from string, to interface{}) error {
u, err := url.ParseRequestURI(from)
if err != nil {
return err
}
if u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid URL: %s", from)
}
req, reqerr := http.NewRequestWithContext(ctx, http.MethodGet, from, nil)
if reqerr != nil {
return errors.Wrap(reqerr, "failed to create http request")
}
req.Header.Set("Content-Type", "application/json")
resp, resperr := http.DefaultClient.Do(req)
if resperr != nil {
return errors.Wrap(resperr, "failed to send http request")
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
log.WithError(err).Error("failed to close response body")
}
}(resp.Body)
if resp.StatusCode != http.StatusOK {
return errors.Errorf("http request to %v failed with status code %d", from, resp.StatusCode)
}
if decodeerr := json.NewDecoder(resp.Body).Decode(&to); decodeerr != nil {
return errors.Wrap(decodeerr, "failed to decode http response")
}
return nil
}
func unmarshalFromFile(ctx context.Context, from string, to interface{}) error {
if ctx == nil {
return errors.New("node: nil context passed to unmarshalFromFile")
}
cleanpath := filepath.Clean(from)
b, err := os.ReadFile(cleanpath)
if err != nil {
return errors.Wrap(err, "failed to open file")
}
if err := yaml.Unmarshal(b, to); err != nil {
return errors.Wrap(err, "failed to unmarshal yaml file")
}
return nil
}
func configureFastSSZHashingAlgorithm() { func configureFastSSZHashingAlgorithm() {
fastssz.EnableVectorizedHTR = true fastssz.EnableVectorizedHTR = true
} }

View File

@@ -3,31 +3,21 @@ package node
import ( import (
"context" "context"
"flag" "flag"
"fmt"
"net/http"
"net/http/httptest"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/prysmaticlabs/prysm/v5/cmd" "github.com/prysmaticlabs/prysm/v5/cmd"
"github.com/prysmaticlabs/prysm/v5/cmd/validator/flags" "github.com/prysmaticlabs/prysm/v5/cmd/validator/flags"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/io/file" "github.com/prysmaticlabs/prysm/v5/io/file"
"github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/validator/accounts" "github.com/prysmaticlabs/prysm/v5/validator/accounts"
"github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet" "github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet"
"github.com/prysmaticlabs/prysm/v5/validator/db/iface"
"github.com/prysmaticlabs/prysm/v5/validator/db/kv" "github.com/prysmaticlabs/prysm/v5/validator/db/kv"
dbTest "github.com/prysmaticlabs/prysm/v5/validator/db/testing"
"github.com/prysmaticlabs/prysm/v5/validator/keymanager" "github.com/prysmaticlabs/prysm/v5/validator/keymanager"
remoteweb3signer "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer" remoteweb3signer "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer"
logtest "github.com/sirupsen/logrus/hooks/test" logtest "github.com/sirupsen/logrus/hooks/test"
@@ -344,722 +334,3 @@ func TestWeb3SignerConfig(t *testing.T) {
}) })
} }
} }
func TestProposerSettings(t *testing.T) {
hook := logtest.NewGlobal()
type proposerSettingsFlag struct {
dir string
url string
defaultfee string
defaultgas string
}
type args struct {
proposerSettingsFlagValues *proposerSettingsFlag
}
tests := []struct {
name string
args args
want func() *validatorserviceconfig.ProposerSettings
urlResponse string
wantErr string
wantLog string
withdb func(db iface.ValidatorDB) error
validatorRegistrationEnabled bool
}{
{
name: "Happy Path default only proposer settings file with builder settings,",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/default-only-proposer-config.json",
url: "",
defaultfee: "",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return &validatorserviceconfig.ProposerSettings{
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
BuilderConfig: &validatorserviceconfig.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
},
{
name: "Happy Path Config file File, bad checksum",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config-badchecksum.json",
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("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
},
},
}
},
wantErr: "",
wantLog: "is not a checksum Ethereum address",
},
{
name: "Happy Path Config file File multiple fee recipients",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config-multiple.json",
url: "",
defaultfee: "",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
key2, err := hexutil.Decode("0xb057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7b")
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),
},
},
bytesutil.ToBytes48(key2): {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x60155530FCE8a85ec7055A5F8b2bE214B3DaeFd4"),
},
BuilderConfig: &validatorserviceconfig.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(35000000),
},
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &validatorserviceconfig.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Config URL File",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "./testdata/good-prepare-beacon-proposer-config.json",
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"),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Config YAML file with custom Gas Limit",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
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: 40000000,
},
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &validatorserviceconfig.BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Suggested Fee ",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Suggested Fee , validator registration enabled",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &validatorserviceconfig.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "Happy Path Suggested Fee , validator registration enabled and default gas",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
defaultgas: "50000000",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &validatorserviceconfig.BuilderConfig{
Enabled: true,
GasLimit: 50000000,
},
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "Suggested Fee does not Override Config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89B",
},
},
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"),
},
},
}
},
wantErr: "",
},
{
name: "Suggested Fee with validator registration does not Override Config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89B",
},
},
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),
},
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "Enable Builder flag overrides empty config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
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),
},
},
}
},
validatorRegistrationEnabled: true,
},
{
name: "Enable Builder flag does override completed builder config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
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(40000000),
},
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &validatorserviceconfig.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
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{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return nil
},
wantErr: "",
},
{
name: "Bad File Path",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/bad-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return nil
},
wantErr: "failed to unmarshal yaml file",
},
{
name: "Both URL and Dir flags used resulting in error",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "./testdata/good-prepare-beacon-proposer-config.json",
defaultfee: "",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return &validatorserviceconfig.ProposerSettings{}
},
wantErr: "cannot specify both",
},
{
name: "Bad Gas value in JSON",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/bad-gas-value-proposer-settings.json",
url: "",
defaultfee: "",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return nil
},
wantErr: "failed to unmarshal yaml file",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
app := cli.App{}
set := flag.NewFlagSet("test", 0)
if tt.args.proposerSettingsFlagValues.dir != "" {
set.String(flags.ProposerSettingsFlag.Name, tt.args.proposerSettingsFlagValues.dir, "")
require.NoError(t, set.Set(flags.ProposerSettingsFlag.Name, tt.args.proposerSettingsFlagValues.dir))
}
if tt.args.proposerSettingsFlagValues.url != "" {
content, err := os.ReadFile(tt.args.proposerSettingsFlagValues.url)
require.NoError(t, err)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Header().Set("Content-Type", "application/json")
_, err := fmt.Fprintf(w, "%s", content)
require.NoError(t, err)
}))
defer srv.Close()
set.String(flags.ProposerSettingsURLFlag.Name, tt.args.proposerSettingsFlagValues.url, "")
require.NoError(t, set.Set(flags.ProposerSettingsURLFlag.Name, srv.URL))
}
if tt.args.proposerSettingsFlagValues.defaultfee != "" {
set.String(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee, "")
require.NoError(t, set.Set(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee))
}
if tt.args.proposerSettingsFlagValues.defaultgas != "" {
set.String(flags.BuilderGasLimitFlag.Name, tt.args.proposerSettingsFlagValues.defaultgas, "")
require.NoError(t, set.Set(flags.BuilderGasLimitFlag.Name, tt.args.proposerSettingsFlagValues.defaultgas))
}
if tt.validatorRegistrationEnabled {
set.Bool(flags.EnableBuilderFlag.Name, true, "")
}
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)
return
}
if tt.wantLog != "" {
assert.LogsContain(t, hook,
tt.wantLog,
)
}
w := tt.want()
require.DeepEqual(t, w, got)
})
}
}
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)
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

@@ -33,7 +33,7 @@ go_library(
"//config/features:go_default_library", "//config/features:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library", "//consensus-types/validator:go_default_library",
"//crypto/bls:go_default_library", "//crypto/bls:go_default_library",
@@ -112,7 +112,7 @@ go_test(
"//config/features:go_default_library", "//config/features:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//config/validator/service:go_default_library", "//config/proposer:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library", "//consensus-types/validator:go_default_library",
"//crypto/bls:go_default_library", "//crypto/bls:go_default_library",

View File

@@ -15,7 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorServiceConfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
@@ -611,10 +611,10 @@ func (s *Server) SetFeeRecipientByPubkey(w http.ResponseWriter, r *http.Request)
settings := s.validatorService.ProposerSettings() settings := s.validatorService.ProposerSettings()
switch { switch {
case settings == nil: case settings == nil:
settings = &validatorServiceConfig.ProposerSettings{ settings = &proposer.Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption{ ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey): { bytesutil.ToBytes48(pubkey): {
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient, FeeRecipient: feeRecipient,
}, },
BuilderConfig: nil, BuilderConfig: nil,
@@ -623,13 +623,13 @@ func (s *Server) SetFeeRecipientByPubkey(w http.ResponseWriter, r *http.Request)
DefaultConfig: nil, DefaultConfig: nil,
} }
case settings.ProposeConfig == nil: case settings.ProposeConfig == nil:
var builderConfig *validatorServiceConfig.BuilderConfig var builderConfig *proposer.BuilderConfig
if settings.DefaultConfig != nil && settings.DefaultConfig.BuilderConfig != nil { if settings.DefaultConfig != nil && settings.DefaultConfig.BuilderConfig != nil {
builderConfig = settings.DefaultConfig.BuilderConfig.Clone() builderConfig = settings.DefaultConfig.BuilderConfig.Clone()
} }
settings.ProposeConfig = map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption{ settings.ProposeConfig = map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey): { bytesutil.ToBytes48(pubkey): {
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient, FeeRecipient: feeRecipient,
}, },
BuilderConfig: builderConfig, BuilderConfig: builderConfig,
@@ -638,16 +638,16 @@ func (s *Server) SetFeeRecipientByPubkey(w http.ResponseWriter, r *http.Request)
default: default:
proposerOption, found := settings.ProposeConfig[bytesutil.ToBytes48(pubkey)] proposerOption, found := settings.ProposeConfig[bytesutil.ToBytes48(pubkey)]
if found && proposerOption != nil { if found && proposerOption != nil {
proposerOption.FeeRecipientConfig = &validatorServiceConfig.FeeRecipientConfig{ proposerOption.FeeRecipientConfig = &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient, FeeRecipient: feeRecipient,
} }
} else { } else {
var builderConfig = &validatorServiceConfig.BuilderConfig{} var builderConfig = &proposer.BuilderConfig{}
if settings.DefaultConfig != nil && settings.DefaultConfig.BuilderConfig != nil { if settings.DefaultConfig != nil && settings.DefaultConfig.BuilderConfig != nil {
builderConfig = settings.DefaultConfig.BuilderConfig.Clone() builderConfig = settings.DefaultConfig.BuilderConfig.Clone()
} }
settings.ProposeConfig[bytesutil.ToBytes48(pubkey)] = &validatorServiceConfig.ProposerOption{ settings.ProposeConfig[bytesutil.ToBytes48(pubkey)] = &proposer.Option{
FeeRecipientConfig: &validatorServiceConfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: feeRecipient, FeeRecipient: feeRecipient,
}, },
BuilderConfig: builderConfig, BuilderConfig: builderConfig,
@@ -769,7 +769,7 @@ func (s *Server) SetGasLimit(w http.ResponseWriter, r *http.Request) {
httputil.HandleError(w, "Gas limit changes only apply when builder is enabled", http.StatusInternalServerError) httputil.HandleError(w, "Gas limit changes only apply when builder is enabled", http.StatusInternalServerError)
return return
} }
settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption) settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
option := settings.DefaultConfig.Clone() option := settings.DefaultConfig.Clone()
option.BuilderConfig.GasLimit = validator.Uint64(gasLimit) option.BuilderConfig.GasLimit = validator.Uint64(gasLimit)
settings.ProposeConfig[bytesutil.ToBytes48(pubkey)] = option settings.ProposeConfig[bytesutil.ToBytes48(pubkey)] = option

View File

@@ -16,7 +16,7 @@ import (
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v5/config/validator/service" "github.com/prysmaticlabs/prysm/v5/config/proposer"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
@@ -849,20 +849,20 @@ func TestServer_GetGasLimit(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args *validatorserviceconfig.ProposerSettings args *proposer.Settings
pubkey [48]byte pubkey [48]byte
want uint64 want uint64
}{ }{
{ {
name: "ProposerSetting for specific pubkey exists", name: "ProposerSetting for specific pubkey exists",
args: &validatorserviceconfig.ProposerSettings{ args: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(byteval): { bytesutil.ToBytes48(byteval): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: 123456789}, BuilderConfig: &proposer.BuilderConfig{GasLimit: 123456789},
}, },
}, },
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: 987654321}, BuilderConfig: &proposer.BuilderConfig{GasLimit: 987654321},
}, },
}, },
pubkey: bytesutil.ToBytes48(byteval), pubkey: bytesutil.ToBytes48(byteval),
@@ -870,14 +870,14 @@ func TestServer_GetGasLimit(t *testing.T) {
}, },
{ {
name: "ProposerSetting for specific pubkey does not exist", name: "ProposerSetting for specific pubkey does not exist",
args: &validatorserviceconfig.ProposerSettings{ args: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(byteval): { bytesutil.ToBytes48(byteval): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: 123456789}, BuilderConfig: &proposer.BuilderConfig{GasLimit: 123456789},
}, },
}, },
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: 987654321}, BuilderConfig: &proposer.BuilderConfig{GasLimit: 987654321},
}, },
}, },
// no settings for the following validator, so the gaslimit returned is the default value. // no settings for the following validator, so the gaslimit returned is the default value.
@@ -941,7 +941,7 @@ func TestServer_SetGasLimit(t *testing.T) {
name string name string
pubkey []byte pubkey []byte
newGasLimit uint64 newGasLimit uint64
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
w []*want w []*want
beaconReturn *beaconResp beaconReturn *beaconResp
wantErr string wantErr string
@@ -957,7 +957,7 @@ func TestServer_SetGasLimit(t *testing.T) {
name: "ProposerSettings.ProposeConfig is nil AND ProposerSettings.DefaultConfig is nil", name: "ProposerSettings.ProposeConfig is nil AND ProposerSettings.DefaultConfig is nil",
pubkey: pubkey1, pubkey: pubkey1,
newGasLimit: 9999, newGasLimit: 9999,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: nil, ProposeConfig: nil,
DefaultConfig: nil, DefaultConfig: nil,
}, },
@@ -967,9 +967,9 @@ func TestServer_SetGasLimit(t *testing.T) {
name: "ProposerSettings.ProposeConfig is nil AND ProposerSettings.DefaultConfig.BuilderConfig is nil", name: "ProposerSettings.ProposeConfig is nil AND ProposerSettings.DefaultConfig.BuilderConfig is nil",
pubkey: pubkey1, pubkey: pubkey1,
newGasLimit: 9999, newGasLimit: 9999,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: nil, ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
BuilderConfig: nil, BuilderConfig: nil,
}, },
}, },
@@ -979,8 +979,8 @@ func TestServer_SetGasLimit(t *testing.T) {
name: "ProposerSettings.ProposeConfig is defined for pubkey, BuilderConfig is nil AND ProposerSettings.DefaultConfig is nil", name: "ProposerSettings.ProposeConfig is defined for pubkey, BuilderConfig is nil AND ProposerSettings.DefaultConfig is nil",
pubkey: pubkey1, pubkey: pubkey1,
newGasLimit: 9999, newGasLimit: 9999,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey1): { bytesutil.ToBytes48(pubkey1): {
BuilderConfig: nil, BuilderConfig: nil,
}, },
@@ -993,10 +993,10 @@ func TestServer_SetGasLimit(t *testing.T) {
name: "ProposerSettings.ProposeConfig is defined for pubkey, BuilderConfig is defined AND ProposerSettings.DefaultConfig is nil", name: "ProposerSettings.ProposeConfig is defined for pubkey, BuilderConfig is defined AND ProposerSettings.DefaultConfig is nil",
pubkey: pubkey1, pubkey: pubkey1,
newGasLimit: 9999, newGasLimit: 9999,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey1): { bytesutil.ToBytes48(pubkey1): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{}, BuilderConfig: &proposer.BuilderConfig{},
}, },
}, },
DefaultConfig: nil, DefaultConfig: nil,
@@ -1007,10 +1007,10 @@ func TestServer_SetGasLimit(t *testing.T) {
name: "ProposerSettings.ProposeConfig is NOT defined for pubkey, BuilderConfig is defined AND ProposerSettings.DefaultConfig is nil", name: "ProposerSettings.ProposeConfig is NOT defined for pubkey, BuilderConfig is defined AND ProposerSettings.DefaultConfig is nil",
pubkey: pubkey2, pubkey: pubkey2,
newGasLimit: 9999, newGasLimit: 9999,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey2): { bytesutil.ToBytes48(pubkey2): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
GasLimit: 12345, GasLimit: 12345,
}, },
@@ -1028,14 +1028,14 @@ func TestServer_SetGasLimit(t *testing.T) {
name: "ProposerSettings.ProposeConfig is defined for pubkey, BuilderConfig is nil AND ProposerSettings.DefaultConfig.BuilderConfig is defined", name: "ProposerSettings.ProposeConfig is defined for pubkey, BuilderConfig is nil AND ProposerSettings.DefaultConfig.BuilderConfig is defined",
pubkey: pubkey1, pubkey: pubkey1,
newGasLimit: 9999, newGasLimit: 9999,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey2): { bytesutil.ToBytes48(pubkey2): {
BuilderConfig: nil, BuilderConfig: nil,
}, },
}, },
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
BuilderConfig: &validatorserviceconfig.BuilderConfig{ BuilderConfig: &proposer.BuilderConfig{
Enabled: true, Enabled: true,
}, },
}, },
@@ -1149,24 +1149,24 @@ func TestServer_DeleteGasLimit(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
pubkey []byte pubkey []byte
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
wantError error wantError error
w []want w []want
}{ }{
{ {
name: "delete existing gas limit with default config", name: "delete existing gas limit with default config",
pubkey: pubkey1, pubkey: pubkey1,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey1): { bytesutil.ToBytes48(pubkey1): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: validator.Uint64(987654321)}, BuilderConfig: &proposer.BuilderConfig{GasLimit: validator.Uint64(987654321)},
}, },
bytesutil.ToBytes48(pubkey2): { bytesutil.ToBytes48(pubkey2): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: validator.Uint64(123456789)}, BuilderConfig: &proposer.BuilderConfig{GasLimit: validator.Uint64(123456789)},
}, },
}, },
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: validator.Uint64(5555)}, BuilderConfig: &proposer.BuilderConfig{GasLimit: validator.Uint64(5555)},
}, },
}, },
wantError: nil, wantError: nil,
@@ -1185,13 +1185,13 @@ func TestServer_DeleteGasLimit(t *testing.T) {
{ {
name: "delete existing gas limit with no default config", name: "delete existing gas limit with no default config",
pubkey: pubkey1, pubkey: pubkey1,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey1): { bytesutil.ToBytes48(pubkey1): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: validator.Uint64(987654321)}, BuilderConfig: &proposer.BuilderConfig{GasLimit: validator.Uint64(987654321)},
}, },
bytesutil.ToBytes48(pubkey2): { bytesutil.ToBytes48(pubkey2): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: validator.Uint64(123456789)}, BuilderConfig: &proposer.BuilderConfig{GasLimit: validator.Uint64(123456789)},
}, },
}, },
}, },
@@ -1211,10 +1211,10 @@ func TestServer_DeleteGasLimit(t *testing.T) {
{ {
name: "delete nonexist gas limit", name: "delete nonexist gas limit",
pubkey: pubkey2, pubkey: pubkey2,
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(pubkey1): { bytesutil.ToBytes48(pubkey1): {
BuilderConfig: &validatorserviceconfig.BuilderConfig{GasLimit: validator.Uint64(987654321)}, BuilderConfig: &proposer.BuilderConfig{GasLimit: validator.Uint64(987654321)},
}, },
}, },
}, },
@@ -1444,22 +1444,22 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args *validatorserviceconfig.ProposerSettings args *proposer.Settings
want *want want *want
cached *eth.FeeRecipientByPubKeyResponse cached *eth.FeeRecipientByPubKeyResponse
}{ }{
{ {
name: "ProposerSettings.ProposeConfig.FeeRecipientConfig defined for pubkey (and ProposerSettings.DefaultConfig.FeeRecipientConfig defined)", name: "ProposerSettings.ProposeConfig.FeeRecipientConfig defined for pubkey (and ProposerSettings.DefaultConfig.FeeRecipientConfig defined)",
args: &validatorserviceconfig.ProposerSettings{ args: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(byteval): { bytesutil.ToBytes48(byteval): {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
}, },
}, },
}, },
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), FeeRecipient: common.HexToAddress("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
}, },
}, },
@@ -1470,10 +1470,10 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
}, },
{ {
name: "ProposerSettings.ProposeConfig.FeeRecipientConfig NOT defined for pubkey and ProposerSettings.DefaultConfig.FeeRecipientConfig defined", name: "ProposerSettings.ProposeConfig.FeeRecipientConfig NOT defined for pubkey and ProposerSettings.DefaultConfig.FeeRecipientConfig defined",
args: &validatorserviceconfig.ProposerSettings{ args: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{}, ProposeConfig: map[[48]byte]*proposer.Option{},
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
}, },
}, },
@@ -1576,7 +1576,7 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args string args string
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
want *want want *want
wantErr bool wantErr bool
beaconReturn *beaconResp beaconReturn *beaconResp
@@ -1597,7 +1597,7 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
{ {
name: "ProposerSetting.ProposeConfig is nil", name: "ProposerSetting.ProposeConfig is nil",
args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: nil, ProposeConfig: nil,
}, },
want: &want{ want: &want{
@@ -1612,9 +1612,9 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
{ {
name: "ProposerSetting.ProposeConfig is nil AND ProposerSetting.Defaultconfig is defined", name: "ProposerSetting.ProposeConfig is nil AND ProposerSetting.Defaultconfig is defined",
args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: nil, ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{}, DefaultConfig: &proposer.Option{},
}, },
want: &want{ want: &want{
valEthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", valEthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
@@ -1628,8 +1628,8 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
{ {
name: "ProposerSetting.ProposeConfig is defined for pubkey", name: "ProposerSetting.ProposeConfig is defined for pubkey",
args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(byteval): {}, bytesutil.ToBytes48(byteval): {},
}, },
}, },
@@ -1645,8 +1645,8 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
{ {
name: "ProposerSetting.ProposeConfig not defined for pubkey", name: "ProposerSetting.ProposeConfig not defined for pubkey",
args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{}, ProposeConfig: map[[48]byte]*proposer.Option{},
}, },
want: &want{ want: &want{
valEthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", valEthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
@@ -1660,8 +1660,8 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
{ {
name: "ProposerSetting.ProposeConfig is nil for pubkey", name: "ProposerSetting.ProposeConfig is nil for pubkey",
args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(byteval): nil, bytesutil.ToBytes48(byteval): nil,
}, },
}, },
@@ -1677,11 +1677,11 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) {
{ {
name: "ProposerSetting.ProposeConfig is nil for pubkey AND DefaultConfig is not nil", name: "ProposerSetting.ProposeConfig is nil for pubkey AND DefaultConfig is not nil",
args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", args: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(byteval): nil, bytesutil.ToBytes48(byteval): nil,
}, },
DefaultConfig: &validatorserviceconfig.ProposerOption{}, DefaultConfig: &proposer.Option{},
}, },
want: &want{ want: &want{
valEthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9", valEthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
@@ -1777,22 +1777,22 @@ func TestServer_DeleteFeeRecipientByPubkey(t *testing.T) {
} }
tests := []struct { tests := []struct {
name string name string
proposerSettings *validatorserviceconfig.ProposerSettings proposerSettings *proposer.Settings
want *want want *want
wantErr bool wantErr bool
}{ }{
{ {
name: "Happy Path Test", name: "Happy Path Test",
proposerSettings: &validatorserviceconfig.ProposerSettings{ proposerSettings: &proposer.Settings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{ ProposeConfig: map[[48]byte]*proposer.Option{
bytesutil.ToBytes48(byteval): { bytesutil.ToBytes48(byteval): {
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455012BFEBf6177F1D2e9738D5"), FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455012BFEBf6177F1D2e9738D5"),
}, },
}, },
}, },
DefaultConfig: &validatorserviceconfig.ProposerOption{ DefaultConfig: &proposer.Option{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{ FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"), FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
}, },
}, },