Compare commits

...

39 Commits

Author SHA1 Message Date
james-prysm
719c4aa338 Merge branch 'develop' into builder-boost-settings 2024-04-17 09:47:43 -05:00
james-prysm
fb09cc5419 Merge branch 'develop' into builder-boost-settings 2024-04-01 11:15:20 -05:00
james-prysm
85772bf4e7 small update to use the builder boost if it's below the default of 100 2024-04-01 11:08:55 -05:00
james-prysm
099d3938d9 Merge branch 'develop' into builder-boost-settings 2024-03-29 13:03:58 -05:00
james-prysm
749cb98d77 adding test based on review change 2024-03-29 11:41:22 -05:00
james-prysm
fd7df5545c ignore builder boost if local boost is set 2024-03-29 11:13:23 -05:00
james-prysm
4680af13cf Merge branch 'develop' into builder-boost-settings 2024-03-29 11:00:30 -05:00
james-prysm
041b077b55 Merge branch 'develop' into builder-boost-settings 2024-03-27 23:05:39 -05:00
james-prysm
ee5703df5c Merge branch 'develop' into builder-boost-settings 2024-03-26 11:42:44 -05:00
james-prysm
3086d0eb31 Merge branch 'develop' into builder-boost-settings 2024-03-26 09:18:10 -05:00
james-prysm
c8181ad6d2 Merge branch 'develop' into builder-boost-settings 2024-03-25 13:10:34 -05:00
james-prysm
062518b652 addressing comments 2024-03-25 12:57:25 -05:00
james-prysm
8aa5f7389a Merge branch 'develop' into builder-boost-settings 2024-03-25 09:11:03 -05:00
james-prysm
421f967ba2 Update validator/client/propose.go
Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>
2024-03-25 09:10:56 -05:00
james-prysm
bdb2158035 Update config/proposer/settings.go
Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>
2024-03-25 09:09:31 -05:00
james-prysm
5492018522 Update config/proposer/settings.go
Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>
2024-03-25 09:09:17 -05:00
james-prysm
f8c4a94b09 adding more tests 2024-03-22 15:00:22 -05:00
james-prysm
1bf7b442c3 Merge branch 'develop' into builder-boost-settings 2024-03-22 14:42:56 -05:00
james-prysm
b0be7cafb3 renaming test 2024-03-22 14:42:25 -05:00
james-prysm
bea46206d0 fixing logic and adding tests 2024-03-22 14:41:59 -05:00
james-prysm
2291865e3f Merge branch 'develop' into builder-boost-settings 2024-03-22 09:47:24 -05:00
james-prysm
ae3be20f92 Merge branch 'develop' into builder-boost-settings 2024-03-21 17:20:29 -05:00
james-prysm
75038e4d71 fixing linting, and wip adding a builder boost factor flag 2024-03-21 17:20:02 -05:00
james-prysm
996192fddd Merge branch 'develop' into builder-boost-settings 2024-03-21 16:17:13 -05:00
james-prysm
ad942a8fd3 fixing branch 2024-03-21 16:16:36 -05:00
james-prysm
4e430a5073 fixing some conflicts but wip to fix branch 2024-03-21 15:38:51 -05:00
james-prysm
36ade7b13f Merge branch 'develop' into builder-boost-settings 2024-02-14 14:04:06 -06:00
james-prysm
26ba7aa469 Merge branch 'develop' into builder-boost-settings 2024-01-22 13:32:00 -06:00
james-prysm
8749e543b1 fixing linting 2024-01-22 12:00:57 -06:00
james-prysm
e9b6193fb7 fixing getBeaconBlock rest API 2024-01-22 11:48:42 -06:00
james-prysm
414a4632b0 Merge branch 'develop' into builder-boost-settings 2024-01-22 10:29:59 -06:00
james-prysm
f3eb41db5e Merge branch 'develop' into builder-boost-settings 2024-01-19 13:09:41 -06:00
james-prysm
c880301139 adding another unit test and gaz 2024-01-19 09:52:29 -06:00
james-prysm
91c9bc4834 Merge branch 'develop' into builder-boost-settings 2024-01-19 09:33:46 -06:00
james-prysm
86bc39dee0 adding tests for builder boost 2024-01-19 09:22:11 -06:00
james-prysm
5d50550a27 adding builder boost factor to builder settings 2024-01-18 16:38:16 -06:00
james-prysm
674122391e Merge branch 'develop' into builder-boost-settings 2024-01-18 15:26:14 -06:00
james-prysm
ba73f17a76 proposer settings wip 2024-01-08 13:17:56 -06:00
james-prysm
8ce7287bca wip 2024-01-05 09:16:28 -06:00
21 changed files with 600 additions and 109 deletions

View File

