diff --git a/beacon-chain/db/iface/interface.go b/beacon-chain/db/iface/interface.go index fcfdeaffb..6e3a6cf8b 100644 --- a/beacon-chain/db/iface/interface.go +++ b/beacon-chain/db/iface/interface.go @@ -53,6 +53,7 @@ type ReadOnlyDatabase interface { PowchainData(ctx context.Context) (*ethpb.ETH1ChainData, error) // Fee reicipients operations. FeeRecipientByValidatorID(ctx context.Context, id types.ValidatorIndex) (common.Address, error) + RegistrationByValidatorID(ctx context.Context, id types.ValidatorIndex) (*ethpb.ValidatorRegistrationV1, error) // origin checkpoint sync support OriginCheckpointBlockRoot(ctx context.Context) ([32]byte, error) BackfillBlockRoot(ctx context.Context) ([32]byte, error) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index ba9d90667..b823e57e6 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition/interop" + "github.com/prysmaticlabs/prysm/beacon-chain/db/kv" "github.com/prysmaticlabs/prysm/config/params" coreBlock "github.com/prysmaticlabs/prysm/consensus-types/blocks" "github.com/prysmaticlabs/prysm/consensus-types/interfaces" @@ -30,15 +31,22 @@ func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockR return nil, err } - builderReady, b, err := vs.getAndBuildHeaderBlock(ctx, altairBlk) - if err != nil { - // In the event of an error, the node should fall back to default execution engine for building block. - log.WithError(err).Error("Failed to build a block from external builder, falling " + - "back to local execution client") - } else if builderReady { - return b, nil + registered, err := vs.validatorRegistered(ctx, altairBlk.ProposerIndex) + if registered && err == nil { + builderReady, b, err := vs.getAndBuildHeaderBlock(ctx, altairBlk) + if err != nil { + // In the event of an error, the node should fall back to default execution engine for building block. + log.WithError(err).Error("Failed to build a block from external builder, falling " + + "back to local execution client") + } else if builderReady { + return b, nil + } + } else if err != nil { + log.WithFields(logrus.Fields{ + "slot": req.Slot, + "validatorIndex": altairBlk.ProposerIndex, + }).Errorf("Could not determine validator has registered. Default to local execution client: %v", err) } - payload, err := vs.getExecutionPayload(ctx, req.Slot, altairBlk.ProposerIndex) if err != nil { return nil, err @@ -289,3 +297,18 @@ func (vs *Server) getAndBuildHeaderBlock(ctx context.Context, b *ethpb.BeaconBlo } return true, gb, nil } + +// validatorRegistered returns true if validator with index `id` was previously registered in the database. +func (vs *Server) validatorRegistered(ctx context.Context, id types.ValidatorIndex) (bool, error) { + if vs.BeaconDB == nil { + return false, errors.New("nil beacon db") + } + _, err := vs.BeaconDB.RegistrationByValidatorID(ctx, id) + switch { + case errors.Is(err, kv.ErrNotFoundFeeRecipient): + return false, nil + case err != nil: + return false, err + } + return true, nil +} 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 5b497db8d..712d44ae5 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go @@ -24,6 +24,7 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/consensus-types/interfaces" + types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/consensus-types/wrapper" "github.com/prysmaticlabs/prysm/encoding/bytesutil" v1 "github.com/prysmaticlabs/prysm/proto/engine/v1" @@ -603,6 +604,8 @@ func TestServer_GetBellatrixBeaconBlock_BuilderCase(t *testing.T) { randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) require.NoError(t, err) + require.NoError(t, proposerServer.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []types.ValidatorIndex{40}, + []*ethpb.ValidatorRegistrationV1{{FeeRecipient: bytesutil.PadTo([]byte{}, fieldparams.FeeRecipientLength), Pubkey: bytesutil.PadTo([]byte{}, fieldparams.BLSPubkeyLength)}})) block, err := proposerServer.getBellatrixBeaconBlock(ctx, ðpb.BlockRequest{ Slot: bellatrixSlot + 1, RandaoReveal: randaoReveal, @@ -613,3 +616,29 @@ func TestServer_GetBellatrixBeaconBlock_BuilderCase(t *testing.T) { require.LogsContain(t, hook, "Computed state root") require.DeepEqual(t, h, bellatrixBlk.BlindedBellatrix.Body.ExecutionPayloadHeader) // Payload header should equal. } + +func TestServer_validatorRegistered(t *testing.T) { + proposerServer := &Server{} + ctx := context.Background() + + reg, err := proposerServer.validatorRegistered(ctx, 0) + require.ErrorContains(t, "nil beacon db", err) + require.Equal(t, false, reg) + + proposerServer.BeaconDB = dbTest.SetupDB(t) + reg, err = proposerServer.validatorRegistered(ctx, 0) + require.NoError(t, err) + require.Equal(t, false, reg) + + f := bytesutil.PadTo([]byte{}, fieldparams.FeeRecipientLength) + p := bytesutil.PadTo([]byte{}, fieldparams.BLSPubkeyLength) + require.NoError(t, proposerServer.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []types.ValidatorIndex{0, 1}, + []*ethpb.ValidatorRegistrationV1{{FeeRecipient: f, Pubkey: p}, {FeeRecipient: f, Pubkey: p}})) + + reg, err = proposerServer.validatorRegistered(ctx, 0) + require.NoError(t, err) + require.Equal(t, true, reg) + reg, err = proposerServer.validatorRegistered(ctx, 1) + require.NoError(t, err) + require.Equal(t, true, reg) +}