diff --git a/beacon-chain/node/config.go b/beacon-chain/node/config.go index bb2aa2de10..19f7d74d70 100644 --- a/beacon-chain/node/config.go +++ b/beacon-chain/node/config.go @@ -73,6 +73,21 @@ func configureBuilderCircuitBreaker(cliCtx *cli.Context) error { return err } } + if cliCtx.IsSet(flags.MinBuilderBid.Name) { + c := params.BeaconConfig().Copy() + c.MinBuilderBid = cliCtx.Uint64(flags.MinBuilderBid.Name) + if err := params.SetActive(c); err != nil { + return err + } + } + if cliCtx.IsSet(flags.MinBuilderDiff.Name) { + c := params.BeaconConfig().Copy() + c.MinBuilderDiff = cliCtx.Uint64(flags.MinBuilderDiff.Name) + if err := params.SetActive(c); err != nil { + return err + } + } + return nil } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index e33bc4f2fa..636858144a 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -96,6 +96,27 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc // Compare payload values between local and builder. Default to the local value if it is higher. localValueGwei := primitives.WeiToGwei(local.Bid) builderValueGwei := primitives.WeiToGwei(bid.Value()) + minBid := primitives.Gwei(params.BeaconConfig().MinBuilderBid) + // Use local block if min bid is not attained + if builderValueGwei < minBid { + log.WithFields(logrus.Fields{ + "minBuilderBid": minBid, + "builderGweiValue": builderValueGwei, + }).Warn("Proposer: using local execution payload because min bid not attained") + return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) + } + + // Use local block if min difference is not attained + minDiff := localValueGwei + primitives.Gwei(params.BeaconConfig().MinBuilderDiff) + if builderValueGwei < minDiff { + log.WithFields(logrus.Fields{ + "localGweiValue": localValueGwei, + "minBidDiff": minDiff, + "builderGweiValue": builderValueGwei, + }).Warn("Proposer: using local execution payload because min difference with local value was not attained") + return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) + } + // Use builder payload if the following in true: // builder_bid_value * builderBoostFactor(default 100) > local_block_value * (local-block-value-boost + 100) boost := primitives.Gwei(params.BeaconConfig().LocalBlockValueBoost) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go index 6e79ada339..7d02c39253 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go @@ -420,7 +420,41 @@ func TestServer_setExecutionData(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(3), e.BlockNumber()) // Local block - require.LogsContain(t, hook, "builderGweiValue=1 localBoostPercentage=0 localGweiValue=2") + require.LogsContain(t, hook, "\"Proposer: using local execution payload because min difference with local value was not attained\" builderGweiValue=1 localGweiValue=2") + }) + t.Run("Builder configured. Builder block does not achieve min bid", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.MinBuilderBid = 5 + params.OverrideBeaconConfig(cfg) + + blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella()) + require.NoError(t, err) + elBid := primitives.Uint64ToWei(2 * 1e9) + ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadCapella{BlockNumber: 3}) + require.NoError(t, err) + vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed, Bid: elBid}} + b := blk.Block() + res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) + require.NoError(t, err) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + require.NoError(t, err) + _, err = builderBid.Header() + require.NoError(t, err) + builderKzgCommitments, err := builderBid.BlobKzgCommitments() + if builderBid.Version() >= version.Deneb { + require.NoError(t, err) + } + require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) + _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) + require.NoError(t, err) + require.IsNil(t, bundle) + e, err := blk.Block().Body().Execution() + require.NoError(t, err) + require.Equal(t, uint64(3), e.BlockNumber()) // Local block + + require.LogsContain(t, hook, "\"Proposer: using local execution payload because min bid not attained\" builderGweiValue=1 minBuilderBid=5") + cfg.MinBuilderBid = 0 + params.OverrideBeaconConfig(cfg) }) t.Run("Builder configured. Local block and local boost has higher value", func(t *testing.T) { cfg := params.BeaconConfig().Copy() diff --git a/cmd/beacon-chain/flags/base.go b/cmd/beacon-chain/flags/base.go index 4e8c948820..731aac2e5c 100644 --- a/cmd/beacon-chain/flags/base.go +++ b/cmd/beacon-chain/flags/base.go @@ -31,6 +31,23 @@ var ( "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)", Value: 10, } + // MinBuilderBid sets an absolute value for the builder bid that this + // node will accept without reverting to local building + MinBuilderBid = &cli.Uint64Flag{ + Name: "min-builder-bid", + Usage: "An absolute value in Gwei that the builder bid has to have in order for this beacon node to use the builder's block. Anything less than this value" + + " and the beacon will revert to local building.", + Value: 0, + } + // MinBuilderDiff sets an absolute value for the difference between the + // builder's bid and the local block value that this node will accept + // without reverting to local building + MinBuilderDiff = &cli.Uint64Flag{ + Name: "min-builder-to-local-difference", + Usage: "An absolute value in Gwei that the builder bid has to have in order for this beacon node to use the builder's block. Anything less than this value" + + " and the beacon will revert to local building.", + Value: 0, + } // ExecutionEngineEndpoint provides an HTTP access endpoint to connect to an execution client on the execution layer ExecutionEngineEndpoint = &cli.StringFlag{ Name: "execution-endpoint", diff --git a/cmd/beacon-chain/main.go b/cmd/beacon-chain/main.go index 19819c8e43..0f3a425476 100644 --- a/cmd/beacon-chain/main.go +++ b/cmd/beacon-chain/main.go @@ -82,6 +82,8 @@ var appFlags = []cli.Flag{ flags.MaxBuilderConsecutiveMissedSlots, flags.EngineEndpointTimeoutSeconds, flags.LocalBlockValueBoost, + flags.MinBuilderBid, + flags.MinBuilderDiff, cmd.BackupWebhookOutputDir, cmd.MinimalConfigFlag, cmd.E2EConfigFlag, diff --git a/cmd/beacon-chain/usage.go b/cmd/beacon-chain/usage.go index 6d0f39cc25..66f7c1013f 100644 --- a/cmd/beacon-chain/usage.go +++ b/cmd/beacon-chain/usage.go @@ -131,6 +131,8 @@ var appHelpFlagGroups = []flagGroup{ flags.EngineEndpointTimeoutSeconds, flags.SlasherDirFlag, flags.LocalBlockValueBoost, + flags.MinBuilderBid, + flags.MinBuilderDiff, flags.JwtId, checkpoint.BlockPath, checkpoint.StatePath, diff --git a/config/params/config.go b/config/params/config.go index 5a33bc1a63..69f7193df1 100644 --- a/config/params/config.go +++ b/config/params/config.go @@ -222,7 +222,8 @@ type BeaconChainConfig struct { MaxBuilderConsecutiveMissedSlots primitives.Slot // MaxBuilderConsecutiveMissedSlots defines the number of consecutive skip slot to fallback from using relay/builder to local execution engine for block construction. MaxBuilderEpochMissedSlots primitives.Slot // MaxBuilderEpochMissedSlots is defining the number of total skip slot (per epoch rolling windows) to fallback from using relay/builder to local execution engine for block construction. LocalBlockValueBoost uint64 // LocalBlockValueBoost is the value boost for local block construction. This is used to prioritize local block construction over relay/builder block construction. - + MinBuilderBid uint64 // MinBuilderBid is the minimum value that the builder's block can have to be considered by this node. + MinBuilderDiff uint64 // MinBuilderDiff is the minimum value above the local block value that the builder has to bid to be considered by this node // Execution engine timeout value ExecutionEngineTimeoutValue uint64 // ExecutionEngineTimeoutValue defines the seconds to wait before timing out engine endpoints with execution payload execution semantics (newPayload, forkchoiceUpdated).