@@ -92,15 +92,16 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc
// Use builder payload if the following in true:
// builder_bid_value * builderBoostFactor(default 100) > local_block_value * (local-block-value-boost + 100)
boost := params.BeaconConfig().LocalBlockValueBoost
higherValueBuilder := builderValueGwei*builderBoostFactor > localValueGwei*(100+boost)
if boost > 0 && builderBoostFactor != defaultBuilderBoostFactor {
if boost > 0 && builderBoostFactor > defaultBuilderBoostFactor {
log.WithFields(logrus.Fields{
"localGweiValue": localValueGwei,
"localBoostPercentage": boost,
"builderGweiValue": builderValueGwei,
"builderBoostFactor": builderBoostFactor,
}).Warn("Proposer: both local boost and builder boost are using non default values")
}).Warn("Proposer: builder boost will be ignored, because local boost is activated and builder boost is above the default")
builderBoostFactor = defaultBuilderBoostFactor
}
higherValueBuilder := builderValueGwei*builderBoostFactor > localValueGwei*(100+boost)
builderValueGweiGauge.Set(float64(builderValueGwei))
localValueGweiGauge.Set(float64(localValueGwei))

View File

@@ -290,7 +290,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
require.Equal(t, uint64(2), e.BlockNumber()) // builder block
})
t.Run("Builder builder has higher value but forced to local payload with builder boost factor", func(t *testing.T) {
t.Run("Builder has higher value but forced to local payload with builder boost factor at 0", func(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella())
require.NoError(t, err)
require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()},
@@ -370,6 +370,23 @@ func TestServer_setExecutionData(t *testing.T) {
require.LogsContain(t, hook, "builderGweiValue=1 localBoostPercentage=0 localGweiValue=2")
})
t.Run("Builder configured. Local block has higher value even with higher builder boost factor", func(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 3}, BlockValue: 2 * 1e9}
b := blk.Block()
localPayload, _, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderPayload, builderKzgCommitments, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
require.NoError(t, err)
require.DeepEqual(t, [][]uint8(nil), builderKzgCommitments)
require.NoError(t, setExecutionData(context.Background(), blk, localPayload, builderPayload, builderKzgCommitments, 99999))
e, err := blk.Block().Body().Execution()
require.NoError(t, err)
require.Equal(t, uint64(3), e.BlockNumber()) // Local block
require.LogsContain(t, hook, "builderGweiValue=1 localBoostPercentage=0 localGweiValue=2")
})
t.Run("Builder configured. Local block and local boost has higher value", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.LocalBlockValueBoost = 1 // Boost 1%.

View File

@@ -27,8 +27,8 @@ var (
// LocalBlockValueBoost sets a percentage boost for local block construction while using a custom builder.
LocalBlockValueBoost = &cli.Uint64Flag{
Name: "local-block-value-boost",
Usage: "A percentage boost for local block construction as a Uint64. This is used to prioritize local block construction over relay/builder block construction" +
"Boost is an additional percentage to multiple local block value. Use builder block if: builder_bid_value * 100 > local_block_value * (local-block-value-boost + 100)",
Usage: "A percentage boost for local block construction as a Uint64. This is used to prioritize local block construction over relay/builder block construction. " +
"Boost is an additional percentage to multiple local block value. Use builder block if: builder_value * builder-boost-factor > local_value * (local-block-value-boost + 100)",
Value: 10,
}
// ExecutionEngineEndpoint provides an HTTP access endpoint to connect to an execution client on the execution layer

View File

@@ -366,6 +366,14 @@ var (
Value: fmt.Sprint(params.BeaconConfig().DefaultBuilderGasLimit),
}
// BuilderBoostFactorFlag sets a multiplier for builder block construction as a Uint64.
BuilderBoostFactorFlag = &cli.Uint64Flag{
Name: "builder-boost-factor",
Usage: "A multiplier for builder block construction as a Uint64. This is used to prioritize relay/builder block construction over local block construction. " +
"Boost factor is a multiplier against the builder value. Use builder block if: builder_value * builder-boost-factor > local_value * (local-block-value-boost + 100)",
Value: 100,
}
// ValidatorsRegistrationBatchSizeFlag sets the maximum size for one batch of validator registrations. Use a non-positive value to disable batching.
ValidatorsRegistrationBatchSizeFlag = &cli.IntFlag{
Name: "validators-registration-batch-size",

View File

@@ -83,6 +83,7 @@ var appFlags = []cli.Flag{
flags.ProposerSettingsFlag,
flags.EnableBuilderFlag,
flags.BuilderGasLimitFlag,
flags.BuilderBoostFactorFlag,
flags.ValidatorsRegistrationBatchSizeFlag,
////////////////////
cmd.DisableMonitoringFlag,

View File

@@ -121,6 +121,7 @@ var appHelpFlagGroups = []flagGroup{
flags.SuggestedFeeRecipientFlag,
flags.EnableBuilderFlag,
flags.BuilderGasLimitFlag,
flags.BuilderBoostFactorFlag,
flags.ValidatorsRegistrationBatchSizeFlag,
flags.EnableDistributed,
},

View File

@@ -35,8 +35,9 @@ type settingsLoader struct {
}
type flagOptions struct {
builderConfig *proposer.BuilderConfig
gasLimit *validator.Uint64
builderConfig *proposer.BuilderConfig
gasLimit *validator.Uint64
builderBoostFactor *uint64
}
// SettingsLoaderOption sets additional options that affect the proposer settings
@@ -74,6 +75,17 @@ func WithGasLimit() SettingsLoaderOption {
}
}
// WithBuilderBoostFactor applies the --builder-boost-factor flag to proposer settings
func WithBuilderBoostFactor() SettingsLoaderOption {
return func(cliCtx *cli.Context, psl *settingsLoader) error {
if cliCtx.IsSet(flags.BuilderBoostFactorFlag.Name) {
bbf := cliCtx.Uint64(flags.BuilderBoostFactorFlag.Name)
psl.options.builderBoostFactor = &bbf
}
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) {
@@ -117,8 +129,11 @@ 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
if psl.options != nil && psl.options.builderConfig != nil {
if psl.options.gasLimit != nil {
psl.options.builderConfig.GasLimit = *psl.options.gasLimit
}
psl.options.builderConfig.BuilderBoostFactor = psl.options.builderBoostFactor
}
// check if database has settings already
@@ -205,20 +220,8 @@ func (psl *settingsLoader) processProposerSettings(loadedSettings, dbSettings *v
// 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 {
if psl.options == nil || psl.options.builderConfig == nil {
dbSettings.DefaultConfig.Builder = nil
}
newSettings.DefaultConfig = dbSettings.DefaultConfig
@@ -229,12 +232,12 @@ func (psl *settingsLoader) processProposerSettings(loadedSettings, dbSettings *v
// process any builder overrides on defaults
if newSettings.DefaultConfig != nil {
newSettings.DefaultConfig.Builder = processBuilderConfig(newSettings.DefaultConfig.Builder, builderConfig, gasLimitOnly)
newSettings.DefaultConfig.Builder = processBuilderConfig(newSettings.DefaultConfig.Builder, psl.options)
}
if dbSettings != nil && len(dbSettings.ProposerConfig) != 0 {
for _, option := range dbSettings.ProposerConfig {
if builderConfig == nil {
if psl.options == nil || psl.options.builderConfig == nil {
option.Builder = nil
}
}
@@ -247,7 +250,7 @@ func (psl *settingsLoader) processProposerSettings(loadedSettings, dbSettings *v
// process any overrides for proposer config
for _, option := range newSettings.ProposerConfig {
if option != nil {
option.Builder = processBuilderConfig(option.Builder, builderConfig, gasLimitOnly)
option.Builder = processBuilderConfig(option.Builder, psl.options)
}
}
@@ -259,18 +262,38 @@ func (psl *settingsLoader) processProposerSettings(loadedSettings, dbSettings *v
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
}
func processBuilderConfig(current *validatorpb.BuilderConfig, options *flagOptions) *validatorpb.BuilderConfig {
// If there are no options, return what was passed in
if options == nil {
return current
}
return override
// Initialize an override variable
var override *validatorpb.BuilderConfig
if options.builderConfig != nil {
// Convert the builder config to consensus form if it exists
override = options.builderConfig.ToConsensus()
}
// If there's nothing to process further, return the override or current based on what's available
if current == nil {
return override
}
if override != nil {
current.Enabled = override.Enabled
}
if options.gasLimit != nil {
current.GasLimit = *options.gasLimit
}
current.GasLimit = reviewGasLimit(current.GasLimit)
if options.builderBoostFactor != nil {
current.BuilderBoostFactor = options.builderBoostFactor
}
return current
}
func reviewGasLimit(gasLimit validator.Uint64) validator.Uint64 {

View File

@@ -26,12 +26,14 @@ import (
)
func TestProposerSettingsLoader(t *testing.T) {
bbf := uint64(100)
hook := logtest.NewGlobal()
type proposerSettingsFlag struct {
dir string
url string
defaultfee string
defaultgas string
dir string
url string
defaultfee string
defaultgas string
builderBoostFactor *uint64
}
type args struct {
@@ -49,6 +51,200 @@ func TestProposerSettingsLoader(t *testing.T) {
validatorRegistrationEnabled bool
skipDBSavedCheck bool
}{
{
name: "builder boost factor set in proposer settings",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-with-builder-boost-config.yaml",
url: "",
defaultfee: "",
},
},
want: func() *proposer.Settings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
tempBBF := uint64(90)
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,
BuilderBoostFactor: &tempBBF,
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
},
withdb: func(db iface.ValidatorDB) error {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
tempBBF := uint64(90)
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: 40000000,
BuilderBoostFactor: &tempBBF,
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
},
},
}
return db.SaveProposerSettings(context.Background(), settings)
},
},
{
name: "builder boost factor flag set with proposer settings file",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
url: "",
defaultfee: "",
builderBoostFactor: &bbf,
},
},
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,
BuilderBoostFactor: &bbf,
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
BuilderBoostFactor: &bbf,
},
},
}
},
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: 40000000,
BuilderBoostFactor: &bbf,
},
},
},
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
BuilderBoostFactor: &bbf,
},
},
}
return db.SaveProposerSettings(context.Background(), settings)
},
},
{
name: "builder boost factor set from flag happy path",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
builderBoostFactor: &bbf,
},
},
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(30000000),
BuilderBoostFactor: &bbf,
},
},
}
},
withdb: func(db iface.ValidatorDB) error {
settings := &proposer.Settings{
ProposeConfig: nil,
DefaultConfig: &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(30000000),
BuilderBoostFactor: &bbf,
},
},
}
return db.SaveProposerSettings(context.Background(), settings)
},
validatorRegistrationEnabled: true,
},
{
name: "builder boost factor set without builder enabled",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "",
builderBoostFactor: &bbf,
},
},
want: func() *proposer.Settings {
return nil
},
wantLog: "No proposer settings were provided",
skipDBSavedCheck: true,
},
{
name: "graffiti in db without fee recipient",
args: args{
@@ -926,6 +1122,10 @@ func TestProposerSettingsLoader(t *testing.T) {
set.String(flags.BuilderGasLimitFlag.Name, tt.args.proposerSettingsFlagValues.defaultgas, "")
require.NoError(t, set.Set(flags.BuilderGasLimitFlag.Name, tt.args.proposerSettingsFlagValues.defaultgas))
}
if tt.args.proposerSettingsFlagValues.builderBoostFactor != nil {
set.Uint64(flags.BuilderBoostFactorFlag.Name, uint64(*tt.args.proposerSettingsFlagValues.builderBoostFactor), "")
require.NoError(t, set.Set(flags.BuilderBoostFactorFlag.Name, fmt.Sprintf("%d", *tt.args.proposerSettingsFlagValues.builderBoostFactor)))
}
if tt.validatorRegistrationEnabled {
set.Bool(flags.EnableBuilderFlag.Name, true, "")
}
@@ -940,6 +1140,7 @@ func TestProposerSettingsLoader(t *testing.T) {
validatorDB,
WithBuilderConfig(),
WithGasLimit(),
WithBuilderBoostFactor(),
)
if tt.wantInitErr != "" {
require.ErrorContains(t, tt.wantInitErr, err)

View File

@@ -0,0 +1,13 @@
---
proposer_config:
'0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a':
fee_recipient: '0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3'
builder:
enabled: true
gas_limit: 40000000
builder_boost_factor: 90
default_config:
fee_recipient: '0x6e35733c5af9B61374A128e6F85f553aF09ff89A'
builder:
enabled: false
gas_limit: '30000000'

View File

@@ -79,9 +79,10 @@ func verifyOption(key string, option *validatorpb.ProposerOptionPayload) error {
// 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.
type BuilderConfig struct {
Enabled bool `json:"enabled" yaml:"enabled"`
GasLimit validator.Uint64 `json:"gas_limit,omitempty" yaml:"gas_limit,omitempty"`
Relays []string `json:"relays,omitempty" yaml:"relays,omitempty"`
Enabled bool `json:"enabled" yaml:"enabled"`
GasLimit validator.Uint64 `json:"gas_limit,omitempty" yaml:"gas_limit,omitempty"`
Relays []string `json:"relays,omitempty" yaml:"relays,omitempty"`
BuilderBoostFactor *uint64 `json:"builder_boost_factor,omitempty" yaml:"builder_boost_factor,omitempty"`
}
// BuilderConfigFromConsensus converts protobuf to a builder config used in in-memory storage
@@ -90,8 +91,9 @@ func BuilderConfigFromConsensus(from *validatorpb.BuilderConfig) *BuilderConfig
return nil
}
c := &BuilderConfig{
Enabled: from.Enabled,
GasLimit: from.GasLimit,
Enabled: from.Enabled,
GasLimit: from.GasLimit,
BuilderBoostFactor: from.BuilderBoostFactor,
}
if from.Relays != nil {
relays := make([]string, len(from.Relays))
@@ -221,16 +223,18 @@ func (bc *BuilderConfig) Clone() *BuilderConfig {
if bc == nil {
return nil
}
c := &BuilderConfig{}
c.Enabled = bc.Enabled
c.GasLimit = bc.GasLimit
var relays []string
if bc.Relays != nil {
relays = make([]string, len(bc.Relays))
copy(relays, bc.Relays)
c.Relays = relays
}
return c
return &BuilderConfig{
Enabled: bc.Enabled,
GasLimit: bc.GasLimit,
BuilderBoostFactor: bc.BuilderBoostFactor,
Relays: relays,
}
}
// Clone creates a deep copy of graffiti config
@@ -246,14 +250,17 @@ func (bc *BuilderConfig) ToConsensus() *validatorpb.BuilderConfig {
if bc == nil {
return nil
}
c := &validatorpb.BuilderConfig{}
c.Enabled = bc.Enabled
var relays []string
if bc.Relays != nil {
relays = make([]string, len(bc.Relays))
copy(relays, bc.Relays)
c.Relays = relays
}
c.GasLimit = bc.GasLimit
return c
return &validatorpb.BuilderConfig{
Enabled: bc.Enabled,
GasLimit: bc.GasLimit,
Relays: relays,
BuilderBoostFactor: bc.BuilderBoostFactor,
}
}

View File

@@ -16,6 +16,7 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
key1hex := "0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a"
key1, err := hexutil.Decode(key1hex)
require.NoError(t, err)
bbf := uint64(100)
settings := &Settings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*Option{
bytesutil.ToBytes48(key1): {
@@ -23,9 +24,10 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
BuilderBoostFactor: &bbf,
},
},
},
@@ -34,9 +36,10 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
BuilderConfig: &BuilderConfig{
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
Relays: []string{"https://example-relay.com"},
Enabled: false,
GasLimit: validator.Uint64(params.BeaconConfig().DefaultBuilderGasLimit),
Relays: []string{"https://example-relay.com"},
BuilderBoostFactor: &bbf,
},
},
}
@@ -57,6 +60,8 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
require.DeepEqual(t, settings.DefaultConfig.BuilderConfig, clone)
settings.DefaultConfig.BuilderConfig.GasLimit = 1
require.NotEqual(t, settings.DefaultConfig.BuilderConfig.GasLimit, clone.GasLimit)
settings.DefaultConfig.BuilderConfig.BuilderBoostFactor = nil
require.NotEqual(t, settings.DefaultConfig.BuilderConfig.BuilderBoostFactor, clone.BuilderBoostFactor)
})
t.Run("Happy Path BuilderConfigFromConsensus", func(t *testing.T) {
@@ -84,6 +89,7 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
require.Equal(t, option.FeeRecipientConfig.FeeRecipient.Hex(), noption.FeeRecipientConfig.FeeRecipient.Hex())
require.Equal(t, option.BuilderConfig.GasLimit, option.BuilderConfig.GasLimit)
require.Equal(t, option.BuilderConfig.Enabled, option.BuilderConfig.Enabled)
require.Equal(t, option.BuilderConfig.BuilderBoostFactor, option.BuilderConfig.BuilderBoostFactor)
})
}
@@ -91,6 +97,7 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
key1hex := "0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a"
key1, err := hexutil.Decode(key1hex)
require.NoError(t, err)
bbf := uint64(100)
type fields struct {
ProposeConfig map[[fieldparams.BLSPubkeyLength]byte]*Option
DefaultConfig *Option
@@ -109,9 +116,10 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
BuilderBoostFactor: &bbf,
},
},
},
@@ -128,9 +136,10 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
BuilderBoostFactor: &bbf,
},
},
},
@@ -145,9 +154,10 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
BuilderBoostFactor: &bbf,
},
},
},
@@ -156,9 +166,10 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
BuilderConfig: &BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
BuilderBoostFactor: &bbf,
},
},
},
@@ -179,9 +190,10 @@ func TestProposerSettings_ShouldBeSaved(t *testing.T) {
ProposeConfig: nil,
DefaultConfig: &Option{
BuilderConfig: &BuilderConfig{
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
Enabled: true,
GasLimit: validator.Uint64(40000000),
Relays: []string{"https://example-relay.com"},
BuilderBoostFactor: &bbf,
},
},
},

