From 5bfb952b6e2269d5413d4baa636cf7524b931225 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Tue, 27 Dec 2022 13:09:44 +0800 Subject: [PATCH 01/30] Revamp proposer rpc --- .../rpc/prysm/v1alpha1/validator/proposer.go | 152 ++++++++++++++++-- 1 file changed, 140 insertions(+), 12 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index c161331a4bdf..2fe7e7a3f105 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -14,8 +14,10 @@ import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/feed" blockfeed "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/feed/block" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv" + fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" @@ -41,26 +43,152 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBeaconBlock") defer span.End() span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot))) - if slots.ToEpoch(req.Slot) < params.BeaconConfig().AltairForkEpoch { - blk, err := vs.getPhase0BeaconBlock(ctx, req) + + // A syncing validator should not produce a block. + if vs.SyncChecker.Syncing() { + return nil, status.Error(codes.Unavailable, "Syncing to latest head, not ready to respond") + } + + // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). + if err := vs.optimisticStatus(ctx); err != nil { + return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) + } + + sBlk, err := getEmptyBlock(req.Slot) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not prepare block: %v", err) + } + + parentRoot, err := vs.HeadFetcher.HeadRoot(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not get head root: %v", err) + } + head, err := vs.HeadFetcher.HeadState(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err) + } + head, err = transition.ProcessSlotsUsingNextSlotCache(ctx, head, parentRoot, req.Slot) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not process slots up to %d: %v", req.Slot, err) + } + + blk := sBlk.Block() + // Set slot, graffiti, randao reveal, and parent root. + blk.SetSlot(req.Slot) + blk.Body().SetGraffiti(req.Graffiti) + blk.Body().SetRandaoReveal(req.RandaoReveal) + blk.SetParentRoot(parentRoot) + + // Set eth1 data. + eth1Data, err := vs.eth1DataMajorityVote(ctx, head) + if err != nil { + log.WithError(err).Error("Could not get eth1data") + } else { + blk.Body().SetEth1Data(eth1Data) + + // Set deposit and attestation. + deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits + if err != nil { + log.WithError(err).Error("Could not pack deposits and attestations") + } else { + blk.Body().SetDeposits(deposits) + blk.Body().SetAttestations(atts) + } + } + + // Set proposer index + idx, err := helpers.BeaconProposerIndex(ctx, head) + if err != nil { + return nil, fmt.Errorf("could not calculate proposer index %v", err) + } + blk.SetProposerIndex(idx) + + // Set slashings + validProposerSlashings, validAttSlashings := vs.getSlashings(ctx, head) + blk.Body().SetProposerSlashings(validProposerSlashings) + blk.Body().SetAttesterSlashings(validAttSlashings) + + // Set exits + blk.Body().SetVoluntaryExits(vs.getExits(head, req.Slot)) + + // Set sync aggregate. New in Altair. + if req.Slot > 0 && slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch { + syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(parentRoot)) if err != nil { - return nil, status.Errorf(codes.Internal, "Could not fetch phase0 beacon block: %v", err) + log.WithError(err).Error("Could not get sync aggregate") + } else { + if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { + log.WithError(err).Error("Could not set sync aggregate") + if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }); err != nil { + return nil, status.Errorf(codes.Internal, "Could not set default sync aggregate: %v", err) + } + } } - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: blk}}, nil - } else if slots.ToEpoch(req.Slot) < params.BeaconConfig().BellatrixForkEpoch { - blk, err := vs.getAltairBeaconBlock(ctx, req) + } + + // Set execution data. New in Bellatrix + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { + fallBackToLocal := true + canUseBuilder, err := vs.canUseBuilder(ctx, req.Slot, idx) if err != nil { - return nil, status.Errorf(codes.Internal, "Could not fetch Altair beacon block: %v", err) + log.WithError(err).Warn("Proposer: failed to check if builder can be used") + } else if canUseBuilder { + h, err := vs.getPayloadHeaderFromBuilder(ctx, req.Slot, idx) + if err != nil { + log.WithError(err).Warn("Proposer: failed to get payload header from builder") + } else { + blk.SetBlinded(true) + if err := blk.Body().SetExecution(h); err != nil { + log.WithError(err).Warn("Proposer: failed to set execution payload") + } else { + fallBackToLocal = false + } + } + } + if fallBackToLocal { + executionData, err := vs.getExecutionPayload(ctx, req.Slot, idx, bytesutil.ToBytes32(parentRoot), head) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not get execution payload: %v", err) + } + if err := blk.Body().SetExecution(executionData); err != nil { + return nil, status.Errorf(codes.Internal, "Could not set execution payload: %v", err) + } } - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: blk}}, nil } - // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). - if err := vs.optimisticStatus(ctx); err != nil { - return nil, err + // Set bls to execution change. New in Capella + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch { + changes, err := vs.BLSChangesPool.BLSToExecChangesForInclusion(head) + if err != nil { + log.WithError(err).Error("Could not get bls to execution changes") + } else { + if err := blk.Body().SetBLSToExecutionChanges(changes); err != nil { + log.WithError(err).Error("Could not set bls to execution changes") + } + } } - return vs.getBellatrixBeaconBlock(ctx, req) + sr, err := vs.computeStateRoot(ctx, sBlk) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err) + } + blk.SetStateRoot(sr) + + pb, err := blk.Proto() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not convert block to proto: %v", err) + } + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch { + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}}, nil + } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}}, nil + } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch { + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: pb.(*ethpb.BeaconBlockAltair)}}, nil + } + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: pb.(*ethpb.BeaconBlock)}}, nil } // ProposeBeaconBlock is called by a proposer during its assigned slot to create a block in an attempt From b557ee18a8d38be811f3c1c97f2a1ee7b783fec1 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 28 Dec 2022 08:54:49 -0800 Subject: [PATCH 02/30] Add canUseBuilder helper method --- .../v1alpha1/validator/proposer_bellatrix.go | 66 +------- .../validator/proposer_bellatrix_test.go | 102 ------------ .../v1alpha1/validator/proposer_builder.go | 93 +++++++++++ .../validator/proposer_builder_test.go | 153 ++++++++++++++++++ 4 files changed, 247 insertions(+), 167 deletions(-) create mode 100644 beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go create mode 100644 beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index f986497fd445..4fb4b4b4ac6d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -12,7 +12,6 @@ import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv" "github.com/prysmaticlabs/prysm/v3/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" @@ -335,54 +334,6 @@ func (vs *Server) readyForBuilder(ctx context.Context) (bool, error) { return blocks.IsExecutionBlock(b.Block().Body()) } -// circuitBreakBuilder returns true if the builder is not allowed to be used due to circuit breaker conditions. -func (vs *Server) circuitBreakBuilder(s types.Slot) (bool, error) { - if vs.ForkFetcher == nil || vs.ForkFetcher.ForkChoicer() == nil { - return true, errors.New("no fork choicer configured") - } - - // Circuit breaker is active if the missing consecutive slots greater than `MaxBuilderConsecutiveMissedSlots`. - highestReceivedSlot := vs.ForkFetcher.ForkChoicer().HighestReceivedBlockSlot() - maxConsecutiveSkipSlotsAllowed := params.BeaconConfig().MaxBuilderConsecutiveMissedSlots - diff, err := s.SafeSubSlot(highestReceivedSlot) - if err != nil { - return true, err - } - if diff > maxConsecutiveSkipSlotsAllowed { - log.WithFields(logrus.Fields{ - "currentSlot": s, - "highestReceivedSlot": highestReceivedSlot, - "maxConsecutiveSkipSlotsAllowed": maxConsecutiveSkipSlotsAllowed, - }).Warn("Builder circuit breaker activated due to missing consecutive slot") - return true, nil - } - - // Not much reason to check missed slots epoch rolling window if input slot is less than epoch. - if s < params.BeaconConfig().SlotsPerEpoch { - return false, nil - } - - // Circuit breaker is active if the missing slots per epoch (rolling window) greater than `MaxBuilderEpochMissedSlots`. - receivedCount, err := vs.ForkFetcher.ForkChoicer().ReceivedBlocksLastEpoch() - if err != nil { - return true, err - } - maxEpochSkipSlotsAllowed := params.BeaconConfig().MaxBuilderEpochMissedSlots - diff, err = params.BeaconConfig().SlotsPerEpoch.SafeSub(receivedCount) - if err != nil { - return true, err - } - if diff > maxEpochSkipSlotsAllowed { - log.WithFields(logrus.Fields{ - "totalMissed": diff, - "maxEpochSkipSlotsAllowed": maxEpochSkipSlotsAllowed, - }).Warn("Builder circuit breaker activated due to missing enough slots last epoch") - return true, nil - } - - return false, nil -} - // GetAndBuildBlindBlock builds blind block from builder network. Returns a boolean status, built block and error. // If the status is false that means builder the header block is disallowed. // This routine is time limited by `blockBuilderTimeout`. @@ -427,26 +378,11 @@ func (vs *Server) GetAndBuildBlindBlock(ctx context.Context, b *ethpb.BeaconBloc 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 -} - // Validates builder signature and returns an error if the signature is invalid. func validateBuilderSignature(bid *ethpb.SignedBuilderBid) error { d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder, nil, /* fork version */ - nil /* genesis val root */) + nil /* genesis val root */) if err != nil { return err } 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 25237e883e14..ef0a9397eb2e 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go @@ -22,8 +22,6 @@ import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" - state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stategen" mockSync "github.com/prysmaticlabs/prysm/v3/beacon-chain/sync/initial-sync/testing" fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" @@ -887,32 +885,6 @@ func TestServer_GetBellatrixBeaconBlock_BuilderCase(t *testing.T) { 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) -} - func TestServer_validateBuilderSignature(t *testing.T) { sk, err := bls.RandKey() require.NoError(t, err) @@ -946,77 +918,3 @@ func TestServer_validateBuilderSignature(t *testing.T) { sBid.Message.Value = make([]byte, 32) require.ErrorIs(t, validateBuilderSignature(sBid), signing.ErrSigFailedToVerify) } - -func TestServer_circuitBreakBuilder(t *testing.T) { - hook := logTest.NewGlobal() - s := &Server{} - _, err := s.circuitBreakBuilder(0) - require.ErrorContains(t, "no fork choicer configured", err) - - s.ForkFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()} - s.ForkFetcher.ForkChoicer().SetGenesisTime(uint64(time.Now().Unix())) - b, err := s.circuitBreakBuilder(params.BeaconConfig().MaxBuilderConsecutiveMissedSlots + 1) - require.NoError(t, err) - require.Equal(t, true, b) - require.LogsContain(t, hook, "Builder circuit breaker activated due to missing consecutive slot") - - ojc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} - ofc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} - ctx := context.Background() - st, blkRoot, err := createState(1, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) - require.NoError(t, err) - require.NoError(t, s.ForkFetcher.ForkChoicer().InsertNode(ctx, st, blkRoot)) - b, err = s.circuitBreakBuilder(params.BeaconConfig().MaxBuilderConsecutiveMissedSlots + 1) - require.NoError(t, err) - require.Equal(t, false, b) - - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig().Copy() - cfg.MaxBuilderEpochMissedSlots = 4 - params.OverrideBeaconConfig(cfg) - st, blkRoot, err = createState(params.BeaconConfig().SlotsPerEpoch, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) - require.NoError(t, err) - require.NoError(t, s.ForkFetcher.ForkChoicer().InsertNode(ctx, st, blkRoot)) - b, err = s.circuitBreakBuilder(params.BeaconConfig().SlotsPerEpoch + 1) - require.NoError(t, err) - require.Equal(t, true, b) - require.LogsContain(t, hook, "Builder circuit breaker activated due to missing enough slots last epoch") - - want := params.BeaconConfig().SlotsPerEpoch - params.BeaconConfig().MaxBuilderEpochMissedSlots - for i := types.Slot(2); i <= want+2; i++ { - st, blkRoot, err = createState(i, [32]byte{byte(i)}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) - require.NoError(t, err) - require.NoError(t, s.ForkFetcher.ForkChoicer().InsertNode(ctx, st, blkRoot)) - } - b, err = s.circuitBreakBuilder(params.BeaconConfig().SlotsPerEpoch + 1) - require.NoError(t, err) - require.Equal(t, false, b) -} - -func createState( - slot types.Slot, - blockRoot [32]byte, - parentRoot [32]byte, - payloadHash [32]byte, - justified *ethpb.Checkpoint, - finalized *ethpb.Checkpoint, -) (state.BeaconState, [32]byte, error) { - - base := ðpb.BeaconStateBellatrix{ - Slot: slot, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - BlockRoots: make([][]byte, 1), - CurrentJustifiedCheckpoint: justified, - FinalizedCheckpoint: finalized, - LatestExecutionPayloadHeader: &v1.ExecutionPayloadHeader{ - BlockHash: payloadHash[:], - }, - LatestBlockHeader: ðpb.BeaconBlockHeader{ - ParentRoot: parentRoot[:], - }, - } - - base.BlockRoots[0] = append(base.BlockRoots[0], blockRoot[:]...) - st, err := state_native.InitializeFromProtoBellatrix(base) - return st, blockRoot, err -} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go new file mode 100644 index 000000000000..a26c7d8a7d7f --- /dev/null +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go @@ -0,0 +1,93 @@ +package validator + +import ( + "context" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv" + "github.com/prysmaticlabs/prysm/v3/config/params" + types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" + "github.com/sirupsen/logrus" +) + +// Returns true if builder (ie outsourcing block construction) can be used. Both conditions have to meet: +// - Validator has registered to use builder (ie called registerBuilder API end point) +// - Circuit breaker has not been activated (ie the liveness of the chain is healthy) +func (vs *Server) canUseBuilder(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (bool, error) { + registered, err := vs.validatorRegistered(ctx, idx) + if err != nil { + return false, err + } + if !registered { + return false, nil + } + activated, err := vs.circuitBreakBuilder(slot) + if err != nil { + return false, err + } + return !activated, 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 +} + +// circuitBreakBuilder returns true if the builder is not allowed to be used due to circuit breaker conditions. +func (vs *Server) circuitBreakBuilder(s types.Slot) (bool, error) { + if vs.ForkFetcher == nil || vs.ForkFetcher.ForkChoicer() == nil { + return true, errors.New("no fork choicer configured") + } + + // Circuit breaker is active if the missing consecutive slots greater than `MaxBuilderConsecutiveMissedSlots`. + highestReceivedSlot := vs.ForkFetcher.ForkChoicer().HighestReceivedBlockSlot() + maxConsecutiveSkipSlotsAllowed := params.BeaconConfig().MaxBuilderConsecutiveMissedSlots + diff, err := s.SafeSubSlot(highestReceivedSlot) + if err != nil { + return true, err + } + + if diff > maxConsecutiveSkipSlotsAllowed { + log.WithFields(logrus.Fields{ + "currentSlot": s, + "highestReceivedSlot": highestReceivedSlot, + "maxConsecutiveSkipSlotsAllowed": maxConsecutiveSkipSlotsAllowed, + }).Warn("Builder circuit breaker activated due to missing consecutive slot") + return true, nil + } + + // Not much reason to check missed slots epoch rolling window if input slot is less than epoch. + if s < params.BeaconConfig().SlotsPerEpoch { + return false, nil + } + + // Circuit breaker is active if the missing slots per epoch (rolling window) greater than `MaxBuilderEpochMissedSlots`. + receivedCount, err := vs.ForkFetcher.ForkChoicer().ReceivedBlocksLastEpoch() + if err != nil { + return true, err + } + maxEpochSkipSlotsAllowed := params.BeaconConfig().MaxBuilderEpochMissedSlots + diff, err = params.BeaconConfig().SlotsPerEpoch.SafeSub(receivedCount) + if err != nil { + return true, err + } + if diff > maxEpochSkipSlotsAllowed { + log.WithFields(logrus.Fields{ + "totalMissed": diff, + "maxEpochSkipSlotsAllowed": maxEpochSkipSlotsAllowed, + }).Warn("Builder circuit breaker activated due to missing enough slots last epoch") + return true, nil + } + + return false, nil +} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go new file mode 100644 index 000000000000..2a37487a6d34 --- /dev/null +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go @@ -0,0 +1,153 @@ +package validator + +import ( + "context" + "testing" + "time" + + blockchainTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing" + dbTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/testing" + doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" + state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" + fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" + "github.com/prysmaticlabs/prysm/v3/config/params" + types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" + v1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/testing/require" + logTest "github.com/sirupsen/logrus/hooks/test" +) + +func TestServer_circuitBreakBuilder(t *testing.T) { + hook := logTest.NewGlobal() + s := &Server{} + _, err := s.circuitBreakBuilder(0) + require.ErrorContains(t, "no fork choicer configured", err) + + s.ForkFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()} + s.ForkFetcher.ForkChoicer().SetGenesisTime(uint64(time.Now().Unix())) + b, err := s.circuitBreakBuilder(params.BeaconConfig().MaxBuilderConsecutiveMissedSlots + 1) + require.NoError( + t, + err, + ) + require.Equal(t, true, b) + require.LogsContain(t, hook, "Builder circuit breaker activated due to missing consecutive slot") + + ojc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} + ofc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} + ctx := context.Background() + st, blkRoot, err := createState(1, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, err) + require.NoError(t, s.ForkFetcher.ForkChoicer().InsertNode(ctx, st, blkRoot)) + b, err = s.circuitBreakBuilder(params.BeaconConfig().MaxBuilderConsecutiveMissedSlots + 1) + require.NoError(t, err) + require.Equal(t, false, b) + + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.MaxBuilderEpochMissedSlots = 4 + params.OverrideBeaconConfig(cfg) + st, blkRoot, err = createState(params.BeaconConfig().SlotsPerEpoch, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, err) + require.NoError(t, s.ForkFetcher.ForkChoicer().InsertNode(ctx, st, blkRoot)) + b, err = s.circuitBreakBuilder(params.BeaconConfig().SlotsPerEpoch + 1) + require.NoError(t, err) + require.Equal(t, true, b) + require.LogsContain(t, hook, "Builder circuit breaker activated due to missing enough slots last epoch") + + want := params.BeaconConfig().SlotsPerEpoch - params.BeaconConfig().MaxBuilderEpochMissedSlots + for i := types.Slot(2); i <= want+2; i++ { + st, blkRoot, err = createState(i, [32]byte{byte(i)}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, err) + require.NoError(t, s.ForkFetcher.ForkChoicer().InsertNode(ctx, st, blkRoot)) + } + b, err = s.circuitBreakBuilder(params.BeaconConfig().SlotsPerEpoch + 1) + require.NoError(t, err) + require.Equal(t, false, b) +} + +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) +} + +func TestServer_canUseBuilder(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.canUseBuilder(ctx, 1, 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}, + []*ethpb.ValidatorRegistrationV1{{FeeRecipient: f, Pubkey: p}})) + + proposerServer.ForkFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()} + proposerServer.ForkFetcher.ForkChoicer().SetGenesisTime(uint64(time.Now().Unix())) + reg, err = proposerServer.canUseBuilder(ctx, params.BeaconConfig().MaxBuilderConsecutiveMissedSlots+1, 0) + require.NoError(t, err) + require.Equal(t, false, reg) + + reg, err = proposerServer.canUseBuilder(ctx, params.BeaconConfig().MaxBuilderConsecutiveMissedSlots, 0) + require.NoError(t, err) + require.Equal(t, true, reg) +} + +func createState( + slot types.Slot, + blockRoot [32]byte, + parentRoot [32]byte, + payloadHash [32]byte, + justified *ethpb.Checkpoint, + finalized *ethpb.Checkpoint, +) (state.BeaconState, [32]byte, error) { + + base := ðpb.BeaconStateBellatrix{ + Slot: slot, + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + BlockRoots: make([][]byte, 1), + CurrentJustifiedCheckpoint: justified, + FinalizedCheckpoint: finalized, + LatestExecutionPayloadHeader: &v1.ExecutionPayloadHeader{ + BlockHash: payloadHash[:], + }, + LatestBlockHeader: ðpb.BeaconBlockHeader{ + ParentRoot: parentRoot[:], + }, + } + + base.BlockRoots[0] = append(base.BlockRoots[0], blockRoot[:]...) + st, err := state_native.InitializeFromProtoBellatrix(base) + return st, blockRoot, err +} From ab8b0d3b11f0282e61e5bc466c49215c19f70902 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 28 Dec 2022 09:38:23 -0800 Subject: [PATCH 03/30] Can build. Need to fix minimal setting --- beacon-chain/rpc/eth/validator/validator.go | 9 +- .../rpc/prysm/v1alpha1/validator/BUILD.bazel | 84 ++- .../v1alpha1/validator/proposer_bellatrix.go | 174 +----- .../validator/proposer_bellatrix_test.go | 582 ------------------ .../validator/proposer_execution_payload.go | 40 +- .../v1alpha1/validator/proposer_phase0.go | 170 ----- .../rpc/prysm/v1alpha1/validator/server.go | 2 + 7 files changed, 98 insertions(+), 963 deletions(-) delete mode 100644 beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go diff --git a/beacon-chain/rpc/eth/validator/validator.go b/beacon-chain/rpc/eth/validator/validator.go index 0787f25ebea2..7bedfc20b450 100644 --- a/beacon-chain/rpc/eth/validator/validator.go +++ b/beacon-chain/rpc/eth/validator/validator.go @@ -500,15 +500,8 @@ func (vs *Server) ProduceBlindedBlock(ctx context.Context, req *ethpbv1.ProduceB if optimistic { return nil, status.Errorf(codes.Unavailable, "The node is currently optimistic and cannot serve validators") } - altairBlk, err := vs.V1Alpha1Server.BuildAltairBeaconBlock(ctx, v1alpha1req) + b, err := vs.V1Alpha1Server.GetBeaconBlock(ctx, v1alpha1req) if err != nil { - return nil, status.Errorf(codes.Internal, "Could not prepare beacon block: %v", err) - } - ok, b, err := vs.V1Alpha1Server.GetAndBuildBlindBlock(ctx, altairBlk) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not prepare blind beacon block: %v", err) - } - if !ok { return nil, status.Error(codes.Unavailable, "Builder is not available due to miss-config or circuit breaker") } blk, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(b.GetBlindedBellatrix()) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 2bd95ff63bca..b3a8b62aa9b4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -13,10 +13,13 @@ go_library( "proposer_altair.go", "proposer_attestations.go", "proposer_bellatrix.go", + "proposer_builder.go", "proposer_deposits.go", + "proposer_empty_block.go", "proposer_eth1data.go", "proposer_execution_payload.go", - "proposer_phase0.go", + "proposer_exists.go", + "proposer_slashings.go", "proposer_sync_aggregate.go", "server.go", "status.go", @@ -46,6 +49,7 @@ go_library( "//beacon-chain/db/kv:go_default_library", "//beacon-chain/execution:go_default_library", "//beacon-chain/operations/attestations:go_default_library", + "//beacon-chain/operations/blstoexec:go_default_library", "//beacon-chain/operations/slashings:go_default_library", "//beacon-chain/operations/synccommittee:go_default_library", "//beacon-chain/operations/voluntaryexits:go_default_library", @@ -58,8 +62,8 @@ go_library( "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", - "//consensus-types/primitives:go_default_library", "//consensus-types/payload-attribute:go_default_library", + "//consensus-types/primitives:go_default_library", "//container/trie:go_default_library", "//contracts/deposit:go_default_library", "//crypto/bls:go_default_library", @@ -160,23 +164,30 @@ common_deps = [ "@org_golang_google_protobuf//types/known/emptypb:go_default_library", ] -# gazelle:ignore go_test( name = "go_default_test", timeout = "moderate", srcs = [ "aggregator_test.go", "assignments_test.go", + "attester_mainnet_test.go", "attester_test.go", "blocks_test.go", "exit_test.go", "proposer_attestations_test.go", "proposer_bellatrix_test.go", + "proposer_builder_test.go", "proposer_deposits_test.go", + "proposer_empty_block_test.go", "proposer_execution_payload_test.go", + "proposer_exists_test.go", + "proposer_slashings_test.go", "proposer_sync_aggregate_test.go", "proposer_test.go", + "proposer_utils_bench_test.go", + "server_mainnet_test.go", "server_test.go", + "status_mainnet_test.go", "status_test.go", "sync_committee_test.go", "validator_test.go", @@ -184,7 +195,72 @@ go_test( embed = [":go_default_library"], eth_network = "minimal", tags = ["minimal"], - deps = common_deps, + deps = [ + "//async/event:go_default_library", + "//beacon-chain/blockchain/testing:go_default_library", + "//beacon-chain/builder:go_default_library", + "//beacon-chain/builder/testing:go_default_library", + "//beacon-chain/cache:go_default_library", + "//beacon-chain/cache/depositcache:go_default_library", + "//beacon-chain/core/altair:go_default_library", + "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/execution:go_default_library", + "//beacon-chain/core/feed:go_default_library", + "//beacon-chain/core/feed/block:go_default_library", + "//beacon-chain/core/feed/operation:go_default_library", + "//beacon-chain/core/feed/state:go_default_library", + "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/core/signing:go_default_library", + "//beacon-chain/core/time:go_default_library", + "//beacon-chain/core/transition:go_default_library", + "//beacon-chain/db/testing:go_default_library", + "//beacon-chain/execution/testing:go_default_library", + "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", + "//beacon-chain/operations/attestations:go_default_library", + "//beacon-chain/operations/slashings:go_default_library", + "//beacon-chain/operations/synccommittee:go_default_library", + "//beacon-chain/operations/voluntaryexits:go_default_library", + "//beacon-chain/p2p/testing:go_default_library", + "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native:go_default_library", + "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state/stategen/mock:go_default_library", + "//beacon-chain/sync/initial-sync/testing:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//consensus-types/primitives:go_default_library", + "//container/trie:go_default_library", + "//crypto/bls:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/engine/v1:go_default_library", + "//proto/eth/v1:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/attestation:go_default_library", + "//proto/prysm/v1alpha1/attestation/aggregation/attestations:go_default_library", + "//proto/prysm/v1alpha1/attestation/aggregation/testing:go_default_library", + "//testing/assert:go_default_library", + "//testing/mock:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "//time:go_default_library", + "//time/slots:go_default_library", + "@com_github_d4l3k_messagediff//: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//core/types:go_default_library", + "@com_github_golang_mock//gomock:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", + "@org_golang_google_grpc//codes:go_default_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", + ], ) go_test( diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index 4fb4b4b4ac6d..dfc043f574c4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -11,7 +11,6 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop" "github.com/prysmaticlabs/prysm/v3/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" @@ -35,73 +34,9 @@ var builderGetPayloadMissCount = promauto.NewCounter(prometheus.CounterOpts{ // block request. This value is known as `BUILDER_PROPOSAL_DELAY_TOLERANCE` in builder spec. const blockBuilderTimeout = 1 * time.Second -func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) { - altairBlk, err := vs.BuildAltairBeaconBlock(ctx, req) - if err != nil { - return nil, err - } - - if !req.SkipMevBoost { - registered, err := vs.validatorRegistered(ctx, altairBlk.ProposerIndex) - if registered && err == nil { - builderReady, b, err := vs.GetAndBuildBlindBlock(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") - builderGetPayloadMissCount.Inc() - } else if builderReady { - return b, nil - } - } else if err != nil { - log.WithError(err).WithFields(logrus.Fields{ - "slot": req.Slot, - "validatorIndex": altairBlk.ProposerIndex, - }).Error("Could not determine validator has registered. Defaulting to local execution client") - } - } - payload, err := vs.getExecutionPayload(ctx, req.Slot, altairBlk.ProposerIndex, bytesutil.ToBytes32(altairBlk.ParentRoot)) - if err != nil { - return nil, err - } - - blk := ðpb.BeaconBlockBellatrix{ - Slot: altairBlk.Slot, - ProposerIndex: altairBlk.ProposerIndex, - ParentRoot: altairBlk.ParentRoot, - StateRoot: params.BeaconConfig().ZeroHash[:], - Body: ðpb.BeaconBlockBodyBellatrix{ - RandaoReveal: altairBlk.Body.RandaoReveal, - Eth1Data: altairBlk.Body.Eth1Data, - Graffiti: altairBlk.Body.Graffiti, - ProposerSlashings: altairBlk.Body.ProposerSlashings, - AttesterSlashings: altairBlk.Body.AttesterSlashings, - Attestations: altairBlk.Body.Attestations, - Deposits: altairBlk.Body.Deposits, - VoluntaryExits: altairBlk.Body.VoluntaryExits, - SyncAggregate: altairBlk.Body.SyncAggregate, - ExecutionPayload: payload, - }, - } - // Compute state root with the newly constructed block. - wsb, err := consensusblocks.NewSignedBeaconBlock( - ðpb.SignedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)}, - ) - if err != nil { - return nil, err - } - stateRoot, err := vs.computeStateRoot(ctx, wsb) - if err != nil { - interop.WriteBlockToDisk(wsb, true /*failed*/) - return nil, fmt.Errorf("could not compute state root: %v", err) - } - blk.StateRoot = stateRoot - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: blk}}, nil -} - // This function retrieves the payload header given the slot number and the validator index. // It's a no-op if the latest head block is not versioned bellatrix. -func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (*enginev1.ExecutionPayloadHeader, error) { +func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (interfaces.ExecutionData, error) { b, err := vs.HeadFetcher.HeadBlock(ctx) if err != nil { return nil, err @@ -161,48 +96,7 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Sl "builderPubKey": fmt.Sprintf("%#x", bid.Message.Pubkey), "blockHash": fmt.Sprintf("%#x", bid.Message.Header.BlockHash), }).Info("Received header with bid") - return bid.Message.Header, nil -} - -// This function constructs the builder block given the input altair block and the header. It returns a generic beacon block for signing -func (vs *Server) buildBlindBlock(ctx context.Context, b *ethpb.BeaconBlockAltair, h *enginev1.ExecutionPayloadHeader) (*ethpb.GenericBeaconBlock, error) { - if b == nil || b.Body == nil { - return nil, errors.New("nil block") - } - if h == nil { - return nil, errors.New("nil header") - } - - blk := ðpb.BlindedBeaconBlockBellatrix{ - Slot: b.Slot, - ProposerIndex: b.ProposerIndex, - ParentRoot: b.ParentRoot, - StateRoot: params.BeaconConfig().ZeroHash[:], - Body: ðpb.BlindedBeaconBlockBodyBellatrix{ - RandaoReveal: b.Body.RandaoReveal, - Eth1Data: b.Body.Eth1Data, - Graffiti: b.Body.Graffiti, - ProposerSlashings: b.Body.ProposerSlashings, - AttesterSlashings: b.Body.AttesterSlashings, - Attestations: b.Body.Attestations, - Deposits: b.Body.Deposits, - VoluntaryExits: b.Body.VoluntaryExits, - SyncAggregate: b.Body.SyncAggregate, - ExecutionPayloadHeader: h, - }, - } - wsb, err := consensusblocks.NewSignedBeaconBlock( - ðpb.SignedBlindedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)}, - ) - if err != nil { - return nil, err - } - stateRoot, err := vs.computeStateRoot(ctx, wsb) - if err != nil { - return nil, errors.Wrap(err, "could not compute state root") - } - blk.StateRoot = stateRoot - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: blk}}, nil + return consensusblocks.WrappedExecutionPayloadHeader(bid.Message.Header) } // This function retrieves the full payload block using the input blind block. This input must be versioned as @@ -316,73 +210,11 @@ func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.SignedBe return wb, nil } -// readyForBuilder returns true if builder is allowed to be used. Builder is only allowed to be use after the -// first finalized checkpt has been execution-enabled. -func (vs *Server) readyForBuilder(ctx context.Context) (bool, error) { - cp := vs.FinalizationFetcher.FinalizedCheckpt() - // Checkpoint root is zero means we are still at genesis epoch. - if bytesutil.ToBytes32(cp.Root) == params.BeaconConfig().ZeroHash { - return false, nil - } - b, err := vs.BeaconDB.Block(ctx, bytesutil.ToBytes32(cp.Root)) - if err != nil { - return false, err - } - if err = consensusblocks.BeaconBlockIsNil(b); err != nil { - return false, err - } - return blocks.IsExecutionBlock(b.Block().Body()) -} - -// GetAndBuildBlindBlock builds blind block from builder network. Returns a boolean status, built block and error. -// If the status is false that means builder the header block is disallowed. -// This routine is time limited by `blockBuilderTimeout`. -func (vs *Server) GetAndBuildBlindBlock(ctx context.Context, b *ethpb.BeaconBlockAltair) (bool, *ethpb.GenericBeaconBlock, error) { - // No op. Builder is not defined. User did not specify a user URL. We should use local EE. - if vs.BlockBuilder == nil || !vs.BlockBuilder.Configured() { - return false, nil, nil - } - ctx, cancel := context.WithTimeout(ctx, blockBuilderTimeout) - defer cancel() - // Does the protocol allow for builder at this current moment. Builder is only allowed post merge after finalization. - ready, err := vs.readyForBuilder(ctx) - if err != nil { - return false, nil, errors.Wrap(err, "could not determine if builder is ready") - } - if !ready { - return false, nil, nil - } - - circuitBreak, err := vs.circuitBreakBuilder(b.Slot) - if err != nil { - return false, nil, errors.Wrap(err, "could not determine if builder circuit breaker condition") - } - if circuitBreak { - return false, nil, nil - } - - h, err := vs.getPayloadHeaderFromBuilder(ctx, b.Slot, b.ProposerIndex) - if err != nil { - return false, nil, errors.Wrap(err, "could not get payload header") - } - log.WithFields(logrus.Fields{ - "blockHash": fmt.Sprintf("%#x", h.BlockHash), - "feeRecipient": fmt.Sprintf("%#x", h.FeeRecipient), - "gasUsed": h.GasUsed, - "slot": b.Slot, - }).Info("Retrieved header from builder") - gb, err := vs.buildBlindBlock(ctx, b, h) - if err != nil { - return false, nil, errors.Wrap(err, "could not combine altair block with payload header") - } - return true, gb, nil -} - // Validates builder signature and returns an error if the signature is invalid. func validateBuilderSignature(bid *ethpb.SignedBuilderBid) error { d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder, nil, /* fork version */ - nil /* genesis val root */) + nil /* genesis val root */) if err != nil { return err } 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 ef0a9397eb2e..264c8a59baa0 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go @@ -5,30 +5,14 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" blockchainTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing" builderTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder/testing" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/cache" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/altair" - consensusblocks "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing" - prysmtime "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time" - dbTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/testing" - mockExecution "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing" - doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stategen" - mockSync "github.com/prysmaticlabs/prysm/v3/beacon-chain/sync/initial-sync/testing" fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" - types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v3/crypto/bls" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v3/encoding/ssz" @@ -37,59 +21,8 @@ import ( "github.com/prysmaticlabs/prysm/v3/testing/require" "github.com/prysmaticlabs/prysm/v3/testing/util" "github.com/prysmaticlabs/prysm/v3/time/slots" - logTest "github.com/sirupsen/logrus/hooks/test" ) -func TestServer_buildHeaderBlock(t *testing.T) { - db := dbTest.SetupDB(t) - ctx := context.Background() - - beaconState, keys := util.DeterministicGenesisStateAltair(t, 16384) - sCom, err := altair.NextSyncCommittee(context.Background(), beaconState) - require.NoError(t, err) - require.NoError(t, beaconState.SetCurrentSyncCommittee(sCom)) - copiedState := beaconState.Copy() - - proposerServer := &Server{ - BeaconDB: db, - StateGen: stategen.New(db, doublylinkedtree.New()), - } - b, err := util.GenerateFullBlockAltair(copiedState, keys, util.DefaultBlockGenConfig(), 1) - require.NoError(t, err) - r := bytesutil.ToBytes32(b.Block.ParentRoot) - util.SaveBlock(t, ctx, proposerServer.BeaconDB, b) - require.NoError(t, proposerServer.BeaconDB.SaveState(ctx, beaconState, r)) - - b1, err := util.GenerateFullBlockAltair(copiedState, keys, util.DefaultBlockGenConfig(), 2) - require.NoError(t, err) - - vs := &Server{StateGen: stategen.New(db, doublylinkedtree.New()), BeaconDB: db} - h := &v1.ExecutionPayloadHeader{ - BlockNumber: 123, - GasLimit: 456, - GasUsed: 789, - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - } - got, err := vs.buildBlindBlock(ctx, b1.Block, h) - require.NoError(t, err) - require.DeepEqual(t, h, got.GetBlindedBellatrix().Body.ExecutionPayloadHeader) - - _, err = vs.buildBlindBlock(ctx, nil, h) - require.ErrorContains(t, "nil block", err) - - _, err = vs.buildBlindBlock(ctx, b1.Block, nil) - require.ErrorContains(t, "nil header", err) -} - func TestServer_getPayloadHeader(t *testing.T) { emptyRoot, err := ssz.TransactionsRoot([][]byte{}) require.NoError(t, err) @@ -370,521 +303,6 @@ func TestServer_getBuilderBlock(t *testing.T) { } } -func TestServer_readyForBuilder(t *testing.T) { - ctx := context.Background() - vs := &Server{BeaconDB: dbTest.SetupDB(t)} - cs := &blockchainTest.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{}} // Checkpoint root is zeros. - vs.FinalizationFetcher = cs - ready, err := vs.readyForBuilder(ctx) - require.NoError(t, err) - require.Equal(t, false, ready) - - b := util.NewBeaconBlockBellatrix() - wb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - wbr, err := wb.Block().HashTreeRoot() - require.NoError(t, err) - - b1 := util.NewBeaconBlockBellatrix() - b1.Block.Body.ExecutionPayload.BlockNumber = 1 // Execution enabled. - wb1, err := blocks.NewSignedBeaconBlock(b1) - require.NoError(t, err) - wbr1, err := wb1.Block().HashTreeRoot() - require.NoError(t, err) - require.NoError(t, vs.BeaconDB.SaveBlock(ctx, wb)) - require.NoError(t, vs.BeaconDB.SaveBlock(ctx, wb1)) - - // Ready is false given finalized block does not have execution. - cs = &blockchainTest.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{Root: wbr[:]}} - vs.FinalizationFetcher = cs - ready, err = vs.readyForBuilder(ctx) - require.NoError(t, err) - require.Equal(t, false, ready) - - // Ready is true given finalized block has execution. - cs = &blockchainTest.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{Root: wbr1[:]}} - vs.FinalizationFetcher = cs - ready, err = vs.readyForBuilder(ctx) - require.NoError(t, err) - require.Equal(t, true, ready) -} - -func TestServer_getAndBuildHeaderBlock(t *testing.T) { - ctx := context.Background() - vs := &Server{} - - // Nil builder - ready, _, err := vs.GetAndBuildBlindBlock(ctx, nil) - require.NoError(t, err) - require.Equal(t, false, ready) - - // Not configured - vs.BlockBuilder = &builderTest.MockBuilderService{} - ready, _, err = vs.GetAndBuildBlindBlock(ctx, nil) - require.NoError(t, err) - require.Equal(t, false, ready) - - // Block is not ready - vs.BlockBuilder = &builderTest.MockBuilderService{HasConfigured: true} - vs.FinalizationFetcher = &blockchainTest.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{}} - ready, _, err = vs.GetAndBuildBlindBlock(ctx, nil) - require.NoError(t, err) - require.Equal(t, false, ready) - - // Failed to get header - b1 := util.NewBeaconBlockBellatrix() - b1.Block.Body.ExecutionPayload.BlockNumber = 1 // Execution enabled. - wb1, err := blocks.NewSignedBeaconBlock(b1) - require.NoError(t, err) - wbr1, err := wb1.Block().HashTreeRoot() - require.NoError(t, err) - vs.BeaconDB = dbTest.SetupDB(t) - require.NoError(t, vs.BeaconDB.SaveBlock(ctx, wb1)) - vs.FinalizationFetcher = &blockchainTest.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{Root: wbr1[:]}} - vs.HeadFetcher = &blockchainTest.ChainService{Block: wb1} - vs.BlockBuilder = &builderTest.MockBuilderService{HasConfigured: true, ErrGetHeader: errors.New("could not get payload")} - vs.ForkFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()} - ready, _, err = vs.GetAndBuildBlindBlock(ctx, ðpb.BeaconBlockAltair{}) - require.ErrorContains(t, "could not get payload", err) - require.Equal(t, false, ready) - - // Block built and validated! - beaconState, keys := util.DeterministicGenesisStateAltair(t, 16384) - sCom, err := altair.NextSyncCommittee(context.Background(), beaconState) - require.NoError(t, err) - require.NoError(t, beaconState.SetCurrentSyncCommittee(sCom)) - copiedState := beaconState.Copy() - - b, err := util.GenerateFullBlockAltair(copiedState, keys, util.DefaultBlockGenConfig(), 1) - require.NoError(t, err) - r := bytesutil.ToBytes32(b.Block.ParentRoot) - util.SaveBlock(t, ctx, vs.BeaconDB, b) - require.NoError(t, vs.BeaconDB.SaveState(ctx, beaconState, r)) - - altairBlk, err := util.GenerateFullBlockAltair(copiedState, keys, util.DefaultBlockGenConfig(), 2) - require.NoError(t, err) - - ts := uint64(time.Now().Unix()) + uint64(altairBlk.Block.Slot)*params.BeaconConfig().SecondsPerSlot - h := &v1.ExecutionPayloadHeader{ - BlockNumber: 123, - GasLimit: 456, - GasUsed: 789, - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - Timestamp: ts, - } - - vs.StateGen = stategen.New(vs.BeaconDB, doublylinkedtree.New()) - vs.GenesisFetcher = &blockchainTest.ChainService{} - vs.ForkFetcher = &blockchainTest.ChainService{Fork: ðpb.Fork{}} - - sk, err := bls.RandKey() - require.NoError(t, err) - bid := ðpb.BuilderBid{ - Header: &v1.ExecutionPayloadHeader{ - BlockNumber: 123, - GasLimit: 456, - GasUsed: 789, - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - Timestamp: ts, - }, - Pubkey: sk.PublicKey().Marshal(), - Value: bytesutil.PadTo([]byte{1, 2, 3}, 32), - } - d := params.BeaconConfig().DomainApplicationBuilder - domain, err := signing.ComputeDomain(d, nil, nil) - require.NoError(t, err) - sr, err := signing.ComputeSigningRoot(bid, domain) - require.NoError(t, err) - sBid := ðpb.SignedBuilderBid{ - Message: bid, - Signature: sk.Sign(sr[:]).Marshal(), - } - vs.BlockBuilder = &builderTest.MockBuilderService{HasConfigured: true, Bid: sBid} - vs.TimeFetcher = &blockchainTest.ChainService{Genesis: time.Now()} - vs.ForkFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()} - ready, builtBlk, err := vs.GetAndBuildBlindBlock(ctx, altairBlk.Block) - require.NoError(t, err) - require.Equal(t, true, ready) - require.DeepEqual(t, h, builtBlk.GetBlindedBellatrix().Body.ExecutionPayloadHeader) -} - -func TestServer_GetBellatrixBeaconBlock_HappyCase(t *testing.T) { - db := dbTest.SetupDB(t) - ctx := context.Background() - hook := logTest.NewGlobal() - - terminalBlockHash := bytesutil.PadTo([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 32) - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig().Copy() - cfg.BellatrixForkEpoch = 2 - cfg.AltairForkEpoch = 1 - cfg.TerminalBlockHash = common.BytesToHash(terminalBlockHash) - cfg.TerminalBlockHashActivationEpoch = 2 - params.OverrideBeaconConfig(cfg) - - beaconState, privKeys := util.DeterministicGenesisState(t, 64) - stateRoot, err := beaconState.HashTreeRoot(ctx) - require.NoError(t, err, "Could not hash genesis state") - - genesis := consensusblocks.NewGenesisBlock(stateRoot[:]) - wsb, err := blocks.NewSignedBeaconBlock(genesis) - require.NoError(t, err) - require.NoError(t, db.SaveBlock(ctx, wsb), "Could not save genesis block") - - parentRoot, err := genesis.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) - require.NoError(t, err) - - emptyPayload := &v1.ExecutionPayload{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - } - var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte - blk := ðpb.SignedBeaconBlockBellatrix{ - Block: ðpb.BeaconBlockBellatrix{ - Slot: bellatrixSlot + 1, - ParentRoot: parentRoot[:], - StateRoot: genesis.Block.StateRoot, - Body: ðpb.BeaconBlockBodyBellatrix{ - RandaoReveal: genesis.Block.Body.RandaoReveal, - Graffiti: genesis.Block.Body.Graffiti, - Eth1Data: genesis.Block.Body.Eth1Data, - SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, - ExecutionPayload: emptyPayload, - }, - }, - Signature: genesis.Signature, - } - - blkRoot, err := blk.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") - - proposerServer := &Server{ - HeadFetcher: &blockchainTest.ChainService{State: beaconState, Root: parentRoot[:], Optimistic: false}, - TimeFetcher: &blockchainTest.ChainService{Genesis: time.Now()}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: &blockchainTest.ChainService{}, - HeadUpdater: &blockchainTest.ChainService{}, - ChainStartFetcher: &mockExecution.Chain{}, - Eth1InfoFetcher: &mockExecution.Chain{}, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), - SyncCommitteePool: synccommittee.NewStore(), - ExecutionEngineCaller: &mockExecution.EngineClient{ - PayloadIDBytes: &v1.PayloadIDBytes{1}, - ExecutionPayload: emptyPayload, - }, - BeaconDB: db, - ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), - BlockBuilder: &builderTest.MockBuilderService{}, - } - proposerServer.ProposerSlotIndexCache.SetProposerAndPayloadIDs(17, 11, [8]byte{'a'}, parentRoot) - - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) - require.NoError(t, err) - - block, err := proposerServer.getBellatrixBeaconBlock(ctx, ðpb.BlockRequest{ - Slot: bellatrixSlot + 1, - RandaoReveal: randaoReveal, - }) - require.NoError(t, err) - bellatrixBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Bellatrix) - require.Equal(t, true, ok) - require.LogsContain(t, hook, "Computed state root") - require.DeepEqual(t, emptyPayload, bellatrixBlk.Bellatrix.Body.ExecutionPayload) // Payload should equal. -} - -func TestServer_GetBellatrixBeaconBlock_LocalProgressingWithBuilderSkipped(t *testing.T) { - db := dbTest.SetupDB(t) - ctx := context.Background() - hook := logTest.NewGlobal() - - terminalBlockHash := bytesutil.PadTo([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 32) - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig().Copy() - cfg.BellatrixForkEpoch = 2 - cfg.AltairForkEpoch = 1 - cfg.TerminalBlockHash = common.BytesToHash(terminalBlockHash) - cfg.TerminalBlockHashActivationEpoch = 2 - params.OverrideBeaconConfig(cfg) - - beaconState, privKeys := util.DeterministicGenesisState(t, 64) - stateRoot, err := beaconState.HashTreeRoot(ctx) - require.NoError(t, err, "Could not hash genesis state") - - genesis := consensusblocks.NewGenesisBlock(stateRoot[:]) - wsb, err := blocks.NewSignedBeaconBlock(genesis) - require.NoError(t, err) - require.NoError(t, db.SaveBlock(ctx, wsb), "Could not save genesis block") - - parentRoot, err := genesis.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) - require.NoError(t, err) - - emptyPayload := &v1.ExecutionPayload{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - } - var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte - blk := ðpb.SignedBeaconBlockBellatrix{ - Block: ðpb.BeaconBlockBellatrix{ - Slot: bellatrixSlot + 1, - ParentRoot: parentRoot[:], - StateRoot: genesis.Block.StateRoot, - Body: ðpb.BeaconBlockBodyBellatrix{ - RandaoReveal: genesis.Block.Body.RandaoReveal, - Graffiti: genesis.Block.Body.Graffiti, - Eth1Data: genesis.Block.Body.Eth1Data, - SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, - ExecutionPayload: emptyPayload, - }, - }, - Signature: genesis.Signature, - } - - blkRoot, err := blk.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") - - proposerServer := &Server{ - HeadFetcher: &blockchainTest.ChainService{State: beaconState, Root: parentRoot[:], Optimistic: false}, - TimeFetcher: &blockchainTest.ChainService{Genesis: time.Now()}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: &blockchainTest.ChainService{}, - HeadUpdater: &blockchainTest.ChainService{}, - ChainStartFetcher: &mockExecution.Chain{}, - Eth1InfoFetcher: &mockExecution.Chain{}, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), - SyncCommitteePool: synccommittee.NewStore(), - ExecutionEngineCaller: &mockExecution.EngineClient{ - PayloadIDBytes: &v1.PayloadIDBytes{1}, - ExecutionPayload: emptyPayload, - }, - BeaconDB: db, - ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), - BlockBuilder: &builderTest.MockBuilderService{}, - } - proposerServer.ProposerSlotIndexCache.SetProposerAndPayloadIDs(17, 11, [8]byte{'a'}, parentRoot) - - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) - require.NoError(t, err) - - // Configure builder, this should fail if it's not local engine processing - proposerServer.BlockBuilder = &builderTest.MockBuilderService{HasConfigured: true, ErrGetHeader: errors.New("bad)")} - block, err := proposerServer.getBellatrixBeaconBlock(ctx, ðpb.BlockRequest{ - Slot: bellatrixSlot + 1, - RandaoReveal: randaoReveal, - SkipMevBoost: true, - }) - require.NoError(t, err) - bellatrixBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Bellatrix) - require.Equal(t, true, ok) - require.LogsContain(t, hook, "Computed state root") - require.DeepEqual(t, emptyPayload, bellatrixBlk.Bellatrix.Body.ExecutionPayload) // Payload should equal. -} - -func TestServer_GetBellatrixBeaconBlock_BuilderCase(t *testing.T) { - db := dbTest.SetupDB(t) - ctx := context.Background() - hook := logTest.NewGlobal() - - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig().Copy() - cfg.BellatrixForkEpoch = 2 - cfg.AltairForkEpoch = 1 - params.OverrideBeaconConfig(cfg) - - beaconState, privKeys := util.DeterministicGenesisState(t, 64) - stateRoot, err := beaconState.HashTreeRoot(ctx) - require.NoError(t, err, "Could not hash genesis state") - - genesis := consensusblocks.NewGenesisBlock(stateRoot[:]) - wsb, err := blocks.NewSignedBeaconBlock(genesis) - require.NoError(t, err) - require.NoError(t, db.SaveBlock(ctx, wsb), "Could not save genesis block") - - parentRoot, err := genesis.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) - require.NoError(t, err) - - emptyPayload := &v1.ExecutionPayload{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - } - var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte - blk := ðpb.SignedBeaconBlockBellatrix{ - Block: ðpb.BeaconBlockBellatrix{ - Slot: bellatrixSlot + 1, - ParentRoot: parentRoot[:], - StateRoot: genesis.Block.StateRoot, - Body: ðpb.BeaconBlockBodyBellatrix{ - RandaoReveal: genesis.Block.Body.RandaoReveal, - Graffiti: genesis.Block.Body.Graffiti, - Eth1Data: genesis.Block.Body.Eth1Data, - SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, - ExecutionPayload: emptyPayload, - }, - }, - Signature: genesis.Signature, - } - - blkRoot, err := blk.Block.HashTreeRoot() - require.NoError(t, err) - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") - - b1 := util.NewBeaconBlockBellatrix() - b1.Block.Body.ExecutionPayload.BlockNumber = 1 // Execution enabled. - wb1, err := blocks.NewSignedBeaconBlock(b1) - require.NoError(t, err) - wbr1, err := wb1.Block().HashTreeRoot() - require.NoError(t, err) - require.NoError(t, db.SaveBlock(ctx, wb1)) - - random, err := helpers.RandaoMix(beaconState, prysmtime.CurrentEpoch(beaconState)) - require.NoError(t, err) - - tstamp, err := slots.ToTime(beaconState.GenesisTime(), bellatrixSlot+1) - require.NoError(t, err) - h := &v1.ExecutionPayloadHeader{ - BlockNumber: 123, - GasLimit: 456, - GasUsed: 789, - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: random, - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - Timestamp: uint64(tstamp.Unix()), - } - - proposerServer := &Server{ - FinalizationFetcher: &blockchainTest.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{Root: wbr1[:]}}, - HeadFetcher: &blockchainTest.ChainService{State: beaconState, Root: parentRoot[:], Optimistic: false, Block: wb1}, - TimeFetcher: &blockchainTest.ChainService{Genesis: time.Unix(int64(beaconState.GenesisTime()), 0)}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: &blockchainTest.ChainService{}, - HeadUpdater: &blockchainTest.ChainService{}, - ForkFetcher: &blockchainTest.ChainService{Fork: ðpb.Fork{}}, - GenesisFetcher: &blockchainTest.ChainService{}, - ChainStartFetcher: &mockExecution.Chain{}, - Eth1InfoFetcher: &mockExecution.Chain{}, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), - SyncCommitteePool: synccommittee.NewStore(), - ExecutionEngineCaller: &mockExecution.EngineClient{ - PayloadIDBytes: &v1.PayloadIDBytes{1}, - ExecutionPayload: emptyPayload, - }, - BeaconDB: db, - } - sk, err := bls.RandKey() - require.NoError(t, err) - bid := ðpb.BuilderBid{ - Header: h, - Pubkey: sk.PublicKey().Marshal(), - Value: bytesutil.PadTo([]byte{1, 2, 3}, 32), - } - d := params.BeaconConfig().DomainApplicationBuilder - domain, err := signing.ComputeDomain(d, nil, nil) - require.NoError(t, err) - sr, err := signing.ComputeSigningRoot(bid, domain) - require.NoError(t, err) - sBid := ðpb.SignedBuilderBid{ - Message: bid, - Signature: sk.Sign(sr[:]).Marshal(), - } - proposerServer.BlockBuilder = &builderTest.MockBuilderService{HasConfigured: true, Bid: sBid} - proposerServer.ForkFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()} - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) - require.NoError(t, err) - - require.NoError(t, proposerServer.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []types.ValidatorIndex{11}, - []*ethpb.ValidatorRegistrationV1{{FeeRecipient: bytesutil.PadTo([]byte{}, fieldparams.FeeRecipientLength), Pubkey: bytesutil.PadTo([]byte{}, fieldparams.BLSPubkeyLength)}})) - - params.SetupTestConfigCleanup(t) - cfg.MaxBuilderConsecutiveMissedSlots = bellatrixSlot + 1 - cfg.MaxBuilderEpochMissedSlots = 32 - params.OverrideBeaconConfig(cfg) - - block, err := proposerServer.getBellatrixBeaconBlock(ctx, ðpb.BlockRequest{ - Slot: bellatrixSlot + 1, - RandaoReveal: randaoReveal, - }) - require.NoError(t, err) - bellatrixBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_BlindedBellatrix) - require.Equal(t, true, ok) - require.LogsContain(t, hook, "Computed state root") - require.DeepEqual(t, h, bellatrixBlk.BlindedBellatrix.Body.ExecutionPayloadHeader) // Payload header should equal. -} - func TestServer_validateBuilderSignature(t *testing.T) { sk, err := bls.RandKey() require.NoError(t, err) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go index 9778b8eba075..89951e59cf5f 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go @@ -12,11 +12,12 @@ import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute" types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" @@ -41,7 +42,7 @@ var ( // This returns the execution payload of a given slot. The function has full awareness of pre and post merge. // The payload is computed given the respected time of merge. -func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx types.ValidatorIndex, headRoot [32]byte) (*enginev1.ExecutionPayload, error) { +func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx types.ValidatorIndex, headRoot [32]byte, st state.BeaconState) (interfaces.ExecutionData, error) { proposerID, payloadId, ok := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, headRoot) feeRecipient := params.BeaconConfig().DefaultFeeRecipient recipient, err := vs.BeaconDB.FeeRecipientByValidatorID(ctx, vIdx) @@ -71,27 +72,14 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, pid, slot) switch { case err == nil: - pb, err := payload.PbBellatrix() - if err != nil { - return nil, err - } - warnIfFeeRecipientDiffers(pb, feeRecipient) - return pb, nil + warnIfFeeRecipientDiffers(payload, feeRecipient) + return payload, nil case errors.Is(err, context.DeadlineExceeded): default: return nil, errors.Wrap(err, "could not get cached payload from execution client") } } - st, err := vs.HeadFetcher.HeadState(ctx) - if err != nil { - return nil, err - } - st, err = transition.ProcessSlotsIfPossible(ctx, st, slot) - if err != nil { - return nil, err - } - var parentHash []byte var hasTerminalBlock bool mergeComplete, err := blocks.IsMergeTransitionComplete(st) @@ -111,14 +99,14 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx parentHash = header.BlockHash() } else { if activationEpochNotReached(slot) { - return emptyPayload(), nil + return consensusblocks.WrappedExecutionPayload(emptyPayload()) } parentHash, hasTerminalBlock, err = vs.getTerminalBlockHashIfExists(ctx, uint64(t.Unix())) if err != nil { return nil, err } if !hasTerminalBlock { - return emptyPayload(), nil + return consensusblocks.WrappedExecutionPayload(emptyPayload()) } } payloadIDCacheMiss.Inc() @@ -176,22 +164,18 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx if err != nil { return nil, err } - pb, err := payload.PbBellatrix() - if err != nil { - return nil, err - } - warnIfFeeRecipientDiffers(pb, feeRecipient) - return pb, nil + warnIfFeeRecipientDiffers(payload, feeRecipient) + return payload, nil } // warnIfFeeRecipientDiffers logs a warning if the fee recipient in the included payload does not // match the requested one. -func warnIfFeeRecipientDiffers(payload *enginev1.ExecutionPayload, feeRecipient common.Address) { +func warnIfFeeRecipientDiffers(payload interfaces.ExecutionData, feeRecipient common.Address) { // Warn if the fee recipient is not the value we expect. - if payload != nil && !bytes.Equal(payload.FeeRecipient, feeRecipient[:]) { + if payload != nil && !bytes.Equal(payload.FeeRecipient(), feeRecipient[:]) { logrus.WithFields(logrus.Fields{ "wantedFeeRecipient": fmt.Sprintf("%#x", feeRecipient), - "received": fmt.Sprintf("%#x", payload.FeeRecipient), + "received": fmt.Sprintf("%#x", payload.FeeRecipient()), }).Warn("Fee recipient address from execution client is not what was expected. " + "It is possible someone has compromised your client to try and take your transaction fees") } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go deleted file mode 100644 index 6ce7208a52b1..000000000000 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go +++ /dev/null @@ -1,170 +0,0 @@ -package validator - -import ( - "context" - "fmt" - - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop" - v "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v3/config/params" - consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" - types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" - "go.opencensus.io/trace" -) - -// blockData required to create a beacon block. -type blockData struct { - ParentRoot []byte - Graffiti [32]byte - ProposerIdx types.ValidatorIndex - Eth1Data *ethpb.Eth1Data - Deposits []*ethpb.Deposit - Attestations []*ethpb.Attestation - ProposerSlashings []*ethpb.ProposerSlashing - AttesterSlashings []*ethpb.AttesterSlashing - VoluntaryExits []*ethpb.SignedVoluntaryExit -} - -func (vs *Server) getPhase0BeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlock, error) { - ctx, span := trace.StartSpan(ctx, "ProposerServer.getPhase0BeaconBlock") - defer span.End() - blkData, err := vs.buildPhase0BlockData(ctx, req) - if err != nil { - return nil, fmt.Errorf("could not build block data: %v", err) - } - - // Use zero hash as stub for state root to compute later. - stateRoot := params.BeaconConfig().ZeroHash[:] - - blk := ðpb.BeaconBlock{ - Slot: req.Slot, - ParentRoot: blkData.ParentRoot, - StateRoot: stateRoot, - ProposerIndex: blkData.ProposerIdx, - Body: ðpb.BeaconBlockBody{ - Eth1Data: blkData.Eth1Data, - Deposits: blkData.Deposits, - Attestations: blkData.Attestations, - RandaoReveal: req.RandaoReveal, - ProposerSlashings: blkData.ProposerSlashings, - AttesterSlashings: blkData.AttesterSlashings, - VoluntaryExits: blkData.VoluntaryExits, - Graffiti: blkData.Graffiti[:], - }, - } - - // Compute state root with the newly constructed block. - wsb, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: blk, Signature: make([]byte, 96)}) - if err != nil { - return nil, err - } - stateRoot, err = vs.computeStateRoot(ctx, wsb) - if err != nil { - interop.WriteBlockToDisk(wsb, true /*failed*/) - return nil, errors.Wrap(err, "could not compute state root") - } - blk.StateRoot = stateRoot - return blk, nil -} - -// Build data required for creating a new beacon block, so this method can be shared across forks. -func (vs *Server) buildPhase0BlockData(ctx context.Context, req *ethpb.BlockRequest) (*blockData, error) { - ctx, span := trace.StartSpan(ctx, "ProposerServer.buildPhase0BlockData") - defer span.End() - - if vs.SyncChecker.Syncing() { - return nil, fmt.Errorf("syncing to latest head, not ready to respond") - } - - if err := vs.HeadUpdater.UpdateHead(ctx); err != nil { - log.WithError(err).Error("Could not process attestations and update head") - } - - // Retrieve the parent block as the current head of the canonical chain. - parentRoot, err := vs.HeadFetcher.HeadRoot(ctx) - if err != nil { - return nil, fmt.Errorf("could not retrieve head root: %v", err) - } - - head, err := vs.HeadFetcher.HeadState(ctx) - if err != nil { - return nil, fmt.Errorf("could not get head state %v", err) - } - - head, err = transition.ProcessSlotsUsingNextSlotCache(ctx, head, parentRoot, req.Slot) - if err != nil { - return nil, fmt.Errorf("could not advance slots to calculate proposer index: %v", err) - } - - eth1Data, err := vs.eth1DataMajorityVote(ctx, head) - if err != nil { - return nil, fmt.Errorf("could not get ETH1 data: %v", err) - } - - deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) - if err != nil { - return nil, err - } - - graffiti := bytesutil.ToBytes32(req.Graffiti) - - // Calculate new proposer index. - idx, err := helpers.BeaconProposerIndex(ctx, head) - if err != nil { - return nil, fmt.Errorf("could not calculate proposer index %v", err) - } - - proposerSlashings := vs.SlashingsPool.PendingProposerSlashings(ctx, head, false /*noLimit*/) - validProposerSlashings := make([]*ethpb.ProposerSlashing, 0, len(proposerSlashings)) - for _, slashing := range proposerSlashings { - _, err := blocks.ProcessProposerSlashing(ctx, head, slashing, v.SlashValidator) - if err != nil { - log.WithError(err).Warn("Proposer: invalid proposer slashing") - continue - } - validProposerSlashings = append(validProposerSlashings, slashing) - } - - attSlashings := vs.SlashingsPool.PendingAttesterSlashings(ctx, head, false /*noLimit*/) - validAttSlashings := make([]*ethpb.AttesterSlashing, 0, len(attSlashings)) - for _, slashing := range attSlashings { - _, err := blocks.ProcessAttesterSlashing(ctx, head, slashing, v.SlashValidator) - if err != nil { - log.WithError(err).Warn("Proposer: invalid attester slashing") - continue - } - validAttSlashings = append(validAttSlashings, slashing) - } - exits := vs.ExitPool.PendingExits(head, req.Slot, false /*noLimit*/) - validExits := make([]*ethpb.SignedVoluntaryExit, 0, len(exits)) - for _, exit := range exits { - val, err := head.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex) - if err != nil { - log.WithError(err).Warn("Proposer: invalid exit") - continue - } - if err := blocks.VerifyExitAndSignature(val, head.Slot(), head.Fork(), exit, head.GenesisValidatorsRoot()); err != nil { - log.WithError(err).Warn("Proposer: invalid exit") - continue - } - validExits = append(validExits, exit) - } - - return &blockData{ - ParentRoot: parentRoot, - Graffiti: graffiti, - ProposerIdx: idx, - Eth1Data: eth1Data, - Deposits: deposits, - Attestations: atts, - ProposerSlashings: validProposerSlashings, - AttesterSlashings: validAttSlashings, - VoluntaryExits: validExits, - }, nil -} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go index ebea1b1dca35..6c795920370c 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go @@ -20,6 +20,7 @@ import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/db" "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits" @@ -72,6 +73,7 @@ type Server struct { BeaconDB db.HeadAccessDatabase ExecutionEngineCaller execution.EngineCaller BlockBuilder builder.BlockBuilder + BLSChangesPool blstoexec.PoolManager } // WaitForActivation checks if a validator public key exists in the active validator registry of the current From b72323ff7d97db7a4eac6812facfc4067920958c Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 28 Dec 2022 10:32:10 -0800 Subject: [PATCH 04/30] Fix build.bazel for v1alpha1 rpcs --- .../rpc/prysm/v1alpha1/validator/BUILD.bazel | 75 ++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 2bd95ff63bca..4ede33a06c00 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -14,9 +14,12 @@ go_library( "proposer_attestations.go", "proposer_bellatrix.go", "proposer_deposits.go", + "proposer_empty_block.go", "proposer_eth1data.go", "proposer_execution_payload.go", + "proposer_exists.go", "proposer_phase0.go", + "proposer_slashings.go", "proposer_sync_aggregate.go", "server.go", "status.go", @@ -58,8 +61,8 @@ go_library( "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", - "//consensus-types/primitives:go_default_library", "//consensus-types/payload-attribute:go_default_library", + "//consensus-types/primitives:go_default_library", "//container/trie:go_default_library", "//contracts/deposit:go_default_library", "//crypto/bls:go_default_library", @@ -173,10 +176,15 @@ go_test( "proposer_attestations_test.go", "proposer_bellatrix_test.go", "proposer_deposits_test.go", + "proposer_empty_block_test.go", "proposer_execution_payload_test.go", + "proposer_exists_test.go", + "proposer_slashings_test.go", "proposer_sync_aggregate_test.go", "proposer_test.go", + "server_mainnet_test.go", "server_test.go", + "status_mainnet_test.go", "status_test.go", "sync_committee_test.go", "validator_test.go", @@ -184,7 +192,70 @@ go_test( embed = [":go_default_library"], eth_network = "minimal", tags = ["minimal"], - deps = common_deps, + deps = [ + "//async/event:go_default_library", + "//beacon-chain/blockchain/testing:go_default_library", + "//beacon-chain/builder:go_default_library", + "//beacon-chain/builder/testing:go_default_library", + "//beacon-chain/cache:go_default_library", + "//beacon-chain/cache/depositcache:go_default_library", + "//beacon-chain/core/altair:go_default_library", + "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/execution:go_default_library", + "//beacon-chain/core/feed:go_default_library", + "//beacon-chain/core/feed/block:go_default_library", + "//beacon-chain/core/feed/operation:go_default_library", + "//beacon-chain/core/feed/state:go_default_library", + "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/core/signing:go_default_library", + "//beacon-chain/core/time:go_default_library", + "//beacon-chain/core/transition:go_default_library", + "//beacon-chain/db/testing:go_default_library", + "//beacon-chain/execution/testing:go_default_library", + "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", + "//beacon-chain/operations/attestations:go_default_library", + "//beacon-chain/operations/slashings:go_default_library", + "//beacon-chain/operations/synccommittee:go_default_library", + "//beacon-chain/operations/voluntaryexits:go_default_library", + "//beacon-chain/p2p/testing:go_default_library", + "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native:go_default_library", + "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/state/stategen/mock:go_default_library", + "//beacon-chain/sync/initial-sync/testing:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//consensus-types/primitives:go_default_library", + "//container/trie:go_default_library", + "//crypto/bls:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/engine/v1:go_default_library", + "//proto/eth/v1:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/attestation:go_default_library", + "//testing/assert:go_default_library", + "//testing/mock:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "//time:go_default_library", + "//time/slots:go_default_library", + "@com_github_d4l3k_messagediff//: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//core/types:go_default_library", + "@com_github_golang_mock//gomock:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", + "@org_golang_google_grpc//codes:go_default_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", + ], ) go_test( From a14b667bee08bd1074ed85160705ce6fcf7453d1 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 28 Dec 2022 11:01:22 -0800 Subject: [PATCH 05/30] Rm unused code --- .../rpc/prysm/v1alpha1/validator/BUILD.bazel | 1 - .../v1alpha1/validator/proposer_altair.go | 63 ------------------- .../validator/proposer_bellatrix_test.go | 4 +- .../proposer_execution_payload_test.go | 8 +-- 4 files changed, 7 insertions(+), 69 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 0dae3a68f20c..bd4439b1e15d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -170,7 +170,6 @@ go_test( srcs = [ "aggregator_test.go", "assignments_test.go", - "attester_mainnet_test.go", "attester_test.go", "blocks_test.go", "exit_test.go", diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index 69a2a619425e..0c767101c5bb 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -2,11 +2,8 @@ package validator import ( "context" - "fmt" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop" "github.com/prysmaticlabs/prysm/v3/config/params" - "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v3/crypto/bls" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" @@ -15,66 +12,6 @@ import ( "go.opencensus.io/trace" ) -func (vs *Server) BuildAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) { - ctx, span := trace.StartSpan(ctx, "ProposerServer.BuildAltairBeaconBlock") - defer span.End() - blkData, err := vs.buildPhase0BlockData(ctx, req) - if err != nil { - return nil, fmt.Errorf("could not build block data: %v", err) - } - - // Use zero hash as stub for state root to compute later. - stateRoot := params.BeaconConfig().ZeroHash[:] - - // No need for safe sub as req.Slot cannot be 0 if requesting Altair blocks. If 0, we will be throwing - // an error in the first validity check of this endpoint. - syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(blkData.ParentRoot)) - if err != nil { - return nil, err - } - - return ðpb.BeaconBlockAltair{ - Slot: req.Slot, - ParentRoot: blkData.ParentRoot, - StateRoot: stateRoot, - ProposerIndex: blkData.ProposerIdx, - Body: ðpb.BeaconBlockBodyAltair{ - Eth1Data: blkData.Eth1Data, - Deposits: blkData.Deposits, - Attestations: blkData.Attestations, - RandaoReveal: req.RandaoReveal, - ProposerSlashings: blkData.ProposerSlashings, - AttesterSlashings: blkData.AttesterSlashings, - VoluntaryExits: blkData.VoluntaryExits, - Graffiti: blkData.Graffiti[:], - SyncAggregate: syncAggregate, - }, - }, nil -} - -func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) { - ctx, span := trace.StartSpan(ctx, "ProposerServer.getAltairBeaconBlock") - defer span.End() - blk, err := vs.BuildAltairBeaconBlock(ctx, req) - if err != nil { - return nil, fmt.Errorf("could not build block data: %v", err) - } - // Compute state root with the newly constructed block. - wsb, err := blocks.NewSignedBeaconBlock( - ðpb.SignedBeaconBlockAltair{Block: blk, Signature: make([]byte, 96)}, - ) - if err != nil { - return nil, err - } - stateRoot, err := vs.computeStateRoot(ctx, wsb) - if err != nil { - interop.WriteBlockToDisk(wsb, true /*failed*/) - return nil, fmt.Errorf("could not compute state root: %v", err) - } - blk.StateRoot = stateRoot - return blk, nil -} - // getSyncAggregate retrieves the sync contributions from the pool to construct the sync aggregate object. // The contributions are filtered based on matching of the input root and slot then profitability. func (vs *Server) getSyncAggregate(ctx context.Context, slot types.Slot, root [32]byte) (*ethpb.SyncAggregate, error) { 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 264c8a59baa0..926b2021b01d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go @@ -158,7 +158,9 @@ func TestServer_getPayloadHeader(t *testing.T) { require.ErrorContains(t, tc.err, err) } else { require.NoError(t, err) - require.DeepEqual(t, tc.returnedHeader, h) + want, err := blocks.WrappedExecutionPayloadHeader(tc.returnedHeader) + require.NoError(t, err) + require.DeepEqual(t, want, h) } }) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload_test.go index 4f570ed32bb9..074bb3c5eb61 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload_test.go @@ -124,7 +124,7 @@ func TestServer_getExecutionPayload(t *testing.T) { ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), } vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(tt.st.Slot(), 100, [8]byte{100}, [32]byte{'a'}) - _, err := vs.getExecutionPayload(context.Background(), tt.st.Slot(), tt.validatorIndx, [32]byte{'a'}) + _, err := vs.getExecutionPayload(context.Background(), tt.st.Slot(), tt.validatorIndx, [32]byte{'a'}, tt.st) if tt.errString != "" { require.ErrorContains(t, tt.errString, err) } else { @@ -160,7 +160,7 @@ func TestServer_getExecutionPayloadContextTimeout(t *testing.T) { } vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nonTransitionSt.Slot(), 100, [8]byte{100}, [32]byte{'a'}) - _, err = vs.getExecutionPayload(context.Background(), nonTransitionSt.Slot(), 100, [32]byte{'a'}) + _, err = vs.getExecutionPayload(context.Background(), nonTransitionSt.Slot(), 100, [32]byte{'a'}, nonTransitionSt) require.NoError(t, err) } @@ -205,7 +205,7 @@ func TestServer_getExecutionPayload_UnexpectedFeeRecipient(t *testing.T) { BeaconDB: beaconDB, ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), } - gotPayload, err := vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}) + gotPayload, err := vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}, transitionSt) require.NoError(t, err) require.NotNil(t, gotPayload) @@ -217,7 +217,7 @@ func TestServer_getExecutionPayload_UnexpectedFeeRecipient(t *testing.T) { payload.FeeRecipient = evilRecipientAddress[:] vs.ProposerSlotIndexCache = cache.NewProposerPayloadIDsCache() - gotPayload, err = vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}) + gotPayload, err = vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}, transitionSt) require.NoError(t, err) require.NotNil(t, gotPayload) From a8986b9cf6111ddabde4feaec9ca9d05b16ad44c Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 30 Dec 2022 13:16:21 -0800 Subject: [PATCH 06/30] Rm old tests --- .../validator/proposer_bellatrix_test.go | 8 +- .../prysm/v1alpha1/validator/proposer_test.go | 384 ------------------ 2 files changed, 5 insertions(+), 387 deletions(-) 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 926b2021b01d..02b65ebbfb38 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go @@ -158,9 +158,11 @@ func TestServer_getPayloadHeader(t *testing.T) { require.ErrorContains(t, tc.err, err) } else { require.NoError(t, err) - want, err := blocks.WrappedExecutionPayloadHeader(tc.returnedHeader) - require.NoError(t, err) - require.DeepEqual(t, want, h) + if tc.returnedHeader != nil { + want, err := blocks.WrappedExecutionPayloadHeader(tc.returnedHeader) + require.NoError(t, err) + require.DeepEqual(t, want, h) + } } }) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index 597583e87263..bd8815fef79b 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -4,7 +4,6 @@ import ( "context" "math/big" "testing" - "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -13,7 +12,6 @@ import ( mock "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder" builderTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder/testing" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v3/beacon-chain/cache/depositcache" b "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" @@ -23,9 +21,7 @@ import ( mockExecution "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing" doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee" - "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits" mockp2p "github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p/testing" state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stategen" @@ -37,17 +33,13 @@ import ( "github.com/prysmaticlabs/prysm/v3/container/trie" "github.com/prysmaticlabs/prysm/v3/crypto/bls" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" - enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation" attaggregation "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation/aggregation/attestations" "github.com/prysmaticlabs/prysm/v3/testing/assert" "github.com/prysmaticlabs/prysm/v3/testing/require" "github.com/prysmaticlabs/prysm/v3/testing/util" - "github.com/prysmaticlabs/prysm/v3/time/slots" logTest "github.com/sirupsen/logrus/hooks/test" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) @@ -1914,382 +1906,6 @@ func TestProposer_DeleteAttsInPool_Aggregated(t *testing.T) { assert.Equal(t, 0, len(atts), "Did not delete unaggregated attestation") } -func TestProposer_GetBeaconBlock_PreForkEpoch(t *testing.T) { - db := dbutil.SetupDB(t) - ctx := context.Background() - - beaconState, privKeys := util.DeterministicGenesisState(t, 64) - stateRoot, err := beaconState.HashTreeRoot(ctx) - require.NoError(t, err, "Could not hash genesis state") - - genesis := b.NewGenesisBlock(stateRoot[:]) - genBlk := ðpb.SignedBeaconBlock{ - Block: ðpb.BeaconBlock{ - Slot: genesis.Block.Slot, - ParentRoot: genesis.Block.ParentRoot, - StateRoot: genesis.Block.StateRoot, - Body: ðpb.BeaconBlockBody{ - RandaoReveal: genesis.Block.Body.RandaoReveal, - Graffiti: genesis.Block.Body.Graffiti, - Eth1Data: genesis.Block.Body.Eth1Data, - }, - }, - Signature: genesis.Signature, - } - util.SaveBlock(t, ctx, db, genBlk) - - parentRoot, err := genBlk.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - proposerServer := &Server{ - HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:]}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: &mock.ChainService{}, - HeadUpdater: &mock.ChainService{}, - ChainStartFetcher: &mockExecution.Chain{}, - Eth1InfoFetcher: &mockExecution.Chain{}, - Eth1BlockFetcher: &mockExecution.Chain{}, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), - SyncCommitteePool: synccommittee.NewStore(), - } - - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) - require.NoError(t, err) - - graffiti := bytesutil.ToBytes32([]byte("eth2")) - req := ðpb.BlockRequest{ - Slot: 1, - RandaoReveal: randaoReveal, - Graffiti: graffiti[:], - } - - proposerSlashings := make([]*ethpb.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) - for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { - proposerSlashing, err := util.GenerateProposerSlashingForValidator( - beaconState, - privKeys[i], - i, /* validator index */ - ) - require.NoError(t, err) - proposerSlashings[i] = proposerSlashing - err = proposerServer.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) - require.NoError(t, err) - } - - attSlashings := make([]*ethpb.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) - for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { - attesterSlashing, err := util.GenerateAttesterSlashingForValidator( - beaconState, - privKeys[i+params.BeaconConfig().MaxProposerSlashings], - types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ - ) - require.NoError(t, err) - attSlashings[i] = attesterSlashing - err = proposerServer.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) - require.NoError(t, err) - } - block, err := proposerServer.GetBeaconBlock(ctx, req) - require.NoError(t, err) - phase0Blk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Phase0) - require.Equal(t, true, ok) - - assert.Equal(t, req.Slot, phase0Blk.Phase0.Slot) - assert.DeepEqual(t, parentRoot[:], phase0Blk.Phase0.ParentRoot, "Expected block to have correct parent root") - assert.DeepEqual(t, randaoReveal, phase0Blk.Phase0.Body.RandaoReveal, "Expected block to have correct randao reveal") - assert.DeepEqual(t, req.Graffiti, phase0Blk.Phase0.Body.Graffiti, "Expected block to have correct Graffiti") - assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(phase0Blk.Phase0.Body.ProposerSlashings))) - assert.DeepEqual(t, proposerSlashings, phase0Blk.Phase0.Body.ProposerSlashings) - assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(phase0Blk.Phase0.Body.AttesterSlashings))) - assert.DeepEqual(t, attSlashings, phase0Blk.Phase0.Body.AttesterSlashings) -} - -func TestProposer_GetBeaconBlock_PostForkEpoch(t *testing.T) { - db := dbutil.SetupDB(t) - ctx := context.Background() - - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig().Copy() - cfg.AltairForkEpoch = 1 - params.OverrideBeaconConfig(cfg) - beaconState, privKeys := util.DeterministicGenesisState(t, 64) - - stateRoot, err := beaconState.HashTreeRoot(ctx) - require.NoError(t, err, "Could not hash genesis state") - - genesis := b.NewGenesisBlock(stateRoot[:]) - util.SaveBlock(t, ctx, db, genesis) - - parentRoot, err := genesis.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - altairSlot, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch) - require.NoError(t, err) - - var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte - genAltair := ðpb.SignedBeaconBlockAltair{ - Block: ðpb.BeaconBlockAltair{ - Slot: altairSlot + 1, - ParentRoot: parentRoot[:], - StateRoot: genesis.Block.StateRoot, - Body: ðpb.BeaconBlockBodyAltair{ - RandaoReveal: genesis.Block.Body.RandaoReveal, - Graffiti: genesis.Block.Body.Graffiti, - Eth1Data: genesis.Block.Body.Eth1Data, - SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, - }, - }, - Signature: genesis.Signature, - } - - blkRoot, err := genAltair.Block.HashTreeRoot() - require.NoError(t, err) - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") - - proposerServer := &Server{ - HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:]}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: &mock.ChainService{}, - HeadUpdater: &mock.ChainService{}, - ChainStartFetcher: &mockExecution.Chain{}, - Eth1InfoFetcher: &mockExecution.Chain{}, - Eth1BlockFetcher: &mockExecution.Chain{}, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), - SyncCommitteePool: synccommittee.NewStore(), - } - - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) - require.NoError(t, err) - - graffiti := bytesutil.ToBytes32([]byte("eth2")) - require.NoError(t, err) - req := ðpb.BlockRequest{ - Slot: altairSlot + 1, - RandaoReveal: randaoReveal, - Graffiti: graffiti[:], - } - - proposerSlashings := make([]*ethpb.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) - for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { - proposerSlashing, err := util.GenerateProposerSlashingForValidator( - beaconState, - privKeys[i], - i, /* validator index */ - ) - require.NoError(t, err) - proposerSlashings[i] = proposerSlashing - err = proposerServer.SlashingsPool.InsertProposerSlashing(context.Background(), beaconState, proposerSlashing) - require.NoError(t, err) - } - - attSlashings := make([]*ethpb.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) - for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { - attesterSlashing, err := util.GenerateAttesterSlashingForValidator( - beaconState, - privKeys[i+params.BeaconConfig().MaxProposerSlashings], - types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings), /* validator index */ - ) - require.NoError(t, err) - attSlashings[i] = attesterSlashing - err = proposerServer.SlashingsPool.InsertAttesterSlashing(context.Background(), beaconState, attesterSlashing) - require.NoError(t, err) - } - block, err := proposerServer.GetBeaconBlock(ctx, req) - require.NoError(t, err) - altairBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Altair) - require.Equal(t, true, ok) - - assert.Equal(t, req.Slot, altairBlk.Altair.Slot) - assert.DeepEqual(t, parentRoot[:], altairBlk.Altair.ParentRoot, "Expected block to have correct parent root") - assert.DeepEqual(t, randaoReveal, altairBlk.Altair.Body.RandaoReveal, "Expected block to have correct randao reveal") - assert.DeepEqual(t, req.Graffiti, altairBlk.Altair.Body.Graffiti, "Expected block to have correct Graffiti") - assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(altairBlk.Altair.Body.ProposerSlashings))) - assert.DeepEqual(t, proposerSlashings, altairBlk.Altair.Body.ProposerSlashings) - assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(altairBlk.Altair.Body.AttesterSlashings))) - assert.DeepEqual(t, attSlashings, altairBlk.Altair.Body.AttesterSlashings) -} - -func TestProposer_GetBeaconBlock_BellatrixEpoch(t *testing.T) { - db := dbutil.SetupDB(t) - ctx := context.Background() - hook := logTest.NewGlobal() - - terminalBlockHash := bytesutil.PadTo([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 32) - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig().Copy() - cfg.BellatrixForkEpoch = 2 - cfg.AltairForkEpoch = 1 - cfg.TerminalBlockHash = common.BytesToHash(terminalBlockHash) - cfg.TerminalBlockHashActivationEpoch = 2 - params.OverrideBeaconConfig(cfg) - beaconState, privKeys := util.DeterministicGenesisState(t, 64) - - stateRoot, err := beaconState.HashTreeRoot(ctx) - require.NoError(t, err, "Could not hash genesis state") - - genesis := b.NewGenesisBlock(stateRoot[:]) - util.SaveBlock(t, ctx, db, genesis) - - parentRoot, err := genesis.Block.HashTreeRoot() - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - - bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) - require.NoError(t, err) - - var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte - blk := ðpb.SignedBeaconBlockBellatrix{ - Block: ðpb.BeaconBlockBellatrix{ - Slot: bellatrixSlot + 1, - ParentRoot: parentRoot[:], - StateRoot: genesis.Block.StateRoot, - Body: ðpb.BeaconBlockBodyBellatrix{ - RandaoReveal: genesis.Block.Body.RandaoReveal, - Graffiti: genesis.Block.Body.Graffiti, - Eth1Data: genesis.Block.Body.Eth1Data, - SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, - ExecutionPayload: &enginev1.ExecutionPayload{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - }, - }, - }, - Signature: genesis.Signature, - } - - blkRoot, err := blk.Block.HashTreeRoot() - require.NoError(t, err) - require.NoError(t, err, "Could not get signing root") - require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") - require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") - - c := mockExecution.New() - c.HashesByHeight[0] = terminalBlockHash - random, err := helpers.RandaoMix(beaconState, slots.ToEpoch(beaconState.Slot())) - require.NoError(t, err) - timeStamp, err := slots.ToTime(beaconState.GenesisTime(), bellatrixSlot+1) - require.NoError(t, err) - - payload := &enginev1.ExecutionPayload{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: random, - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - Transactions: make([][]byte, 0), - ExtraData: make([]byte, 0), - BlockNumber: 1, - GasLimit: 2, - GasUsed: 3, - Timestamp: uint64(timeStamp.Unix()), - } - proposerServer := &Server{ - HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:], Optimistic: false}, - TimeFetcher: &mock.ChainService{Genesis: time.Now()}, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: &mock.ChainService{}, - HeadUpdater: &mock.ChainService{}, - ChainStartFetcher: &mockExecution.Chain{}, - Eth1InfoFetcher: &mockExecution.Chain{}, - Eth1BlockFetcher: c, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), - SyncCommitteePool: synccommittee.NewStore(), - ExecutionEngineCaller: &mockExecution.EngineClient{ - PayloadIDBytes: &enginev1.PayloadIDBytes{1}, - ExecutionPayload: payload, - }, - BeaconDB: db, - ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), - } - - randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) - require.NoError(t, err) - - graffiti := bytesutil.ToBytes32([]byte("eth2")) - require.NoError(t, err) - req := ðpb.BlockRequest{ - Slot: bellatrixSlot + 1, - RandaoReveal: randaoReveal, - Graffiti: graffiti[:], - } - - block, err := proposerServer.GetBeaconBlock(ctx, req) - require.NoError(t, err) - bellatrixBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Bellatrix) - require.Equal(t, true, ok) - - assert.Equal(t, req.Slot, bellatrixBlk.Bellatrix.Slot) - assert.DeepEqual(t, parentRoot[:], bellatrixBlk.Bellatrix.ParentRoot, "Expected block to have correct parent root") - assert.DeepEqual(t, randaoReveal, bellatrixBlk.Bellatrix.Body.RandaoReveal, "Expected block to have correct randao reveal") - assert.DeepEqual(t, req.Graffiti, bellatrixBlk.Bellatrix.Body.Graffiti, "Expected block to have correct Graffiti") - - require.LogsContain(t, hook, "Fee recipient is currently using the burn address") - require.DeepEqual(t, payload, bellatrixBlk.Bellatrix.Body.ExecutionPayload) // Payload should equal. - - // Operator sets default fee recipient to not be burned through beacon node cli. - newHook := logTest.NewGlobal() - params.SetupTestConfigCleanup(t) - cfg = params.MinimalSpecConfig().Copy() - cfg.DefaultFeeRecipient = common.Address{'b'} - params.OverrideBeaconConfig(cfg) - _, err = proposerServer.GetBeaconBlock(ctx, req) - require.NoError(t, err) - require.LogsDoNotContain(t, newHook, "Fee recipient is currently using the burn address") -} - -func TestProposer_GetBeaconBlock_Optimistic(t *testing.T) { - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig().Copy() - cfg.BellatrixForkEpoch = 2 - cfg.AltairForkEpoch = 1 - params.OverrideBeaconConfig(cfg) - - bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) - require.NoError(t, err) - - proposerServer := &Server{OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, TimeFetcher: &mock.ChainService{}} - req := ðpb.BlockRequest{ - Slot: bellatrixSlot + 1, - } - _, err = proposerServer.GetBeaconBlock(context.Background(), req) - s, ok := status.FromError(err) - require.Equal(t, true, ok) - require.DeepEqual(t, codes.Unavailable, s.Code()) - require.ErrorContains(t, errOptimisticMode.Error(), err) -} - func TestProposer_GetSyncAggregate_OK(t *testing.T) { proposerServer := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, From 2851145713cd4e64567c68dd018b1a5c146bf2f3 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 30 Dec 2022 14:08:01 -0800 Subject: [PATCH 07/30] Add back tests --- .../rpc/eth/beacon/sync_committee_test.go | 2 +- .../rpc/prysm/v1alpha1/validator/BUILD.bazel | 2 +- .../prysm/v1alpha1/validator/proposer_test.go | 343 ++++++++++++++++++ 3 files changed, 345 insertions(+), 2 deletions(-) diff --git a/beacon-chain/rpc/eth/beacon/sync_committee_test.go b/beacon-chain/rpc/eth/beacon/sync_committee_test.go index c1cbb9d63c38..088f4bfb359d 100644 --- a/beacon-chain/rpc/eth/beacon/sync_committee_test.go +++ b/beacon-chain/rpc/eth/beacon/sync_committee_test.go @@ -164,7 +164,7 @@ func TestListSyncCommittees(t *testing.T) { chainService := &mock.ChainService{} s := &Server{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ - Genesis: time.Now(), + Genesis: time.Now(),`` }, StateFetcher: &testutil.MockFetcher{ BeaconState: st, diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index bd4439b1e15d..5c478bed8475 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -43,7 +43,6 @@ go_library( "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/core/transition/interop:go_default_library", "//beacon-chain/core/validators:go_default_library", "//beacon-chain/db:go_default_library", "//beacon-chain/db/kv:go_default_library", @@ -219,6 +218,7 @@ go_test( "//beacon-chain/operations/synccommittee:go_default_library", "//beacon-chain/operations/voluntaryexits:go_default_library", "//beacon-chain/p2p/testing:go_default_library", + "//beacon-chain/rpc/testutil:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stategen:go_default_library", diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index bd8815fef79b..d939eb7d39e5 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -4,6 +4,7 @@ import ( "context" "math/big" "testing" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -12,17 +13,23 @@ import ( mock "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder" builderTest "github.com/prysmaticlabs/prysm/v3/beacon-chain/builder/testing" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v3/beacon-chain/cache/depositcache" b "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing" coretime "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/db" dbutil "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/testing" mockExecution "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing" doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits" mockp2p "github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p/testing" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/testutil" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stategen" mockSync "github.com/prysmaticlabs/prysm/v3/beacon-chain/sync/initial-sync/testing" @@ -33,16 +40,352 @@ import ( "github.com/prysmaticlabs/prysm/v3/container/trie" "github.com/prysmaticlabs/prysm/v3/crypto/bls" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation" attaggregation "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation/aggregation/attestations" "github.com/prysmaticlabs/prysm/v3/testing/assert" "github.com/prysmaticlabs/prysm/v3/testing/require" "github.com/prysmaticlabs/prysm/v3/testing/util" + "github.com/prysmaticlabs/prysm/v3/time/slots" logTest "github.com/sirupsen/logrus/hooks/test" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) +func TestServer_GetBeaconBlock_Phase0(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + beaconState, privKeys := util.DeterministicGenesisState(t, 64) + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + genesis := b.NewGenesisBlock(stateRoot[:]) + genBlk := ðpb.SignedBeaconBlock{ + Block: ðpb.BeaconBlock{ + Slot: genesis.Block.Slot, + ParentRoot: genesis.Block.ParentRoot, + StateRoot: genesis.Block.StateRoot, + Body: ðpb.BeaconBlockBody{ + RandaoReveal: genesis.Block.Body.RandaoReveal, + Graffiti: genesis.Block.Body.Graffiti, + Eth1Data: genesis.Block.Body.Eth1Data, + }, + }, + Signature: genesis.Signature, + } + util.SaveBlock(t, ctx, db, genBlk) + + parentRoot, err := genBlk.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + + randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + require.NoError(t, err) + + graffiti := bytesutil.ToBytes32([]byte("eth2")) + req := ðpb.BlockRequest{ + Slot: 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + proposerSlashings, attSlashings := injectSlashings(t, beaconState, privKeys, proposerServer) + + block, err := proposerServer.GetBeaconBlock(ctx, req) + require.NoError(t, err) + phase0Blk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Phase0) + require.Equal(t, true, ok) + assert.Equal(t, req.Slot, phase0Blk.Phase0.Slot) + assert.DeepEqual(t, parentRoot[:], phase0Blk.Phase0.ParentRoot, "Expected block to have correct parent root") + assert.DeepEqual(t, randaoReveal, phase0Blk.Phase0.Body.RandaoReveal, "Expected block to have correct randao reveal") + assert.DeepEqual(t, req.Graffiti, phase0Blk.Phase0.Body.Graffiti, "Expected block to have correct Graffiti") + assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(phase0Blk.Phase0.Body.ProposerSlashings))) + assert.DeepEqual(t, proposerSlashings, phase0Blk.Phase0.Body.ProposerSlashings) + assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(phase0Blk.Phase0.Body.AttesterSlashings))) + assert.DeepEqual(t, attSlashings, phase0Blk.Phase0.Body.AttesterSlashings) +} + +func TestServer_GetBeaconBlock_Altair(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.AltairForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + beaconState, privKeys := util.DeterministicGenesisState(t, 64) + + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + genesis := b.NewGenesisBlock(stateRoot[:]) + util.SaveBlock(t, ctx, db, genesis) + + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + altairSlot, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch) + require.NoError(t, err) + + var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte + genAltair := ðpb.SignedBeaconBlockAltair{ + Block: ðpb.BeaconBlockAltair{ + Slot: altairSlot + 1, + ParentRoot: parentRoot[:], + StateRoot: genesis.Block.StateRoot, + Body: ðpb.BeaconBlockBodyAltair{ + RandaoReveal: genesis.Block.Body.RandaoReveal, + Graffiti: genesis.Block.Body.Graffiti, + Eth1Data: genesis.Block.Body.Eth1Data, + SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, + }, + }, + Signature: genesis.Signature, + } + + blkRoot, err := genAltair.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") + + proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + + randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + require.NoError(t, err) + + graffiti := bytesutil.ToBytes32([]byte("eth2")) + require.NoError(t, err) + req := ðpb.BlockRequest{ + Slot: altairSlot + 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + proposerSlashings, attSlashings := injectSlashings(t, beaconState, privKeys, proposerServer) + + block, err := proposerServer.GetBeaconBlock(ctx, req) + require.NoError(t, err) + altairBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Altair) + require.Equal(t, true, ok) + + assert.Equal(t, req.Slot, altairBlk.Altair.Slot) + assert.DeepEqual(t, parentRoot[:], altairBlk.Altair.ParentRoot, "Expected block to have correct parent root") + assert.DeepEqual(t, randaoReveal, altairBlk.Altair.Body.RandaoReveal, "Expected block to have correct randao reveal") + assert.DeepEqual(t, req.Graffiti, altairBlk.Altair.Body.Graffiti, "Expected block to have correct Graffiti") + assert.Equal(t, params.BeaconConfig().MaxProposerSlashings, uint64(len(altairBlk.Altair.Body.ProposerSlashings))) + assert.DeepEqual(t, proposerSlashings, altairBlk.Altair.Body.ProposerSlashings) + assert.Equal(t, params.BeaconConfig().MaxAttesterSlashings, uint64(len(altairBlk.Altair.Body.AttesterSlashings))) + assert.DeepEqual(t, attSlashings, altairBlk.Altair.Body.AttesterSlashings) +} + +func TestServer_GetBeaconBlock_Bellatrix(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + hook := logTest.NewGlobal() + + terminalBlockHash := bytesutil.PadTo([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 32) + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.BellatrixForkEpoch = 2 + cfg.AltairForkEpoch = 1 + cfg.TerminalBlockHash = common.BytesToHash(terminalBlockHash) + cfg.TerminalBlockHashActivationEpoch = 2 + params.OverrideBeaconConfig(cfg) + beaconState, privKeys := util.DeterministicGenesisState(t, 64) + + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + genesis := b.NewGenesisBlock(stateRoot[:]) + util.SaveBlock(t, ctx, db, genesis) + + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) + require.NoError(t, err) + + var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte + blk := ðpb.SignedBeaconBlockBellatrix{ + Block: ðpb.BeaconBlockBellatrix{ + Slot: bellatrixSlot + 1, + ParentRoot: parentRoot[:], + StateRoot: genesis.Block.StateRoot, + Body: ðpb.BeaconBlockBodyBellatrix{ + RandaoReveal: genesis.Block.Body.RandaoReveal, + Graffiti: genesis.Block.Body.Graffiti, + Eth1Data: genesis.Block.Body.Eth1Data, + SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, + ExecutionPayload: &enginev1.ExecutionPayload{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + }, + }, + Signature: genesis.Signature, + } + + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") + + c := mockExecution.New() + c.HashesByHeight[0] = terminalBlockHash + random, err := helpers.RandaoMix(beaconState, slots.ToEpoch(beaconState.Slot())) + require.NoError(t, err) + timeStamp, err := slots.ToTime(beaconState.GenesisTime(), bellatrixSlot+1) + require.NoError(t, err) + + payload := &enginev1.ExecutionPayload{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: random, + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + Transactions: make([][]byte, 0), + ExtraData: make([]byte, 0), + BlockNumber: 1, + GasLimit: 2, + GasUsed: 3, + Timestamp: uint64(timeStamp.Unix()), + } + + proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + proposerServer.Eth1BlockFetcher = c + proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{ + PayloadIDBytes: &enginev1.PayloadIDBytes{1}, + ExecutionPayload: payload, + } + + randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + require.NoError(t, err) + + graffiti := bytesutil.ToBytes32([]byte("eth2")) + require.NoError(t, err) + req := ðpb.BlockRequest{ + Slot: bellatrixSlot + 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + + block, err := proposerServer.GetBeaconBlock(ctx, req) + require.NoError(t, err) + bellatrixBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Bellatrix) + require.Equal(t, true, ok) + + assert.Equal(t, req.Slot, bellatrixBlk.Bellatrix.Slot) + assert.DeepEqual(t, parentRoot[:], bellatrixBlk.Bellatrix.ParentRoot, "Expected block to have correct parent root") + assert.DeepEqual(t, randaoReveal, bellatrixBlk.Bellatrix.Body.RandaoReveal, "Expected block to have correct randao reveal") + assert.DeepEqual(t, req.Graffiti, bellatrixBlk.Bellatrix.Body.Graffiti, "Expected block to have correct Graffiti") + + require.LogsContain(t, hook, "Fee recipient is currently using the burn address") + require.DeepEqual(t, payload, bellatrixBlk.Bellatrix.Body.ExecutionPayload) // Payload should equal. + + // Operator sets default fee recipient to not be burned through beacon node cli. + newHook := logTest.NewGlobal() + params.SetupTestConfigCleanup(t) + cfg = params.MinimalSpecConfig().Copy() + cfg.DefaultFeeRecipient = common.Address{'b'} + params.OverrideBeaconConfig(cfg) + _, err = proposerServer.GetBeaconBlock(ctx, req) + require.NoError(t, err) + require.LogsDoNotContain(t, newHook, "Fee recipient is currently using the burn address") +} + +func TestServer_GetBeaconBlock_Optimistic(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.BellatrixForkEpoch = 2 + cfg.AltairForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + + bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) + require.NoError(t, err) + + proposerServer := &Server{ + OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, + SyncChecker: &mockSync.Sync{}, + TimeFetcher: &mock.ChainService{}} + req := ðpb.BlockRequest{ + Slot: bellatrixSlot + 1, + } + _, err = proposerServer.GetBeaconBlock(context.Background(), req) + s, ok := status.FromError(err) + require.Equal(t, true, ok) + require.DeepEqual(t, codes.Unavailable, s.Code()) + require.ErrorContains(t, errOptimisticMode.Error(), err) +} + +func getProposerServer(db db.HeadAccessDatabase, headState state.BeaconState, headRoot []byte) *Server { + return &Server{ + HeadFetcher: &mock.ChainService{State: headState, Root: headRoot}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: &mock.ChainService{}, + HeadUpdater: &mock.ChainService{}, + ChainStartFetcher: &mockExecution.Chain{}, + Eth1InfoFetcher: &mockExecution.Chain{}, + Eth1BlockFetcher: &mockExecution.Chain{}, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db, doublylinkedtree.New()), + SyncCommitteePool: synccommittee.NewStore(), + OptimisticModeFetcher: &mock.ChainService{}, + TimeFetcher: &testutil.MockGenesisTimeFetcher{ + Genesis: time.Now(), + }, + ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), + BeaconDB: db, + } +} + +func injectSlashings(t *testing.T, st state.BeaconState, keys []bls.SecretKey, server *Server) ([]*ethpb.ProposerSlashing, []*ethpb.AttesterSlashing) { + proposerSlashings := make([]*ethpb.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) + for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxProposerSlashings; i++ { + proposerSlashing, err := util.GenerateProposerSlashingForValidator(st, keys[i], i /* validator index */) + require.NoError(t, err) + proposerSlashings[i] = proposerSlashing + err = server.SlashingsPool.InsertProposerSlashing(context.Background(), st, proposerSlashing) + require.NoError(t, err) + } + + attSlashings := make([]*ethpb.AttesterSlashing, params.BeaconConfig().MaxAttesterSlashings) + for i := uint64(0); i < params.BeaconConfig().MaxAttesterSlashings; i++ { + attesterSlashing, err := util.GenerateAttesterSlashingForValidator(st, keys[i+params.BeaconConfig().MaxProposerSlashings], types.ValidatorIndex(i+params.BeaconConfig().MaxProposerSlashings) /* validator index */) + require.NoError(t, err) + attSlashings[i] = attesterSlashing + err = server.SlashingsPool.InsertAttesterSlashing(context.Background(), st, attesterSlashing) + require.NoError(t, err) + } + return proposerSlashings, attSlashings +} + func TestProposer_ProposeBlock_OK(t *testing.T) { tests := []struct { name string From 9a0aa6e8e6bc0e65b433e2822aed84c7d942eccd Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 30 Dec 2022 14:32:03 -0800 Subject: [PATCH 08/30] Fix more tests --- .../rpc/eth/validator/validator_test.go | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/beacon-chain/rpc/eth/validator/validator_test.go b/beacon-chain/rpc/eth/validator/validator_test.go index 694442f7aa2b..5da1a34a8fbc 100644 --- a/beacon-chain/rpc/eth/validator/validator_test.go +++ b/beacon-chain/rpc/eth/validator/validator_test.go @@ -689,18 +689,20 @@ func TestProduceBlockV2(t *testing.T) { mockChainService := &mockChain.ChainService{State: beaconState, Root: parentRoot[:]} mockExecutionChain := &mockExecution.Chain{} v1Alpha1Server := &v1alpha1validator.Server{ - HeadFetcher: mockChainService, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: mockChainService, - HeadUpdater: mockChainService, - ChainStartFetcher: mockExecutionChain, - Eth1InfoFetcher: mockExecutionChain, - Eth1BlockFetcher: mockExecutionChain, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), + HeadFetcher: mockChainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: mockChainService, + HeadUpdater: mockChainService, + ChainStartFetcher: mockExecutionChain, + Eth1InfoFetcher: mockExecutionChain, + Eth1BlockFetcher: mockExecutionChain, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db, doublylinkedtree.New()), + TimeFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, } proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) @@ -797,19 +799,21 @@ func TestProduceBlockV2(t *testing.T) { mochChainService := &mockChain.ChainService{State: beaconState, Root: parentRoot[:]} mockExecutionChain := &mockExecution.Chain{} v1Alpha1Server := &v1alpha1validator.Server{ - HeadFetcher: mochChainService, - SyncChecker: &mockSync.Sync{IsSyncing: false}, - BlockReceiver: mochChainService, - HeadUpdater: mochChainService, - ChainStartFetcher: mockExecutionChain, - Eth1InfoFetcher: mockExecutionChain, - Eth1BlockFetcher: mockExecutionChain, - MockEth1Votes: true, - AttPool: attestations.NewPool(), - SlashingsPool: slashings.NewPool(), - ExitPool: voluntaryexits.NewPool(), - StateGen: stategen.New(db, doublylinkedtree.New()), - SyncCommitteePool: synccommittee.NewStore(), + HeadFetcher: mochChainService, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + BlockReceiver: mochChainService, + HeadUpdater: mochChainService, + ChainStartFetcher: mockExecutionChain, + Eth1InfoFetcher: mockExecutionChain, + Eth1BlockFetcher: mockExecutionChain, + MockEth1Votes: true, + AttPool: attestations.NewPool(), + SlashingsPool: slashings.NewPool(), + ExitPool: voluntaryexits.NewPool(), + StateGen: stategen.New(db, doublylinkedtree.New()), + SyncCommitteePool: synccommittee.NewStore(), + TimeFetcher: mochChainService, + OptimisticModeFetcher: mochChainService, } proposerSlashings := make([]*ethpbalpha.ProposerSlashing, params.BeaconConfig().MaxProposerSlashings) From e298d35194ef052983445515c9d99dcb0e32cf4a Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 30 Dec 2022 14:33:14 -0800 Subject: [PATCH 09/30] Gazelle --- beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel | 2 ++ 1 file changed, 2 insertions(+) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 5c478bed8475..b2708ad677ba 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -163,6 +163,7 @@ common_deps = [ "@org_golang_google_protobuf//types/known/emptypb:go_default_library", ] +# gazelle:ignore go_test( name = "go_default_test", timeout = "moderate", @@ -210,6 +211,7 @@ go_test( "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/transition:go_default_library", + "//beacon-chain/db:go_default_library", "//beacon-chain/db/testing:go_default_library", "//beacon-chain/execution/testing:go_default_library", "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", From 144b800f85ff504dea74ec2624156841e27737f4 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 4 Jan 2023 14:03:50 -0800 Subject: [PATCH 10/30] Add capella test --- beacon-chain/execution/testing/BUILD.bazel | 1 + .../execution/testing/mock_engine_client.go | 7 +- .../rpc/prysm/v1alpha1/validator/BUILD.bazel | 68 +---------- .../prysm/v1alpha1/validator/proposer_test.go | 112 ++++++++++++++++++ 4 files changed, 120 insertions(+), 68 deletions(-) diff --git a/beacon-chain/execution/testing/BUILD.bazel b/beacon-chain/execution/testing/BUILD.bazel index a6a0f93adfd4..9bfca3034d97 100644 --- a/beacon-chain/execution/testing/BUILD.bazel +++ b/beacon-chain/execution/testing/BUILD.bazel @@ -26,6 +26,7 @@ go_library( "//encoding/bytesutil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", diff --git a/beacon-chain/execution/testing/mock_engine_client.go b/beacon-chain/execution/testing/mock_engine_client.go index 7b99a22fe56f..594398b0a374 100644 --- a/beacon-chain/execution/testing/mock_engine_client.go +++ b/beacon-chain/execution/testing/mock_engine_client.go @@ -15,6 +15,7 @@ import ( types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" + "github.com/prysmaticlabs/prysm/v3/time/slots" ) // EngineClient -- @@ -23,6 +24,7 @@ type EngineClient struct { PayloadIDBytes *pb.PayloadIDBytes ForkChoiceUpdatedResp []byte ExecutionPayload *pb.ExecutionPayload + ExecutionPayloadCapella *pb.ExecutionPayloadCapella ExecutionBlock *pb.ExecutionBlock Err error ErrLatestExecBlock error @@ -54,7 +56,10 @@ func (e *EngineClient) ForkchoiceUpdated( } // GetPayload -- -func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, _ types.Slot) (interfaces.ExecutionData, error) { +func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, s types.Slot) (interfaces.ExecutionData, error) { + if slots.ToEpoch(s) >= params.BeaconConfig().CapellaForkEpoch { + return blocks.WrappedExecutionPayloadCapella(e.ExecutionPayloadCapella) + } p, err := blocks.WrappedExecutionPayload(e.ExecutionPayload) if err != nil { return nil, err diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 28fba87879bd..d64f7135798a 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -19,7 +19,6 @@ go_library( "proposer_eth1data.go", "proposer_execution_payload.go", "proposer_exits.go", - "proposer_phase0.go", "proposer_slashings.go", "proposer_sync_aggregate.go", "server.go", @@ -194,72 +193,7 @@ go_test( embed = [":go_default_library"], eth_network = "minimal", tags = ["minimal"], - deps = [ - "//async/event:go_default_library", - "//beacon-chain/blockchain/testing:go_default_library", - "//beacon-chain/builder:go_default_library", - "//beacon-chain/builder/testing:go_default_library", - "//beacon-chain/cache:go_default_library", - "//beacon-chain/cache/depositcache:go_default_library", - "//beacon-chain/core/altair:go_default_library", - "//beacon-chain/core/blocks:go_default_library", - "//beacon-chain/core/execution:go_default_library", - "//beacon-chain/core/feed:go_default_library", - "//beacon-chain/core/feed/block:go_default_library", - "//beacon-chain/core/feed/operation:go_default_library", - "//beacon-chain/core/feed/state:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/signing:go_default_library", - "//beacon-chain/core/time:go_default_library", - "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/db:go_default_library", - "//beacon-chain/db/testing:go_default_library", - "//beacon-chain/execution/testing:go_default_library", - "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", - "//beacon-chain/operations/attestations:go_default_library", - "//beacon-chain/operations/slashings:go_default_library", - "//beacon-chain/operations/synccommittee:go_default_library", - "//beacon-chain/operations/voluntaryexits:go_default_library", - "//beacon-chain/p2p/testing:go_default_library", - "//beacon-chain/rpc/testutil:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/state-native:go_default_library", - "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/state/stategen/mock:go_default_library", - "//beacon-chain/sync/initial-sync/testing:go_default_library", - "//config/fieldparams:go_default_library", - "//config/params:go_default_library", - "//consensus-types/blocks:go_default_library", - "//consensus-types/interfaces:go_default_library", - "//consensus-types/primitives:go_default_library", - "//container/trie:go_default_library", - "//crypto/bls:go_default_library", - "//encoding/bytesutil:go_default_library", - "//encoding/ssz:go_default_library", - "//proto/engine/v1:go_default_library", - "//proto/eth/v1:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//proto/prysm/v1alpha1/attestation:go_default_library", - "//testing/assert:go_default_library", - "//testing/mock:go_default_library", - "//testing/require:go_default_library", - "//testing/util:go_default_library", - "//time:go_default_library", - "//time/slots:go_default_library", - "@com_github_d4l3k_messagediff//: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//core/types:go_default_library", - "@com_github_golang_mock//gomock:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", - "@com_github_sirupsen_logrus//hooks/test:go_default_library", - "@org_golang_google_grpc//codes:go_default_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", - ], + deps = common_deps, ) go_test( diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index d939eb7d39e5..52746b56ab42 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -19,11 +19,13 @@ import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing" coretime "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v3/beacon-chain/db" dbutil "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/testing" mockExecution "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing" doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee" "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits" @@ -317,6 +319,115 @@ func TestServer_GetBeaconBlock_Bellatrix(t *testing.T) { require.LogsDoNotContain(t, newHook, "Fee recipient is currently using the burn address") } +func TestServer_GetBeaconBlock_Capella(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.CapellaForkEpoch = 3 + cfg.BellatrixForkEpoch = 2 + cfg.AltairForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + beaconState, privKeys := util.DeterministicGenesisState(t, 64) + + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + genesis := b.NewGenesisBlock(stateRoot[:]) + util.SaveBlock(t, ctx, db, genesis) + + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + capellaSlot, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch) + require.NoError(t, err) + + var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte + blk := ðpb.SignedBeaconBlockCapella{ + Block: ðpb.BeaconBlockCapella{ + Slot: capellaSlot + 1, + ParentRoot: parentRoot[:], + StateRoot: genesis.Block.StateRoot, + Body: ðpb.BeaconBlockBodyCapella{ + RandaoReveal: genesis.Block.Body.RandaoReveal, + Graffiti: genesis.Block.Body.Graffiti, + Eth1Data: genesis.Block.Body.Eth1Data, + SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, + ExecutionPayload: &enginev1.ExecutionPayloadCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + }, + }, + Signature: genesis.Signature, + } + + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") + + random, err := helpers.RandaoMix(beaconState, slots.ToEpoch(beaconState.Slot())) + require.NoError(t, err) + timeStamp, err := slots.ToTime(beaconState.GenesisTime(), capellaSlot+1) + require.NoError(t, err) + payload := &enginev1.ExecutionPayloadCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: random, + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + Transactions: make([][]byte, 0), + ExtraData: make([]byte, 0), + BlockNumber: 1, + GasLimit: 2, + GasUsed: 3, + Timestamp: uint64(timeStamp.Unix()), + } + + proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{ + PayloadIDBytes: &enginev1.PayloadIDBytes{1}, + ExecutionPayloadCapella: payload, + } + + randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + require.NoError(t, err) + + graffiti := bytesutil.ToBytes32([]byte("eth2")) + require.NoError(t, err) + req := ðpb.BlockRequest{ + Slot: capellaSlot + 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + + copiedState := beaconState.Copy() + copiedState, err = transition.ProcessSlots(ctx, copiedState, capellaSlot+1) + require.NoError(t, err) + change, err := util.GenerateBLSToExecutionChange(copiedState, privKeys[1], 0) + require.NoError(t, err) + proposerServer.BLSChangesPool.InsertBLSToExecChange(change) + + got, err := proposerServer.GetBeaconBlock(ctx, req) + require.NoError(t, err) + require.Equal(t, 1, len(got.GetCapella().Body.BlsToExecutionChanges)) + require.DeepEqual(t, change, got.GetCapella().Body.BlsToExecutionChanges[0]) +} + func TestServer_GetBeaconBlock_Optimistic(t *testing.T) { params.SetupTestConfigCleanup(t) cfg := params.BeaconConfig().Copy() @@ -362,6 +473,7 @@ func getProposerServer(db db.HeadAccessDatabase, headState state.BeaconState, he }, ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), BeaconDB: db, + BLSChangesPool: blstoexec.NewPool(), } } From a29bef8cd422aa03999be647b246e8b2a825c1a0 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 4 Jan 2023 14:10:59 -0800 Subject: [PATCH 11/30] Use metric --- beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go | 1 + 1 file changed, 1 insertion(+) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 2fe7e7a3f105..182d49ffa5b1 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -138,6 +138,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } else if canUseBuilder { h, err := vs.getPayloadHeaderFromBuilder(ctx, req.Slot, idx) if err != nil { + builderGetPayloadMissCount.Inc() log.WithError(err).Warn("Proposer: failed to get payload header from builder") } else { blk.SetBlinded(true) From a1e86bf63813eea61ca90fd108eff98d09822314 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 4 Jan 2023 14:12:57 -0800 Subject: [PATCH 12/30] Use timeout --- .../rpc/prysm/v1alpha1/validator/proposer_bellatrix.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index dfc043f574c4..19967f2d0c36 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -53,6 +53,10 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Sl if err != nil { return nil, err } + + ctx, cancel := context.WithTimeout(ctx, blockBuilderTimeout) + defer cancel() + bid, err := vs.BlockBuilder.GetHeader(ctx, slot, bytesutil.ToBytes32(h.BlockHash()), pk) if err != nil { return nil, err @@ -214,7 +218,7 @@ func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.SignedBe func validateBuilderSignature(bid *ethpb.SignedBuilderBid) error { d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder, nil, /* fork version */ - nil /* genesis val root */) + nil /* genesis val root */) if err != nil { return err } From 2e038fae55fc1a347b7a879ab95e642c02e4c7fd Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 4 Jan 2023 14:17:46 -0800 Subject: [PATCH 13/30] Go fmt --- beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index 19967f2d0c36..21571bfd282b 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -218,7 +218,7 @@ func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.SignedBe func validateBuilderSignature(bid *ethpb.SignedBuilderBid) error { d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder, nil, /* fork version */ - nil /* genesis val root */) + nil /* genesis val root */) if err != nil { return err } From 933e920f4c79b714dc0c91634f6987701fa1ad34 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 4 Jan 2023 14:51:49 -0800 Subject: [PATCH 14/30] Disable transition cache --- beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel | 1 + beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index d64f7135798a..88695a2940c4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -124,6 +124,7 @@ common_deps = [ "//beacon-chain/operations/synccommittee:go_default_library", "//beacon-chain/operations/voluntaryexits:go_default_library", "//beacon-chain/p2p/testing:go_default_library", + "//beacon-chain/rpc/testutil:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stategen:go_default_library", diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index 52746b56ab42..f82e46bab8a2 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -322,6 +322,7 @@ func TestServer_GetBeaconBlock_Bellatrix(t *testing.T) { func TestServer_GetBeaconBlock_Capella(t *testing.T) { db := dbutil.SetupDB(t) ctx := context.Background() + transition.SkipSlotCache.Disable() params.SetupTestConfigCleanup(t) cfg := params.BeaconConfig().Copy() From c84b525a81d13805364e47abc33c621dc2aad20d Mon Sep 17 00:00:00 2001 From: terence tsao Date: Thu, 5 Jan 2023 07:18:45 -0800 Subject: [PATCH 15/30] Refactor fork based helpers --- .../rpc/prysm/v1alpha1/validator/BUILD.bazel | 1 + .../rpc/prysm/v1alpha1/validator/proposer.go | 69 +++---------------- .../v1alpha1/validator/proposer_altair.go | 26 +++++++ .../v1alpha1/validator/proposer_bellatrix.go | 33 +++++++++ .../v1alpha1/validator/proposer_capella.go | 25 +++++++ 5 files changed, 95 insertions(+), 59 deletions(-) create mode 100644 beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 88695a2940c4..b335b3d3dd8f 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "proposer_attestations.go", "proposer_bellatrix.go", "proposer_builder.go", + "proposer_capella.go", "proposer_deposits.go", "proposer_empty_block.go", "proposer_eth1data.go", diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 182d49ffa5b1..fbba90a00a97 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -17,7 +17,6 @@ import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv" - fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" @@ -96,80 +95,32 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } } - // Set proposer index + // Set proposer index. idx, err := helpers.BeaconProposerIndex(ctx, head) if err != nil { return nil, fmt.Errorf("could not calculate proposer index %v", err) } blk.SetProposerIndex(idx) - // Set slashings + // Set slashings. validProposerSlashings, validAttSlashings := vs.getSlashings(ctx, head) blk.Body().SetProposerSlashings(validProposerSlashings) blk.Body().SetAttesterSlashings(validAttSlashings) - // Set exits + // Set exits. blk.Body().SetVoluntaryExits(vs.getExits(head, req.Slot)) // Set sync aggregate. New in Altair. - if req.Slot > 0 && slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch { - syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(parentRoot)) - if err != nil { - log.WithError(err).Error("Could not get sync aggregate") - } else { - if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { - log.WithError(err).Error("Could not set sync aggregate") - if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{ - SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), - SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), - }); err != nil { - return nil, status.Errorf(codes.Internal, "Could not set default sync aggregate: %v", err) - } - } - } - } + vs.setSyncAggregate(ctx, blk) - // Set execution data. New in Bellatrix - if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { - fallBackToLocal := true - canUseBuilder, err := vs.canUseBuilder(ctx, req.Slot, idx) - if err != nil { - log.WithError(err).Warn("Proposer: failed to check if builder can be used") - } else if canUseBuilder { - h, err := vs.getPayloadHeaderFromBuilder(ctx, req.Slot, idx) - if err != nil { - builderGetPayloadMissCount.Inc() - log.WithError(err).Warn("Proposer: failed to get payload header from builder") - } else { - blk.SetBlinded(true) - if err := blk.Body().SetExecution(h); err != nil { - log.WithError(err).Warn("Proposer: failed to set execution payload") - } else { - fallBackToLocal = false - } - } - } - if fallBackToLocal { - executionData, err := vs.getExecutionPayload(ctx, req.Slot, idx, bytesutil.ToBytes32(parentRoot), head) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get execution payload: %v", err) - } - if err := blk.Body().SetExecution(executionData); err != nil { - return nil, status.Errorf(codes.Internal, "Could not set execution payload: %v", err) - } - } + // Set execution data. New in Bellatrix. + if err := vs.setExecutionData(ctx, blk, head); err != nil { + return nil, status.Errorf(codes.Internal, "Could not set execution data: %v", err) } - // Set bls to execution change. New in Capella - if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch { - changes, err := vs.BLSChangesPool.BLSToExecChangesForInclusion(head) - if err != nil { - log.WithError(err).Error("Could not get bls to execution changes") - } else { - if err := blk.Body().SetBLSToExecutionChanges(changes); err != nil { - log.WithError(err).Error("Could not set bls to execution changes") - } - } + // Set bls to execution change. New in Capella. + if err := vs.setBlsToExecData(blk, head); err != nil { + return nil, status.Errorf(codes.Internal, "Could not set bls to execution data: %v", err) } sr, err := vs.computeStateRoot(ctx, sBlk) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index 0c767101c5bb..206145a3edcd 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -3,15 +3,41 @@ package validator import ( "context" + fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v3/crypto/bls" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" synccontribution "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation/aggregation/sync_contribution" + "github.com/prysmaticlabs/prysm/v3/time/slots" "go.opencensus.io/trace" ) +func (vs *Server) setSyncAggregate(ctx context.Context, blk interfaces.BeaconBlock) { + slot := blk.Slot() + if slot == 0 || slots.ToEpoch(slot) < params.BeaconConfig().AltairForkEpoch { + return + } + + syncAggregate, err := vs.getSyncAggregate(ctx, slot-1, blk.ParentRoot()) + if err != nil { + log.WithError(err).Error("Could not get sync aggregate") + } else { + if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { + log.WithError(err).Error("Could not set sync aggregate") + if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }); err != nil { + log.WithError(err).Error("Could not set sync aggregate") + } + } + } + return +} + // getSyncAggregate retrieves the sync contributions from the pool to construct the sync aggregate object. // The contributions are filtered based on matching of the input root and slot then profitability. func (vs *Server) getSyncAggregate(ctx context.Context, slot types.Slot, root [32]byte) (*ethpb.SyncAggregate, error) { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index 21571bfd282b..f0e04ad69a2a 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -11,6 +11,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" "github.com/prysmaticlabs/prysm/v3/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" @@ -34,6 +35,38 @@ var builderGetPayloadMissCount = promauto.NewCounter(prometheus.CounterOpts{ // block request. This value is known as `BUILDER_PROPOSAL_DELAY_TOLERANCE` in builder spec. const blockBuilderTimeout = 1 * time.Second +// Sets the execution data for the block. Execution data can come from local EL client or remote builder depends on validator registration and circuit breaker conditions. +func (vs *Server) setExecutionData(ctx context.Context, blk interfaces.BeaconBlock, headState state.BeaconState) error { + idx := blk.ProposerIndex() + slot := blk.Slot() + if slots.ToEpoch(slot) < params.BeaconConfig().BellatrixForkEpoch { + return nil + } + + canUseBuilder, err := vs.canUseBuilder(ctx, slot, idx) + if err != nil { + log.WithError(err).Warn("Proposer: failed to check if builder can be used") + } else if canUseBuilder { + h, err := vs.getPayloadHeaderFromBuilder(ctx, slot, idx) + if err != nil { + builderGetPayloadMissCount.Inc() + log.WithError(err).Warn("Proposer: failed to get payload header from builder") + } else { + blk.SetBlinded(true) + if err := blk.Body().SetExecution(h); err != nil { + log.WithError(err).Warn("Proposer: failed to set execution payload") + } else { + return nil + } + } + } + executionData, err := vs.getExecutionPayload(ctx, slot, idx, blk.ParentRoot(), headState) + if err != nil { + return errors.Wrap(err, "failed to get execution payload") + } + return blk.Body().SetExecution(executionData) +} + // This function retrieves the payload header given the slot number and the validator index. // It's a no-op if the latest head block is not versioned bellatrix. func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot types.Slot, idx types.ValidatorIndex) (interfaces.ExecutionData, error) { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go new file mode 100644 index 000000000000..6c0960a3e15c --- /dev/null +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go @@ -0,0 +1,25 @@ +package validator + +import ( + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v3/time/slots" +) + +// Sets the bls to exec data for a block. +func (vs *Server) setBlsToExecData(blk interfaces.BeaconBlock, headState state.BeaconState) error { + if slots.ToEpoch(blk.Slot()) < params.BeaconConfig().CapellaForkEpoch { + return nil + } + + changes, err := vs.BLSChangesPool.BLSToExecChangesForInclusion(headState) + if err != nil { + log.WithError(err).Error("Could not get bls to execution changes") + } else { + if err := blk.Body().SetBLSToExecutionChanges(changes); err != nil { + log.WithError(err).Error("Could not set bls to execution changes") + } + } + return nil +} From f380656a6b78b6edfb170aa886249bbc4d6b5150 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Thu, 5 Jan 2023 07:34:01 -0800 Subject: [PATCH 16/30] Fix return --- beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go | 1 - 1 file changed, 1 deletion(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index 206145a3edcd..7e345b3fc1c6 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -35,7 +35,6 @@ func (vs *Server) setSyncAggregate(ctx context.Context, blk interfaces.BeaconBlo } } } - return } // getSyncAggregate retrieves the sync contributions from the pool to construct the sync aggregate object. From 4891145a2309e0bd305393b9897d793088090117 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Thu, 5 Jan 2023 11:00:39 -0800 Subject: [PATCH 17/30] Fix test --- beacon-chain/rpc/eth/validator/validator_test.go | 8 ++++++++ .../rpc/prysm/v1alpha1/validator/proposer.go | 12 ++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/beacon-chain/rpc/eth/validator/validator_test.go b/beacon-chain/rpc/eth/validator/validator_test.go index 5da1a34a8fbc..b20c4e20928b 100644 --- a/beacon-chain/rpc/eth/validator/validator_test.go +++ b/beacon-chain/rpc/eth/validator/validator_test.go @@ -2109,6 +2109,14 @@ func TestProduceBlindedBlock(t *testing.T) { require.NoError(t, err) graffiti := bytesutil.ToBytes32([]byte("eth2")) + copied := beaconState.Copy() + require.NoError(t, copied.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) + idx, err := helpers.BeaconProposerIndex(ctx, copied) + require.NoError(t, err) + require.NoError(t, + db.SaveRegistrationsByValidatorIDs(ctx, []types.ValidatorIndex{idx}, + []*ethpbalpha.ValidatorRegistrationV1{{FeeRecipient: make([]byte, 20), Pubkey: make([]byte, 48)}})) + req := ðpbv1.ProduceBlockRequest{ Slot: params.BeaconConfig().SlotsPerEpoch + 1, RandaoReveal: randaoReveal, diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index fbba90a00a97..1147c1d7f780 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -48,9 +48,11 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( return nil, status.Error(codes.Unavailable, "Syncing to latest head, not ready to respond") } - // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). - if err := vs.optimisticStatus(ctx); err != nil { - return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { + // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). + if err := vs.optimisticStatus(ctx); err != nil { + return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) + } } sBlk, err := getEmptyBlock(req.Slot) @@ -135,8 +137,10 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch { return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}}, nil - } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { + } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch && !blk.IsBlinded() { return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}}, nil + } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch && blk.IsBlinded() { + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: pb.(*ethpb.BlindedBeaconBlockBellatrix)}}, nil } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch { return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: pb.(*ethpb.BeaconBlockAltair)}}, nil } From 4756bbe6b0f15d53734f0708fc54ebd4b95c4e3a Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 6 Jan 2023 07:53:46 -0800 Subject: [PATCH 18/30] Potuz feedback --- .../rpc/prysm/v1alpha1/validator/proposer.go | 9 ++++++--- .../rpc/prysm/v1alpha1/validator/proposer_altair.go | 12 +++++------- .../rpc/prysm/v1alpha1/validator/proposer_capella.go | 12 +++++++++--- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 1147c1d7f780..65489eb5b3c3 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -48,8 +48,8 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( return nil, status.Error(codes.Unavailable, "Syncing to latest head, not ready to respond") } + // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { - // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). if err := vs.optimisticStatus(ctx); err != nil { return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) } @@ -59,7 +59,6 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( if err != nil { return nil, status.Errorf(codes.Internal, "Could not prepare block: %v", err) } - parentRoot, err := vs.HeadFetcher.HeadRoot(ctx) if err != nil { return nil, status.Errorf(codes.Internal, "Could not get head root: %v", err) @@ -83,6 +82,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( // Set eth1 data. eth1Data, err := vs.eth1DataMajorityVote(ctx, head) if err != nil { + blk.Body().SetEth1Data(ðpb.Eth1Data{DepositRoot: params.BeaconConfig().ZeroHash[:], BlockHash: params.BeaconConfig().ZeroHash[:]}) log.WithError(err).Error("Could not get eth1data") } else { blk.Body().SetEth1Data(eth1Data) @@ -90,6 +90,8 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( // Set deposit and attestation. deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits if err != nil { + blk.Body().SetDeposits([]*ethpb.Deposit{}) + blk.Body().SetAttestations([]*ethpb.Attestation{}) log.WithError(err).Error("Could not pack deposits and attestations") } else { blk.Body().SetDeposits(deposits) @@ -122,7 +124,8 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( // Set bls to execution change. New in Capella. if err := vs.setBlsToExecData(blk, head); err != nil { - return nil, status.Errorf(codes.Internal, "Could not set bls to execution data: %v", err) + // Empty bls to exec array is set within `setBlsToExecData`. + log.WithError(err).Error("Could not set bls to execution data") } sr, err := vs.computeStateRoot(ctx, sBlk) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index 7e345b3fc1c6..e0979f1af0f6 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -3,7 +3,6 @@ package validator import ( "context" - fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" @@ -11,25 +10,24 @@ import ( "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" synccontribution "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation/aggregation/sync_contribution" - "github.com/prysmaticlabs/prysm/v3/time/slots" + "github.com/prysmaticlabs/prysm/v3/runtime/version" "go.opencensus.io/trace" ) func (vs *Server) setSyncAggregate(ctx context.Context, blk interfaces.BeaconBlock) { - slot := blk.Slot() - if slot == 0 || slots.ToEpoch(slot) < params.BeaconConfig().AltairForkEpoch { + if blk.Version() < version.Altair { return } - - syncAggregate, err := vs.getSyncAggregate(ctx, slot-1, blk.ParentRoot()) + syncAggregate, err := vs.getSyncAggregate(ctx, blk.Slot()-1, blk.ParentRoot()) if err != nil { log.WithError(err).Error("Could not get sync aggregate") } else { if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { log.WithError(err).Error("Could not set sync aggregate") + emptySig := [96]byte{0xC0} if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{ SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), - SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + SyncCommitteeSignature: emptySig[:], }); err != nil { log.WithError(err).Error("Could not set sync aggregate") } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go index 6c0960a3e15c..ead3ff951b27 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go @@ -2,22 +2,28 @@ package validator import ( "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v3/config/params" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" - "github.com/prysmaticlabs/prysm/v3/time/slots" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/runtime/version" ) // Sets the bls to exec data for a block. func (vs *Server) setBlsToExecData(blk interfaces.BeaconBlock, headState state.BeaconState) error { - if slots.ToEpoch(blk.Slot()) < params.BeaconConfig().CapellaForkEpoch { + if blk.Version() < version.Capella { return nil } changes, err := vs.BLSChangesPool.BLSToExecChangesForInclusion(headState) if err != nil { + if err := blk.Body().SetBLSToExecutionChanges([]*ethpb.SignedBLSToExecutionChange{}); err != nil { + log.WithError(err).Error("Could not set bls to execution data in block") + } log.WithError(err).Error("Could not get bls to execution changes") } else { if err := blk.Body().SetBLSToExecutionChanges(changes); err != nil { + if err := blk.Body().SetBLSToExecutionChanges([]*ethpb.SignedBLSToExecutionChange{}); err != nil { + log.WithError(err).Error("Could not set bls to execution data in block") + } log.WithError(err).Error("Could not set bls to execution changes") } } From d608353ad6ccced822b017a9f744ef7083d05dc7 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 6 Jan 2023 14:23:42 -0800 Subject: [PATCH 19/30] Fix bls to exec data --- .../rpc/prysm/v1alpha1/validator/proposer.go | 5 +---- .../v1alpha1/validator/proposer_capella.go | 18 ++++++++---------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 65489eb5b3c3..b09bd67fd249 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -123,10 +123,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } // Set bls to execution change. New in Capella. - if err := vs.setBlsToExecData(blk, head); err != nil { - // Empty bls to exec array is set within `setBlsToExecData`. - log.WithError(err).Error("Could not set bls to execution data") - } + vs.setBlsToExecData(blk, head) sr, err := vs.computeStateRoot(ctx, sBlk) if err != nil { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go index ead3ff951b27..b5dea5cb9980 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_capella.go @@ -8,24 +8,22 @@ import ( ) // Sets the bls to exec data for a block. -func (vs *Server) setBlsToExecData(blk interfaces.BeaconBlock, headState state.BeaconState) error { +func (vs *Server) setBlsToExecData(blk interfaces.BeaconBlock, headState state.BeaconState) { if blk.Version() < version.Capella { - return nil + return + } + if err := blk.Body().SetBLSToExecutionChanges([]*ethpb.SignedBLSToExecutionChange{}); err != nil { + log.WithError(err).Error("Could not set bls to execution data in block") + return } - changes, err := vs.BLSChangesPool.BLSToExecChangesForInclusion(headState) if err != nil { - if err := blk.Body().SetBLSToExecutionChanges([]*ethpb.SignedBLSToExecutionChange{}); err != nil { - log.WithError(err).Error("Could not set bls to execution data in block") - } log.WithError(err).Error("Could not get bls to execution changes") + return } else { if err := blk.Body().SetBLSToExecutionChanges(changes); err != nil { - if err := blk.Body().SetBLSToExecutionChanges([]*ethpb.SignedBLSToExecutionChange{}); err != nil { - log.WithError(err).Error("Could not set bls to execution data in block") - } log.WithError(err).Error("Could not set bls to execution changes") + return } } - return nil } From 3ad693e85696f9ba65e9629193f3c09c0247c1d0 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 6 Jan 2023 14:27:05 -0800 Subject: [PATCH 20/30] Move deposit and att outside of else block --- .../rpc/prysm/v1alpha1/validator/proposer.go | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index b09bd67fd249..ae287008e397 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -86,17 +86,17 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( log.WithError(err).Error("Could not get eth1data") } else { blk.Body().SetEth1Data(eth1Data) + } - // Set deposit and attestation. - deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits - if err != nil { - blk.Body().SetDeposits([]*ethpb.Deposit{}) - blk.Body().SetAttestations([]*ethpb.Attestation{}) - log.WithError(err).Error("Could not pack deposits and attestations") - } else { - blk.Body().SetDeposits(deposits) - blk.Body().SetAttestations(atts) - } + // Set deposit and attestation. + deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits + if err != nil { + blk.Body().SetDeposits([]*ethpb.Deposit{}) + blk.Body().SetAttestations([]*ethpb.Attestation{}) + log.WithError(err).Error("Could not pack deposits and attestations") + } else { + blk.Body().SetDeposits(deposits) + blk.Body().SetAttestations(atts) } // Set proposer index. From daa1104aa54c5c0afc4b7df593b62ebded821c35 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 6 Jan 2023 14:29:11 -0800 Subject: [PATCH 21/30] Fix err msg --- beacon-chain/rpc/eth/validator/validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon-chain/rpc/eth/validator/validator.go b/beacon-chain/rpc/eth/validator/validator.go index 7bedfc20b450..c2b8424a53a7 100644 --- a/beacon-chain/rpc/eth/validator/validator.go +++ b/beacon-chain/rpc/eth/validator/validator.go @@ -502,7 +502,7 @@ func (vs *Server) ProduceBlindedBlock(ctx context.Context, req *ethpbv1.ProduceB } b, err := vs.V1Alpha1Server.GetBeaconBlock(ctx, v1alpha1req) if err != nil { - return nil, status.Error(codes.Unavailable, "Builder is not available due to miss-config or circuit breaker") + return nil, status.Error(codes.Unavailable, "Could not get block from prysm API") } blk, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(b.GetBlindedBellatrix()) if err != nil { From d0d5cde795be7053da3b00a38f7d80a772dd7115 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 6 Jan 2023 14:38:19 -0800 Subject: [PATCH 22/30] Rm elses --- beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index ae287008e397..03c3296fdddb 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -137,11 +137,14 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch { return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}}, nil - } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch && !blk.IsBlinded() { + } + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch && !blk.IsBlinded() { return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}}, nil - } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch && blk.IsBlinded() { + } + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch && blk.IsBlinded() { return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: pb.(*ethpb.BlindedBeaconBlockBellatrix)}}, nil - } else if slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch { + } + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch { return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: pb.(*ethpb.BeaconBlockAltair)}}, nil } return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: pb.(*ethpb.BeaconBlock)}}, nil From a40c2f9f06c5b83338f03c5d2b3ed06e590a0caf Mon Sep 17 00:00:00 2001 From: terence tsao Date: Sun, 8 Jan 2023 08:03:33 -0800 Subject: [PATCH 23/30] Better reconstruct error msg when EL client is syncing --- beacon-chain/execution/engine_client.go | 6 ++++++ beacon-chain/sync/rpc_beacon_blocks_by_root.go | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/beacon-chain/execution/engine_client.go b/beacon-chain/execution/engine_client.go index 297cfbb31c16..9ae76352f580 100644 --- a/beacon-chain/execution/engine_client.go +++ b/beacon-chain/execution/engine_client.go @@ -86,6 +86,8 @@ type EngineCaller interface { GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error) } +var EmptyBlockHash = errors.New("Block hash is empty 0x0000...") + // NewPayload calls the engine_newPayloadVX method via JSON-RPC. func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionData) ([]byte, error) { ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.NewPayload") @@ -471,6 +473,10 @@ func (s *Service) ReconstructFullBlock( if executionBlock == nil { return nil, fmt.Errorf("received nil execution block for request by hash %#x", executionBlockHash) } + if bytes.Equal(executionBlock.Hash.Bytes(), []byte{}) { + return nil, EmptyBlockHash + } + executionBlock.Version = blindedBlock.Version() payload, err := fullPayloadFromExecutionBlock(header, executionBlock) if err != nil { diff --git a/beacon-chain/sync/rpc_beacon_blocks_by_root.go b/beacon-chain/sync/rpc_beacon_blocks_by_root.go index 46ea536428df..08507895617d 100644 --- a/beacon-chain/sync/rpc_beacon_blocks_by_root.go +++ b/beacon-chain/sync/rpc_beacon_blocks_by_root.go @@ -6,6 +6,7 @@ import ( libp2pcore "github.com/libp2p/go-libp2p/core" "github.com/libp2p/go-libp2p/core/peer" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution" "github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p/types" "github.com/prysmaticlabs/prysm/v3/config/params" "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" @@ -77,7 +78,11 @@ func (s *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{ if blk.Block().IsBlinded() { blk, err = s.cfg.executionPayloadReconstructor.ReconstructFullBlock(ctx, blk) if err != nil { - log.WithError(err).Error("Could not get reconstruct full bellatrix block from blinded body") + if errors.Is(err, execution.EmptyBlockHash) { + log.WithError(err).Warn("Could not reconstruct block from header with syncing execution client. Waiting to complete syncing") + } else { + log.WithError(err).Error("Could not get reconstruct full block from blinded body") + } s.writeErrorResponseToStream(responseCodeServerError, types.ErrGeneric.Error(), stream) return err } From dd883df2792c4561d5af671c5ba70a3b9e7fa799 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Sun, 8 Jan 2023 08:48:30 -0800 Subject: [PATCH 24/30] Tested and worked --- beacon-chain/execution/engine_client.go | 5 ++++- beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/beacon-chain/execution/engine_client.go b/beacon-chain/execution/engine_client.go index 9ae76352f580..6ed905098194 100644 --- a/beacon-chain/execution/engine_client.go +++ b/beacon-chain/execution/engine_client.go @@ -473,7 +473,7 @@ func (s *Service) ReconstructFullBlock( if executionBlock == nil { return nil, fmt.Errorf("received nil execution block for request by hash %#x", executionBlockHash) } - if bytes.Equal(executionBlock.Hash.Bytes(), []byte{}) { + if bytes.Equal(executionBlock.Hash.Bytes(), params.BeaconConfig().ZeroHash[:]) { return nil, EmptyBlockHash } @@ -537,6 +537,9 @@ func (s *Service) ReconstructFullBellatrixBlockBatch( if b == nil { return nil, fmt.Errorf("received nil execution block for request by hash %#x", executionHashes[sliceIdx]) } + if bytes.Equal(b.Hash.Bytes(), params.BeaconConfig().ZeroHash[:]) { + return nil, EmptyBlockHash + } header, err := blindedBlocks[realIdx].Block().Body().Execution() if err != nil { return nil, err diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 03c3296fdddb..c46eeeb251f4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -49,11 +49,11 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). - if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { - if err := vs.optimisticStatus(ctx); err != nil { - return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) - } - } + //if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { + // if err := vs.optimisticStatus(ctx); err != nil { + // return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) + // } + //} sBlk, err := getEmptyBlock(req.Slot) if err != nil { From dd591bbccbce42f3c0f65dd9628a2574abb9fafe Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 11 Jan 2023 07:42:16 -0800 Subject: [PATCH 25/30] Potuz feedback --- beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index c46eeeb251f4..201524f401e7 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -82,11 +82,10 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( // Set eth1 data. eth1Data, err := vs.eth1DataMajorityVote(ctx, head) if err != nil { - blk.Body().SetEth1Data(ðpb.Eth1Data{DepositRoot: params.BeaconConfig().ZeroHash[:], BlockHash: params.BeaconConfig().ZeroHash[:]}) + eth1Data = ðpb.Eth1Data{DepositRoot: params.BeaconConfig().ZeroHash[:], BlockHash: params.BeaconConfig().ZeroHash[:]} log.WithError(err).Error("Could not get eth1data") - } else { - blk.Body().SetEth1Data(eth1Data) } + blk.Body().SetEth1Data(eth1Data) // Set deposit and attestation. deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits @@ -94,10 +93,9 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( blk.Body().SetDeposits([]*ethpb.Deposit{}) blk.Body().SetAttestations([]*ethpb.Attestation{}) log.WithError(err).Error("Could not pack deposits and attestations") - } else { - blk.Body().SetDeposits(deposits) - blk.Body().SetAttestations(atts) } + blk.Body().SetDeposits(deposits) + blk.Body().SetAttestations(atts) // Set proposer index. idx, err := helpers.BeaconProposerIndex(ctx, head) From e2c59cc249159d4488cd0e2140aa77f2df0bf07f Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 11 Jan 2023 07:44:44 -0800 Subject: [PATCH 26/30] Rm --- beacon-chain/execution/engine_client.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/beacon-chain/execution/engine_client.go b/beacon-chain/execution/engine_client.go index 320195f5d632..9ae76352f580 100644 --- a/beacon-chain/execution/engine_client.go +++ b/beacon-chain/execution/engine_client.go @@ -537,9 +537,6 @@ func (s *Service) ReconstructFullBellatrixBlockBatch( if b == nil { return nil, fmt.Errorf("received nil execution block for request by hash %#x", executionHashes[sliceIdx]) } - if bytes.Equal(b.Hash.Bytes(), params.BeaconConfig().ZeroHash[:]) { - return nil, EmptyBlockHash - } header, err := blindedBlocks[realIdx].Block().Body().Execution() if err != nil { return nil, err From 8291ed8f2f153dbc8f06105d149b85bfad68a68b Mon Sep 17 00:00:00 2001 From: terence tsao Date: Thu, 12 Jan 2023 07:23:10 -0800 Subject: [PATCH 27/30] Fix test --- beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 201524f401e7..c04fa106d32a 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -49,11 +49,11 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } // An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain). - //if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { - // if err := vs.optimisticStatus(ctx); err != nil { - // return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) - // } - //} + if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch { + if err := vs.optimisticStatus(ctx); err != nil { + return nil, status.Errorf(codes.Unavailable, "Validator is not ready to propose: %v", err) + } + } sBlk, err := getEmptyBlock(req.Slot) if err != nil { From 44b60998e9b8e79c07f7fa6a3f6217516eb34b9d Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 13 Jan 2023 13:46:09 -0800 Subject: [PATCH 28/30] Sync aggregate empty case --- .../rpc/prysm/v1alpha1/validator/BUILD.bazel | 1 + .../v1alpha1/validator/proposer_altair.go | 29 ++++++++++++------- .../validator/proposer_altair_test.go | 28 ++++++++++++++++++ 3 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair_test.go diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index b335b3d3dd8f..38b80d8d98e6 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -175,6 +175,7 @@ go_test( "attester_test.go", "blocks_test.go", "exit_test.go", + "proposer_altair_test.go", "proposer_attestations_test.go", "proposer_bellatrix_test.go", "proposer_builder_test.go", diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index e0979f1af0f6..3d512e332fc0 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -3,6 +3,7 @@ package validator import ( "context" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v3/config/params" "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" @@ -18,20 +19,23 @@ func (vs *Server) setSyncAggregate(ctx context.Context, blk interfaces.BeaconBlo if blk.Version() < version.Altair { return } + + // Set empty sync aggregate in case subsequent calls fail. Empty sync aggregate is better than failing. + emptySig := [96]byte{0xC0} + if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), + SyncCommitteeSignature: emptySig[:], + }); err != nil { + log.WithError(err).Error("Could not set empty sync aggregate") + } + syncAggregate, err := vs.getSyncAggregate(ctx, blk.Slot()-1, blk.ParentRoot()) if err != nil { log.WithError(err).Error("Could not get sync aggregate") - } else { - if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { - log.WithError(err).Error("Could not set sync aggregate") - emptySig := [96]byte{0xC0} - if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{ - SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), - SyncCommitteeSignature: emptySig[:], - }); err != nil { - log.WithError(err).Error("Could not set sync aggregate") - } - } + return + } + if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { + log.WithError(err).Error("Could not set sync aggregate") } } @@ -41,6 +45,9 @@ func (vs *Server) getSyncAggregate(ctx context.Context, slot types.Slot, root [3 ctx, span := trace.StartSpan(ctx, "ProposerServer.getSyncAggregate") defer span.End() + if vs.SyncCommitteePool == nil { + return nil, errors.New("sync committee pool is nil") + } // Contributions have to match the input root contributions, err := vs.SyncCommitteePool.SyncCommitteeContributions(slot) if err != nil { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair_test.go new file mode 100644 index 000000000000..32b5429d2120 --- /dev/null +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair_test.go @@ -0,0 +1,28 @@ +package validator + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/testing/require" + "github.com/prysmaticlabs/prysm/v3/testing/util" +) + +func TestServer_SetSyncAggregate_EmptyCase(t *testing.T) { + b, err := blocks.NewBeaconBlock(util.NewBeaconBlockAltair().Block) + require.NoError(t, err) + s := &Server{} // Sever is not initialized with sync committee pool. + s.setSyncAggregate(context.Background(), b) + agg, err := b.Body().SyncAggregate() + require.NoError(t, err) + + emptySig := [96]byte{0xC0} + want := ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), + SyncCommitteeSignature: emptySig[:], + } + require.DeepEqual(t, want, agg) +} From ac95af3796a12f8951b6882d809ff3dba5e23702 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 13 Jan 2023 14:14:22 -0800 Subject: [PATCH 29/30] Dont set it --- .../rpc/prysm/v1alpha1/validator/proposer_altair.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index 3d512e332fc0..f18d7563c456 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -22,17 +22,15 @@ func (vs *Server) setSyncAggregate(ctx context.Context, blk interfaces.BeaconBlo // Set empty sync aggregate in case subsequent calls fail. Empty sync aggregate is better than failing. emptySig := [96]byte{0xC0} - if err := blk.Body().SetSyncAggregate(ðpb.SyncAggregate{ + syncAggregate := ðpb.SyncAggregate{ SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), SyncCommitteeSignature: emptySig[:], - }); err != nil { - log.WithError(err).Error("Could not set empty sync aggregate") } - syncAggregate, err := vs.getSyncAggregate(ctx, blk.Slot()-1, blk.ParentRoot()) + var err error + syncAggregate, err = vs.getSyncAggregate(ctx, blk.Slot()-1, blk.ParentRoot()) if err != nil { log.WithError(err).Error("Could not get sync aggregate") - return } if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { log.WithError(err).Error("Could not set sync aggregate") From 575e523dcedf2f9455b658918788bf1950c069af Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 13 Jan 2023 14:35:47 -0800 Subject: [PATCH 30/30] Refactor to set empty within the error --- .../v1alpha1/validator/proposer_altair.go | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index f18d7563c456..ca0ee72ce281 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -20,18 +20,21 @@ func (vs *Server) setSyncAggregate(ctx context.Context, blk interfaces.BeaconBlo return } - // Set empty sync aggregate in case subsequent calls fail. Empty sync aggregate is better than failing. - emptySig := [96]byte{0xC0} - syncAggregate := ðpb.SyncAggregate{ - SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), - SyncCommitteeSignature: emptySig[:], - } - - var err error - syncAggregate, err = vs.getSyncAggregate(ctx, blk.Slot()-1, blk.ParentRoot()) + syncAggregate, err := vs.getSyncAggregate(ctx, blk.Slot()-1, blk.ParentRoot()) if err != nil { log.WithError(err).Error("Could not get sync aggregate") + emptySig := [96]byte{0xC0} + emptyAggregate := ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, params.BeaconConfig().SyncCommitteeSize), + SyncCommitteeSignature: emptySig[:], + } + if err := blk.Body().SetSyncAggregate(emptyAggregate); err != nil { + log.WithError(err).Error("Could not set sync aggregate") + } + return } + + // Can not error. We already filter block versioning at the top. Phase 0 is impossible. if err := blk.Body().SetSyncAggregate(syncAggregate); err != nil { log.WithError(err).Error("Could not set sync aggregate") }