View File

@@ -16,7 +16,6 @@ import (
v1alpha1 "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
_ "google.golang.org/protobuf/types/known/wrapperspb"
)
const (
@@ -524,9 +523,10 @@ type BuilderConfig struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
GasLimit github_com_prysmaticlabs_prysm_v5_consensus_types_validator.Uint64 `protobuf:"varint,2,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/validator.Uint64"`
Relays []string `protobuf:"bytes,3,rep,name=relays,proto3" json:"relays,omitempty"`
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
GasLimit github_com_prysmaticlabs_prysm_v5_consensus_types_validator.Uint64 `protobuf:"varint,2,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/validator.Uint64"`
Relays []string `protobuf:"bytes,3,rep,name=relays,proto3" json:"relays,omitempty"`
BuilderBoostFactor *uint64 `protobuf:"varint,4,opt,name=builder_boost_factor,json=builderBoostFactor,proto3,oneof" json:"builder_boost_factor,omitempty"`
}
func (x *BuilderConfig) Reset() {
@@ -582,6 +582,13 @@ func (x *BuilderConfig) GetRelays() []string {
return nil
}
func (x *BuilderConfig) GetBuilderBoostFactor() uint64 {
if x != nil && x.BuilderBoostFactor != nil {
return *x.BuilderBoostFactor
}
return 0
}
type ProposerSettingsPayload struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -645,9 +652,7 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte
0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x6b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67,
0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65,
0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79,
0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x61, 0x74, 0x74, 0x65,
@@ -793,7 +798,7 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte
0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a,
0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48,
0x00, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x88, 0x01, 0x01, 0x42, 0x0b,
0x0a, 0x09, 0x5f, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x22, 0xa6, 0x01, 0x0a, 0x0d,
0x0a, 0x09, 0x5f, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x22, 0xf6, 0x01, 0x0a, 0x0d,
0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a,
0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x63, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c,
@@ -804,7 +809,12 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte
0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x69, 0x6e, 0x74,
0x36, 0x34, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06,
0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65,
0x6c, 0x61, 0x79, 0x73, 0x22, 0xe7, 0x02, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
0x6c, 0x61, 0x79, 0x73, 0x12, 0x35, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x5f,
0x62, 0x6f, 0x6f, 0x73, 0x74, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01,
0x28, 0x04, 0x48, 0x00, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x6f, 0x6f,
0x73, 0x74, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x17, 0x0a, 0x15, 0x5f,
0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x5f, 0x66, 0x61,
0x63, 0x74, 0x6f, 0x72, 0x22, 0xe7, 0x02, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
0x12, 0x74, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x65, 0x74, 0x68, 0x65,
@@ -994,6 +1004,7 @@ func file_proto_prysm_v1alpha1_validator_client_keymanager_proto_init() {
(*SignRequest_BlindedBlockDeneb)(nil),
}
file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[2].OneofWrappers = []interface{}{}
file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[3].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{

View File

@@ -1,7 +1,6 @@
syntax = "proto3";
package ethereum.validator.accounts.v2;
import "google/protobuf/wrappers.proto";
import "proto/eth/ext/options.proto";
import "proto/prysm/v1alpha1/attestation.proto";
import "proto/prysm/v1alpha1/beacon_block.proto";
@@ -96,6 +95,7 @@ message BuilderConfig {
bool enabled = 1;
uint64 gas_limit = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/validator.Uint64"];
repeated string relays = 3;
optional uint64 builder_boost_factor = 4;
}
// ProposerSettingsPayload is used to unmarshal files sent from the validator flag as well as safe to bolt db bucket

View File

@@ -94,6 +94,7 @@ go_library(
"@org_golang_google_grpc//status:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
],
)
@@ -176,6 +177,7 @@ go_test(
"@org_golang_google_grpc//metadata:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
"@org_uber_go_mock//gomock:go_default_library",
],
)

View File

@@ -66,6 +66,7 @@ go_library(
"@com_github_sirupsen_logrus//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
"@org_golang_x_sync//errgroup:go_default_library",
],
)
@@ -139,6 +140,7 @@ go_test(
"@com_github_pkg_errors//:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
"@org_uber_go_mock//gomock:go_default_library",
],
)

View File

@@ -77,7 +77,7 @@ func (c *beaconApiValidatorClient) GetAttestationData(ctx context.Context, in *e
func (c *beaconApiValidatorClient) GetBeaconBlock(ctx context.Context, in *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
return wrapInMetrics[*ethpb.GenericBeaconBlock]("GetBeaconBlock", func() (*ethpb.GenericBeaconBlock, error) {
return c.getBeaconBlock(ctx, in.Slot, in.RandaoReveal, in.Graffiti)
return c.getBeaconBlock(ctx, in.Slot, in.RandaoReveal, in.Graffiti, in.BuilderBoostFactor)
})
}

View File

@@ -15,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/network/httputil"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
"google.golang.org/protobuf/types/known/wrapperspb"
)
type abstractProduceBlockResponseJson struct {
@@ -22,20 +23,26 @@ type abstractProduceBlockResponseJson struct {
Data json.RawMessage `json:"data"`
}
func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primitives.Slot, randaoReveal []byte, graffiti []byte) (*ethpb.GenericBeaconBlock, error) {
func buildGetBeaconBlockUrlValues(randaoReveal []byte, graffiti []byte, builderBoostFactor *wrapperspb.UInt64Value) neturl.Values {
queryParams := neturl.Values{}
if builderBoostFactor != nil {
queryParams.Add("builder_boost_factor", fmt.Sprint(builderBoostFactor.Value))
}
queryParams.Add("randao_reveal", hexutil.Encode(randaoReveal))
if len(graffiti) > 0 {
queryParams.Add("graffiti", hexutil.Encode(graffiti))
}
return queryParams
}
func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primitives.Slot, randaoReveal []byte, graffiti []byte, builderBoostFactor *wrapperspb.UInt64Value) (*ethpb.GenericBeaconBlock, error) {
var ver string
var blinded bool
var decoder *json.Decoder
// Try v3 endpoint first. If it's not supported, then we fall back to older endpoints.
// We try the blinded block endpoint first. If it fails, we assume that we got a full block and try the full block endpoint.
queryUrl := buildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
queryUrl := buildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), buildGetBeaconBlockUrlValues(randaoReveal, graffiti, builderBoostFactor))
produceBlockV3ResponseJson := structs.ProduceBlockV3Response{}
err := c.jsonRestHandler.Get(ctx, queryUrl, &produceBlockV3ResponseJson)
errJson := &httputil.DefaultJsonError{}
@@ -47,14 +54,14 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
return nil, errJson
}
log.Debug("Endpoint /eth/v3/validator/blocks is not supported, falling back to older endpoints for block proposal.")
fallbackResp, err := c.fallBackToBlinded(ctx, slot, queryParams)
fallbackResp, err := c.fallBackToBlinded(ctx, slot, buildGetBeaconBlockUrlValues(randaoReveal, graffiti, nil))
errJson = &httputil.DefaultJsonError{}
if err != nil {
if !errors.As(err, &errJson) {
return nil, err
}
log.Debug("Endpoint /eth/v1/validator/blinded_blocks failed to produce a blinded block, trying /eth/v2/validator/blocks.")
fallbackResp, err = c.fallBackToFull(ctx, slot, queryParams)
fallbackResp, err = c.fallBackToFull(ctx, slot, buildGetBeaconBlockUrlValues(randaoReveal, graffiti, nil))
if err != nil {
return nil, err
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
test_helpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
"go.uber.org/mock/gomock"
"google.golang.org/protobuf/types/known/wrapperspb"
)
func TestGetBeaconBlock_RequestFailed(t *testing.T) {
@@ -36,7 +37,7 @@ func TestGetBeaconBlock_RequestFailed(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2})
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2}, nil)
assert.ErrorContains(t, "foo error", err)
}
@@ -139,7 +140,7 @@ func TestGetBeaconBlock_Error(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2})
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2}, nil)
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
})
}
@@ -175,7 +176,7 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, nil)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -218,7 +219,7 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, nil)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -262,7 +263,7 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, nil)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -307,7 +308,7 @@ func TestGetBeaconBlock_BlindedBellatrixValid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, nil)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -352,7 +353,7 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, nil)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -397,7 +398,7 @@ func TestGetBeaconBlock_BlindedCapellaValid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, nil)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -442,7 +443,7 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, nil)
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -473,7 +474,7 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
ctx,
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
fmt.Sprintf("/eth/v3/validator/blocks/%d?builder_boost_factor=%s&graffiti=%s&randao_reveal=%s", slot, "100", hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&structs.ProduceBlockV3Response{},
).SetArg(
2,
@@ -487,7 +488,7 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, &wrapperspb.UInt64Value{Value: 100})
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -518,7 +519,7 @@ func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) {
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
ctx,
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
fmt.Sprintf("/eth/v3/validator/blocks/%d?builder_boost_factor=%s&graffiti=%s&randao_reveal=%s", slot, "100", hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&structs.ProduceBlockV3Response{},
).Return(
&httputil.DefaultJsonError{Code: http.StatusNotFound},
@@ -538,7 +539,7 @@ func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, &wrapperspb.UInt64Value{Value: 100})
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{
@@ -569,7 +570,7 @@ func TestGetBeaconBlock_FallbackToFullBlock(t *testing.T) {
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
ctx,
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
fmt.Sprintf("/eth/v3/validator/blocks/%d?builder_boost_factor=%s&graffiti=%s&randao_reveal=%s", slot, "100", hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
&structs.ProduceBlockV3Response{},
).Return(
&httputil.DefaultJsonError{Code: http.StatusNotFound},
@@ -596,7 +597,7 @@ func TestGetBeaconBlock_FallbackToFullBlock(t *testing.T) {
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti, &wrapperspb.UInt64Value{Value: 100})
require.NoError(t, err)
expectedBeaconBlock := &ethpb.GenericBeaconBlock{

View File

@@ -28,6 +28,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
"google.golang.org/protobuf/types/known/wrapperspb"
)
const (
@@ -79,9 +80,10 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK
// Request block from beacon node
b, err := v.validatorClient.GetBeaconBlock(ctx, &ethpb.BlockRequest{
Slot: slot,
RandaoReveal: randaoReveal,
Graffiti: g,
Slot: slot,
RandaoReveal: randaoReveal,
Graffiti: g,
BuilderBoostFactor: findBuilderBoost(pubKey, v.proposerSettings),
})
if err != nil {
log.WithField("slot", slot).WithError(err).Error("Failed to request block from beacon node")
@@ -225,6 +227,31 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK
}
}
func findBuilderBoost(pubKey [fieldparams.BLSPubkeyLength]byte, proposerSettings *proposer.Settings) *wrapperspb.UInt64Value {
if proposerSettings == nil {
return nil
}
if proposerSettings.ProposeConfig != nil {
option, ok := proposerSettings.ProposeConfig[pubKey]
if ok && option.BuilderConfig != nil && option.BuilderConfig.BuilderBoostFactor != nil {
return &wrapperspb.UInt64Value{
Value: *option.BuilderConfig.BuilderBoostFactor,
}
}
}
if proposerSettings.DefaultConfig != nil &&
proposerSettings.DefaultConfig.BuilderConfig != nil &&
proposerSettings.DefaultConfig.BuilderConfig.BuilderBoostFactor != nil {
return &wrapperspb.UInt64Value{
Value: *proposerSettings.DefaultConfig.BuilderConfig.BuilderBoostFactor,
}
}
return nil
}
// ProposeExit performs a voluntary exit on a validator.
// The exit is signed by the validator before being sent to the beacon node for broadcasting.
func ProposeExit(

View File

@@ -5,9 +5,11 @@ import (
"encoding/hex"
"errors"
"fmt"
"reflect"
"strings"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru"
@@ -31,6 +33,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/validator/graffiti"
logTest "github.com/sirupsen/logrus/hooks/test"
"go.uber.org/mock/gomock"
"google.golang.org/protobuf/types/known/wrapperspb"
)
type mocks struct {
@@ -1260,3 +1263,156 @@ func Test_validator_SetGraffiti(t *testing.T) {
})
}
}
func Test_findBuilderBoost(t *testing.T) {
pubKey := [fieldparams.BLSPubkeyLength]byte{'a'}
type args struct {
proposerSettings *proposer.Settings
}
tests := []struct {
name string
args args
want *wrapperspb.UInt64Value
}{
{
name: "no proposer settings",
args: args{
proposerSettings: nil,
},
want: nil,
},
{
name: "Proposer settings without builder settings",
args: args{
proposerSettings: &proposer.Settings{
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
config[pubKey] = &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("a"),
},
}
return config
}(),
},
},
want: nil,
},
{
name: "Proposer settings with builder settings but without builder boost factor",
args: args{
proposerSettings: &proposer.Settings{
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
config[pubKey] = &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("a"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
},
}
return config
}(),
},
},
want: nil,
},
{
name: "Proposer settings with builder settings and specific propose config",
args: args{
proposerSettings: &proposer.Settings{
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
bb := uint64(123)
config[pubKey] = &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("a"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
BuilderBoostFactor: &bb,
},
}
return config
}(),
},
},
want: &wrapperspb.UInt64Value{
Value: 123,
},
},
{
name: "Proposer settings with builder settings and specific propose config but wrong pubkey",
args: args{
proposerSettings: &proposer.Settings{
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
bb := uint64(123)
config[[fieldparams.BLSPubkeyLength]byte{'z'}] = &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("a"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
BuilderBoostFactor: &bb,
},
}
return config
}(),
},
},
want: nil,
},
{
name: "Proposer settings with builder settings and default config",
args: args{
proposerSettings: &proposer.Settings{
DefaultConfig: func() *proposer.Option {
bb := uint64(123)
return &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("a"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
BuilderBoostFactor: &bb,
},
}
}(),
},
},
want: &wrapperspb.UInt64Value{
Value: 123,
},
},
{
name: "Proposer settings with nil boost settings",
args: args{
proposerSettings: &proposer.Settings{
DefaultConfig: func() *proposer.Option {
var bb *uint64
return &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("a"),
},
BuilderConfig: &proposer.BuilderConfig{
Enabled: true,
BuilderBoostFactor: bb,
},
}
}(),
},
},
want: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := findBuilderBoost(pubKey, tt.args.proposerSettings); !reflect.DeepEqual(got, tt.want) {
t.Errorf("findBuilderBoost() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -613,6 +613,7 @@ func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*proposer.Sett
db,
loader.WithBuilderConfig(),
loader.WithGasLimit(),
loader.WithBuilderBoostFactor(),
)
if err != nil {
return nil, err