github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go (about)

     1  package validator
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"math/big"
     9  	"reflect"
    10  	"time"
    11  
    12  	fastssz "github.com/ferranbt/fastssz"
    13  	"github.com/pkg/errors"
    14  	types "github.com/prysmaticlabs/eth2-types"
    15  	"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
    16  	"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
    17  	blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
    18  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    19  	"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
    20  	"github.com/prysmaticlabs/prysm/beacon-chain/core/state/interop"
    21  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    22  	dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
    23  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    24  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    25  	"github.com/prysmaticlabs/prysm/proto/interfaces"
    26  	attaggregation "github.com/prysmaticlabs/prysm/shared/aggregation/attestations"
    27  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    28  	"github.com/prysmaticlabs/prysm/shared/featureconfig"
    29  	"github.com/prysmaticlabs/prysm/shared/hashutil"
    30  	"github.com/prysmaticlabs/prysm/shared/params"
    31  	"github.com/prysmaticlabs/prysm/shared/rand"
    32  	"github.com/prysmaticlabs/prysm/shared/trieutil"
    33  	"github.com/sirupsen/logrus"
    34  	"go.opencensus.io/trace"
    35  	"google.golang.org/grpc/codes"
    36  	"google.golang.org/grpc/status"
    37  )
    38  
    39  // eth1DataNotification is a latch to stop flooding logs with the same warning.
    40  var eth1DataNotification bool
    41  
    42  const eth1dataTimeout = 2 * time.Second
    43  
    44  type eth1DataSingleVote struct {
    45  	eth1Data    *ethpb.Eth1Data
    46  	blockHeight *big.Int
    47  }
    48  
    49  type eth1DataAggregatedVote struct {
    50  	data  eth1DataSingleVote
    51  	votes int
    52  }
    53  
    54  // GetBlock is called by a proposer during its assigned slot to request a block to sign
    55  // by passing in the slot and the signed randao reveal of the slot.
    56  func (vs *Server) GetBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlock, error) {
    57  	ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBlock")
    58  	defer span.End()
    59  	span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot)))
    60  
    61  	if vs.SyncChecker.Syncing() {
    62  		return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond")
    63  	}
    64  
    65  	// Retrieve the parent block as the current head of the canonical chain.
    66  	parentRoot, err := vs.HeadFetcher.HeadRoot(ctx)
    67  	if err != nil {
    68  		return nil, status.Errorf(codes.Internal, "Could not retrieve head root: %v", err)
    69  	}
    70  
    71  	head, err := vs.HeadFetcher.HeadState(ctx)
    72  	if err != nil {
    73  		return nil, status.Errorf(codes.Internal, "Could not get head state %v", err)
    74  	}
    75  
    76  	if featureconfig.Get().EnableNextSlotStateCache {
    77  		head, err = state.ProcessSlotsUsingNextSlotCache(ctx, head, parentRoot, req.Slot)
    78  		if err != nil {
    79  			return nil, status.Errorf(codes.Internal, "Could not advance slots to calculate proposer index: %v", err)
    80  		}
    81  	} else {
    82  		head, err = state.ProcessSlots(ctx, head, req.Slot)
    83  		if err != nil {
    84  			return nil, status.Errorf(codes.Internal, "Could not advance slot to calculate proposer index: %v", err)
    85  		}
    86  	}
    87  
    88  	eth1Data, err := vs.eth1DataMajorityVote(ctx, head)
    89  	if err != nil {
    90  		return nil, status.Errorf(codes.Internal, "Could not get ETH1 data: %v", err)
    91  	}
    92  
    93  	// Pack ETH1 deposits which have not been included in the beacon chain.
    94  	deposits, err := vs.deposits(ctx, head, eth1Data)
    95  	if err != nil {
    96  		return nil, status.Errorf(codes.Internal, "Could not get ETH1 deposits: %v", err)
    97  	}
    98  
    99  	// Pack aggregated attestations which have not been included in the beacon chain.
   100  	atts, err := vs.packAttestations(ctx, head)
   101  	if err != nil {
   102  		return nil, status.Errorf(codes.Internal, "Could not get attestations to pack into block: %v", err)
   103  	}
   104  
   105  	// Use zero hash as stub for state root to compute later.
   106  	stateRoot := params.BeaconConfig().ZeroHash[:]
   107  
   108  	graffiti := bytesutil.ToBytes32(req.Graffiti)
   109  
   110  	// Calculate new proposer index.
   111  	idx, err := helpers.BeaconProposerIndex(head)
   112  	if err != nil {
   113  		return nil, status.Errorf(codes.Internal, "Could not calculate proposer index %v", err)
   114  	}
   115  
   116  	blk := &ethpb.BeaconBlock{
   117  		Slot:          req.Slot,
   118  		ParentRoot:    parentRoot,
   119  		StateRoot:     stateRoot,
   120  		ProposerIndex: idx,
   121  		Body: &ethpb.BeaconBlockBody{
   122  			Eth1Data:          eth1Data,
   123  			Deposits:          deposits,
   124  			Attestations:      atts,
   125  			RandaoReveal:      req.RandaoReveal,
   126  			ProposerSlashings: vs.SlashingsPool.PendingProposerSlashings(ctx, head, false /*noLimit*/),
   127  			AttesterSlashings: vs.SlashingsPool.PendingAttesterSlashings(ctx, head, false /*noLimit*/),
   128  			VoluntaryExits:    vs.ExitPool.PendingExits(head, req.Slot, false /*noLimit*/),
   129  			Graffiti:          graffiti[:],
   130  		},
   131  	}
   132  
   133  	// Compute state root with the newly constructed block.
   134  	stateRoot, err = vs.computeStateRoot(ctx, wrapper.WrappedPhase0SignedBeaconBlock(&ethpb.SignedBeaconBlock{Block: blk, Signature: make([]byte, 96)}))
   135  	if err != nil {
   136  		interop.WriteBlockToDisk(wrapper.WrappedPhase0SignedBeaconBlock(&ethpb.SignedBeaconBlock{Block: blk}), true /*failed*/)
   137  		return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err)
   138  	}
   139  	blk.StateRoot = stateRoot
   140  
   141  	return blk, nil
   142  }
   143  
   144  // ProposeBlock is called by a proposer during its assigned slot to create a block in an attempt
   145  // to get it processed by the beacon node as the canonical head.
   146  func (vs *Server) ProposeBlock(ctx context.Context, rBlk *ethpb.SignedBeaconBlock) (*ethpb.ProposeResponse, error) {
   147  	blk := wrapper.WrappedPhase0SignedBeaconBlock(rBlk)
   148  	root, err := blk.Block().HashTreeRoot()
   149  	if err != nil {
   150  		return nil, status.Errorf(codes.Internal, "Could not tree hash block: %v", err)
   151  	}
   152  
   153  	// Do not block proposal critical path with debug logging or block feed updates.
   154  	defer func() {
   155  		log.WithField("blockRoot", fmt.Sprintf("%#x", bytesutil.Trunc(root[:]))).Debugf(
   156  			"Block proposal received via RPC")
   157  		vs.BlockNotifier.BlockFeed().Send(&feed.Event{
   158  			Type: blockfeed.ReceivedBlock,
   159  			Data: &blockfeed.ReceivedBlockData{SignedBlock: blk},
   160  		})
   161  	}()
   162  
   163  	// Broadcast the new block to the network.
   164  	if err := vs.P2P.Broadcast(ctx, blk.Proto()); err != nil {
   165  		return nil, status.Errorf(codes.Internal, "Could not broadcast block: %v", err)
   166  	}
   167  	log.WithFields(logrus.Fields{
   168  		"blockRoot": hex.EncodeToString(root[:]),
   169  	}).Debug("Broadcasting block")
   170  
   171  	if err := vs.BlockReceiver.ReceiveBlock(ctx, blk, root); err != nil {
   172  		return nil, status.Errorf(codes.Internal, "Could not process beacon block: %v", err)
   173  	}
   174  
   175  	return &ethpb.ProposeResponse{
   176  		BlockRoot: root[:],
   177  	}, nil
   178  }
   179  
   180  // eth1DataMajorityVote determines the appropriate eth1data for a block proposal using
   181  // an algorithm called Voting with the Majority. The algorithm works as follows:
   182  //  - Determine the timestamp for the start slot for the eth1 voting period.
   183  //  - Determine the earliest and latest timestamps that a valid block can have.
   184  //  - Determine the first block not before the earliest timestamp. This block is the lower bound.
   185  //  - Determine the last block not after the latest timestamp. This block is the upper bound.
   186  //  - If the last block is too early, use current eth1data from the beacon state.
   187  //  - Filter out votes on unknown blocks and blocks which are outside of the range determined by the lower and upper bounds.
   188  //  - If no blocks are left after filtering votes, use eth1data from the latest valid block.
   189  //  - Otherwise:
   190  //    - Determine the vote with the highest count. Prefer the vote with the highest eth1 block height in the event of a tie.
   191  //    - This vote's block is the eth1 block to use for the block proposal.
   192  func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState iface.BeaconState) (*ethpb.Eth1Data, error) {
   193  	ctx, cancel := context.WithTimeout(ctx, eth1dataTimeout)
   194  	defer cancel()
   195  
   196  	slot := beaconState.Slot()
   197  	votingPeriodStartTime := vs.slotStartTime(slot)
   198  
   199  	if vs.MockEth1Votes {
   200  		return vs.mockETH1DataVote(ctx, slot)
   201  	}
   202  	if !vs.Eth1InfoFetcher.IsConnectedToETH1() {
   203  		return vs.randomETH1DataVote(ctx)
   204  	}
   205  	eth1DataNotification = false
   206  
   207  	eth1FollowDistance := params.BeaconConfig().Eth1FollowDistance
   208  	earliestValidTime := votingPeriodStartTime - 2*params.BeaconConfig().SecondsPerETH1Block*eth1FollowDistance
   209  	latestValidTime := votingPeriodStartTime - params.BeaconConfig().SecondsPerETH1Block*eth1FollowDistance
   210  
   211  	lastBlockByEarliestValidTime, err := vs.Eth1BlockFetcher.BlockByTimestamp(ctx, earliestValidTime)
   212  	if err != nil {
   213  		log.WithError(err).Error("Could not get last block by earliest valid time")
   214  		return vs.randomETH1DataVote(ctx)
   215  	}
   216  	// Increment the earliest block if the original block's time is before valid time.
   217  	// This is very likely to happen because BlockTimeByHeight returns the last block AT OR BEFORE the specified time.
   218  	if lastBlockByEarliestValidTime.Time < earliestValidTime {
   219  		lastBlockByEarliestValidTime.Number = big.NewInt(0).Add(lastBlockByEarliestValidTime.Number, big.NewInt(1))
   220  	}
   221  
   222  	lastBlockByLatestValidTime, err := vs.Eth1BlockFetcher.BlockByTimestamp(ctx, latestValidTime)
   223  	if err != nil {
   224  		log.WithError(err).Error("Could not get last block by latest valid time")
   225  		return vs.randomETH1DataVote(ctx)
   226  	}
   227  	if lastBlockByLatestValidTime.Time < earliestValidTime {
   228  		return vs.HeadFetcher.HeadETH1Data(), nil
   229  	}
   230  
   231  	lastBlockDepositCount, lastBlockDepositRoot := vs.DepositFetcher.DepositsNumberAndRootAtHeight(ctx, lastBlockByLatestValidTime.Number)
   232  	if lastBlockDepositCount == 0 {
   233  		return vs.ChainStartFetcher.ChainStartEth1Data(), nil
   234  	}
   235  
   236  	if lastBlockDepositCount >= vs.HeadFetcher.HeadETH1Data().DepositCount {
   237  		hash, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, lastBlockByLatestValidTime.Number)
   238  		if err != nil {
   239  			log.WithError(err).Error("Could not get hash of last block by latest valid time")
   240  			return vs.randomETH1DataVote(ctx)
   241  		}
   242  		return &ethpb.Eth1Data{
   243  			BlockHash:    hash.Bytes(),
   244  			DepositCount: lastBlockDepositCount,
   245  			DepositRoot:  lastBlockDepositRoot[:],
   246  		}, nil
   247  	}
   248  	return vs.HeadFetcher.HeadETH1Data(), nil
   249  }
   250  
   251  func (vs *Server) slotStartTime(slot types.Slot) uint64 {
   252  	startTime, _ := vs.Eth1InfoFetcher.Eth2GenesisPowchainInfo()
   253  	return helpers.VotingPeriodStartTime(startTime, slot)
   254  }
   255  
   256  func (vs *Server) inRangeVotes(ctx context.Context,
   257  	beaconState iface.ReadOnlyBeaconState,
   258  	firstValidBlockNumber, lastValidBlockNumber *big.Int) ([]eth1DataSingleVote, error) {
   259  
   260  	currentETH1Data := vs.HeadFetcher.HeadETH1Data()
   261  
   262  	var inRangeVotes []eth1DataSingleVote
   263  	for _, eth1Data := range beaconState.Eth1DataVotes() {
   264  		exists, height, err := vs.BlockFetcher.BlockExistsWithCache(ctx, bytesutil.ToBytes32(eth1Data.BlockHash))
   265  		if err != nil {
   266  			log.Warningf("Could not fetch eth1data height for received eth1data vote: %v", err)
   267  		}
   268  		// Make sure we don't "undo deposit progress". See https://github.com/ethereum/eth2.0-specs/pull/1836
   269  		if eth1Data.DepositCount < currentETH1Data.DepositCount {
   270  			continue
   271  		}
   272  		// firstValidBlockNumber.Cmp(height) < 1 filters out all blocks before firstValidBlockNumber
   273  		// lastValidBlockNumber.Cmp(height) > -1 filters out all blocks after lastValidBlockNumber
   274  		// These filters result in the range [firstValidBlockNumber, lastValidBlockNumber]
   275  		if exists && firstValidBlockNumber.Cmp(height) < 1 && lastValidBlockNumber.Cmp(height) > -1 {
   276  			inRangeVotes = append(inRangeVotes, eth1DataSingleVote{eth1Data: eth1Data, blockHeight: height})
   277  		}
   278  	}
   279  
   280  	return inRangeVotes, nil
   281  }
   282  
   283  func chosenEth1DataMajorityVote(votes []eth1DataSingleVote) eth1DataAggregatedVote {
   284  	var voteCount []eth1DataAggregatedVote
   285  	for _, singleVote := range votes {
   286  		newVote := true
   287  		for i, aggregatedVote := range voteCount {
   288  			aggregatedData := aggregatedVote.data
   289  			if reflect.DeepEqual(singleVote.eth1Data, aggregatedData.eth1Data) {
   290  				voteCount[i].votes++
   291  				newVote = false
   292  				break
   293  			}
   294  		}
   295  
   296  		if newVote {
   297  			voteCount = append(voteCount, eth1DataAggregatedVote{data: singleVote, votes: 1})
   298  		}
   299  	}
   300  	if len(voteCount) == 0 {
   301  		return eth1DataAggregatedVote{}
   302  	}
   303  	currentVote := voteCount[0]
   304  	for _, aggregatedVote := range voteCount[1:] {
   305  		// Choose new eth1data if it has more votes or the same number of votes with a bigger block height.
   306  		if aggregatedVote.votes > currentVote.votes ||
   307  			(aggregatedVote.votes == currentVote.votes &&
   308  				aggregatedVote.data.blockHeight.Cmp(currentVote.data.blockHeight) == 1) {
   309  			currentVote = aggregatedVote
   310  		}
   311  	}
   312  
   313  	return currentVote
   314  }
   315  
   316  func (vs *Server) mockETH1DataVote(ctx context.Context, slot types.Slot) (*ethpb.Eth1Data, error) {
   317  	if !eth1DataNotification {
   318  		log.Warn("Beacon Node is no longer connected to an ETH1 chain, so ETH1 data votes are now mocked.")
   319  		eth1DataNotification = true
   320  	}
   321  	// If a mock eth1 data votes is specified, we use the following for the
   322  	// eth1data we provide to every proposer based on https://github.com/ethereum/eth2.0-pm/issues/62:
   323  	//
   324  	// slot_in_voting_period = current_slot % SLOTS_PER_ETH1_VOTING_PERIOD
   325  	// Eth1Data(
   326  	//   DepositRoot = hash(current_epoch + slot_in_voting_period),
   327  	//   DepositCount = state.eth1_deposit_index,
   328  	//   BlockHash = hash(hash(current_epoch + slot_in_voting_period)),
   329  	// )
   330  	slotInVotingPeriod := slot.ModSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod)))
   331  	headState, err := vs.HeadFetcher.HeadState(ctx)
   332  	if err != nil {
   333  		return nil, err
   334  	}
   335  	var enc []byte
   336  	enc = fastssz.MarshalUint64(enc, uint64(helpers.SlotToEpoch(slot))+uint64(slotInVotingPeriod))
   337  	depRoot := hashutil.Hash(enc)
   338  	blockHash := hashutil.Hash(depRoot[:])
   339  	return &ethpb.Eth1Data{
   340  		DepositRoot:  depRoot[:],
   341  		DepositCount: headState.Eth1DepositIndex(),
   342  		BlockHash:    blockHash[:],
   343  	}, nil
   344  }
   345  
   346  func (vs *Server) randomETH1DataVote(ctx context.Context) (*ethpb.Eth1Data, error) {
   347  	if !eth1DataNotification {
   348  		log.Warn("Beacon Node is no longer connected to an ETH1 chain, so ETH1 data votes are now random.")
   349  		eth1DataNotification = true
   350  	}
   351  	headState, err := vs.HeadFetcher.HeadState(ctx)
   352  	if err != nil {
   353  		return nil, err
   354  	}
   355  
   356  	// set random roots and block hashes to prevent a majority from being
   357  	// built if the eth1 node is offline
   358  	randGen := rand.NewGenerator()
   359  	depRoot := hashutil.Hash(bytesutil.Bytes32(randGen.Uint64()))
   360  	blockHash := hashutil.Hash(bytesutil.Bytes32(randGen.Uint64()))
   361  	return &ethpb.Eth1Data{
   362  		DepositRoot:  depRoot[:],
   363  		DepositCount: headState.Eth1DepositIndex(),
   364  		BlockHash:    blockHash[:],
   365  	}, nil
   366  }
   367  
   368  // computeStateRoot computes the state root after a block has been processed through a state transition and
   369  // returns it to the validator client.
   370  func (vs *Server) computeStateRoot(ctx context.Context, block interfaces.SignedBeaconBlock) ([]byte, error) {
   371  	beaconState, err := vs.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(block.Block().ParentRoot()))
   372  	if err != nil {
   373  		return nil, errors.Wrap(err, "could not retrieve beacon state")
   374  	}
   375  	root, err := state.CalculateStateRoot(
   376  		ctx,
   377  		beaconState,
   378  		block,
   379  	)
   380  	if err != nil {
   381  		return nil, errors.Wrapf(err, "could not calculate state root at slot %d", beaconState.Slot())
   382  	}
   383  
   384  	log.WithField("beaconStateRoot", fmt.Sprintf("%#x", root)).Debugf("Computed state root")
   385  	return root[:], nil
   386  }
   387  
   388  // deposits returns a list of pending deposits that are ready for inclusion in the next beacon
   389  // block. Determining deposits depends on the current eth1data vote for the block and whether or not
   390  // this eth1data has enough support to be considered for deposits inclusion. If current vote has
   391  // enough support, then use that vote for basis of determining deposits, otherwise use current state
   392  // eth1data.
   393  func (vs *Server) deposits(
   394  	ctx context.Context,
   395  	beaconState iface.BeaconState,
   396  	currentVote *ethpb.Eth1Data,
   397  ) ([]*ethpb.Deposit, error) {
   398  	ctx, span := trace.StartSpan(ctx, "ProposerServer.deposits")
   399  	defer span.End()
   400  
   401  	if vs.MockEth1Votes || !vs.Eth1InfoFetcher.IsConnectedToETH1() {
   402  		return []*ethpb.Deposit{}, nil
   403  	}
   404  	// Need to fetch if the deposits up to the state's latest eth 1 data matches
   405  	// the number of all deposits in this RPC call. If not, then we return nil.
   406  	canonicalEth1Data, canonicalEth1DataHeight, err := vs.canonicalEth1Data(ctx, beaconState, currentVote)
   407  	if err != nil {
   408  		return nil, err
   409  	}
   410  
   411  	_, genesisEth1Block := vs.Eth1InfoFetcher.Eth2GenesisPowchainInfo()
   412  	if genesisEth1Block.Cmp(canonicalEth1DataHeight) == 0 {
   413  		return []*ethpb.Deposit{}, nil
   414  	}
   415  
   416  	// If there are no pending deposits, exit early.
   417  	allPendingContainers := vs.PendingDepositsFetcher.PendingContainers(ctx, canonicalEth1DataHeight)
   418  	if len(allPendingContainers) == 0 {
   419  		return []*ethpb.Deposit{}, nil
   420  	}
   421  
   422  	depositTrie, err := vs.depositTrie(ctx, canonicalEth1Data, canonicalEth1DataHeight)
   423  	if err != nil {
   424  		return nil, errors.Wrap(err, "could not retrieve deposit trie")
   425  	}
   426  
   427  	// Deposits need to be received in order of merkle index root, so this has to make sure
   428  	// deposits are sorted from lowest to highest.
   429  	var pendingDeps []*dbpb.DepositContainer
   430  	for _, dep := range allPendingContainers {
   431  		if uint64(dep.Index) >= beaconState.Eth1DepositIndex() && uint64(dep.Index) < canonicalEth1Data.DepositCount {
   432  			pendingDeps = append(pendingDeps, dep)
   433  		}
   434  	}
   435  
   436  	for i := range pendingDeps {
   437  		// Don't construct merkle proof if the number of deposits is more than max allowed in block.
   438  		if uint64(i) == params.BeaconConfig().MaxDeposits {
   439  			break
   440  		}
   441  		pendingDeps[i].Deposit, err = constructMerkleProof(depositTrie, int(pendingDeps[i].Index), pendingDeps[i].Deposit)
   442  		if err != nil {
   443  			return nil, err
   444  		}
   445  	}
   446  	// Limit the return of pending deposits to not be more than max deposits allowed in block.
   447  	var pendingDeposits []*ethpb.Deposit
   448  	for i := uint64(0); i < uint64(len(pendingDeps)) && i < params.BeaconConfig().MaxDeposits; i++ {
   449  		pendingDeposits = append(pendingDeposits, pendingDeps[i].Deposit)
   450  	}
   451  	return pendingDeposits, nil
   452  }
   453  
   454  // canonicalEth1Data determines the canonical eth1data and eth1 block height to use for determining deposits.
   455  func (vs *Server) canonicalEth1Data(
   456  	ctx context.Context,
   457  	beaconState iface.BeaconState,
   458  	currentVote *ethpb.Eth1Data) (*ethpb.Eth1Data, *big.Int, error) {
   459  
   460  	var eth1BlockHash [32]byte
   461  
   462  	// Add in current vote, to get accurate vote tally
   463  	if err := beaconState.AppendEth1DataVotes(currentVote); err != nil {
   464  		return nil, nil, errors.Wrap(err, "could not append eth1 data votes to state")
   465  	}
   466  	hasSupport, err := blocks.Eth1DataHasEnoughSupport(beaconState, currentVote)
   467  	if err != nil {
   468  		return nil, nil, errors.Wrap(err, "could not determine if current eth1data vote has enough support")
   469  	}
   470  	var canonicalEth1Data *ethpb.Eth1Data
   471  	if hasSupport {
   472  		canonicalEth1Data = currentVote
   473  		eth1BlockHash = bytesutil.ToBytes32(currentVote.BlockHash)
   474  	} else {
   475  		canonicalEth1Data = beaconState.Eth1Data()
   476  		eth1BlockHash = bytesutil.ToBytes32(beaconState.Eth1Data().BlockHash)
   477  	}
   478  	_, canonicalEth1DataHeight, err := vs.Eth1BlockFetcher.BlockExists(ctx, eth1BlockHash)
   479  	if err != nil {
   480  		return nil, nil, errors.Wrap(err, "could not fetch eth1data height")
   481  	}
   482  	return canonicalEth1Data, canonicalEth1DataHeight, nil
   483  }
   484  
   485  func (vs *Server) depositTrie(ctx context.Context, canonicalEth1Data *ethpb.Eth1Data, canonicalEth1DataHeight *big.Int) (*trieutil.SparseMerkleTrie, error) {
   486  	ctx, span := trace.StartSpan(ctx, "ProposerServer.depositTrie")
   487  	defer span.End()
   488  
   489  	var depositTrie *trieutil.SparseMerkleTrie
   490  
   491  	finalizedDeposits := vs.DepositFetcher.FinalizedDeposits(ctx)
   492  	depositTrie = finalizedDeposits.Deposits
   493  	upToEth1DataDeposits := vs.DepositFetcher.NonFinalizedDeposits(ctx, canonicalEth1DataHeight)
   494  	insertIndex := finalizedDeposits.MerkleTrieIndex + 1
   495  
   496  	for _, dep := range upToEth1DataDeposits {
   497  		depHash, err := dep.Data.HashTreeRoot()
   498  		if err != nil {
   499  			return nil, errors.Wrap(err, "could not hash deposit data")
   500  		}
   501  		depositTrie.Insert(depHash[:], int(insertIndex))
   502  		insertIndex++
   503  	}
   504  	valid, err := vs.validateDepositTrie(depositTrie, canonicalEth1Data)
   505  	// Log a warning here, as the cached trie is invalid.
   506  	if !valid {
   507  		log.Warnf("Cached deposit trie is invalid, rebuilding it now: %v", err)
   508  		return vs.rebuildDepositTrie(ctx, canonicalEth1Data, canonicalEth1DataHeight)
   509  	}
   510  
   511  	return depositTrie, nil
   512  }
   513  
   514  // rebuilds our deposit trie by recreating it from all processed deposits till
   515  // specified eth1 block height.
   516  func (vs *Server) rebuildDepositTrie(ctx context.Context, canonicalEth1Data *ethpb.Eth1Data, canonicalEth1DataHeight *big.Int) (*trieutil.SparseMerkleTrie, error) {
   517  	ctx, span := trace.StartSpan(ctx, "ProposerServer.rebuildDepositTrie")
   518  	defer span.End()
   519  
   520  	deposits := vs.DepositFetcher.AllDeposits(ctx, canonicalEth1DataHeight)
   521  	trieItems := make([][]byte, 0, len(deposits))
   522  	for _, dep := range deposits {
   523  		depHash, err := dep.Data.HashTreeRoot()
   524  		if err != nil {
   525  			return nil, errors.Wrap(err, "could not hash deposit data")
   526  		}
   527  		trieItems = append(trieItems, depHash[:])
   528  	}
   529  	depositTrie, err := trieutil.GenerateTrieFromItems(trieItems, params.BeaconConfig().DepositContractTreeDepth)
   530  	if err != nil {
   531  		return nil, err
   532  	}
   533  
   534  	valid, err := vs.validateDepositTrie(depositTrie, canonicalEth1Data)
   535  	// Log an error here, as even with rebuilding the trie, it is still invalid.
   536  	if !valid {
   537  		log.Errorf("Rebuilt deposit trie is invalid: %v", err)
   538  	}
   539  	return depositTrie, nil
   540  }
   541  
   542  // validate that the provided deposit trie matches up with the canonical eth1 data provided.
   543  func (vs *Server) validateDepositTrie(trie *trieutil.SparseMerkleTrie, canonicalEth1Data *ethpb.Eth1Data) (bool, error) {
   544  	if trie.NumOfItems() != int(canonicalEth1Data.DepositCount) {
   545  		return false, errors.Errorf("wanted the canonical count of %d but received %d", canonicalEth1Data.DepositCount, trie.NumOfItems())
   546  	}
   547  	rt := trie.HashTreeRoot()
   548  	if !bytes.Equal(rt[:], canonicalEth1Data.DepositRoot) {
   549  		return false, errors.Errorf("wanted the canonical deposit root of %#x but received %#x", canonicalEth1Data.DepositRoot, rt)
   550  	}
   551  	return true, nil
   552  }
   553  
   554  // in case no vote for new eth1data vote considered best vote we
   555  // default into returning the latest deposit root and the block
   556  // hash of eth1 block hash that is FOLLOW_DISTANCE back from its
   557  // latest block.
   558  func (vs *Server) defaultEth1DataResponse(ctx context.Context, currentHeight *big.Int) (*ethpb.Eth1Data, error) {
   559  	if ctx.Err() != nil {
   560  		return nil, ctx.Err()
   561  	}
   562  	eth1FollowDistance := int64(params.BeaconConfig().Eth1FollowDistance)
   563  	ancestorHeight := big.NewInt(0).Sub(currentHeight, big.NewInt(eth1FollowDistance))
   564  	blockHash, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, ancestorHeight)
   565  	if err != nil {
   566  		return nil, errors.Wrap(err, "could not fetch ETH1_FOLLOW_DISTANCE ancestor")
   567  	}
   568  	// Fetch all historical deposits up to an ancestor height.
   569  	depositsTillHeight, depositRoot := vs.DepositFetcher.DepositsNumberAndRootAtHeight(ctx, ancestorHeight)
   570  	if depositsTillHeight == 0 {
   571  		return vs.ChainStartFetcher.ChainStartEth1Data(), nil
   572  	}
   573  	// // Make sure we don't "undo deposit progress". See https://github.com/ethereum/eth2.0-specs/pull/1836
   574  	currentETH1Data := vs.HeadFetcher.HeadETH1Data()
   575  	if depositsTillHeight < currentETH1Data.DepositCount {
   576  		return currentETH1Data, nil
   577  	}
   578  	return &ethpb.Eth1Data{
   579  		DepositRoot:  depositRoot[:],
   580  		BlockHash:    blockHash[:],
   581  		DepositCount: depositsTillHeight,
   582  	}, nil
   583  }
   584  
   585  // This filters the input attestations to return a list of valid attestations to be packaged inside a beacon block.
   586  func (vs *Server) filterAttestationsForBlockInclusion(ctx context.Context, st iface.BeaconState, atts []*ethpb.Attestation) ([]*ethpb.Attestation, error) {
   587  	ctx, span := trace.StartSpan(ctx, "ProposerServer.filterAttestationsForBlockInclusion")
   588  	defer span.End()
   589  
   590  	validAtts, invalidAtts := proposerAtts(atts).filter(ctx, st)
   591  	if err := vs.deleteAttsInPool(ctx, invalidAtts); err != nil {
   592  		return nil, err
   593  	}
   594  	deduped, err := validAtts.dedup()
   595  	if err != nil {
   596  		return nil, err
   597  	}
   598  	sorted, err := deduped.sortByProfitability()
   599  	if err != nil {
   600  		return nil, err
   601  	}
   602  	return sorted.limitToMaxAttestations(), nil
   603  }
   604  
   605  // The input attestations are processed and seen by the node, this deletes them from pool
   606  // so proposers don't include them in a block for the future.
   607  func (vs *Server) deleteAttsInPool(ctx context.Context, atts []*ethpb.Attestation) error {
   608  	ctx, span := trace.StartSpan(ctx, "ProposerServer.deleteAttsInPool")
   609  	defer span.End()
   610  
   611  	for _, att := range atts {
   612  		if ctx.Err() != nil {
   613  			return ctx.Err()
   614  		}
   615  		if helpers.IsAggregated(att) {
   616  			if err := vs.AttPool.DeleteAggregatedAttestation(att); err != nil {
   617  				return err
   618  			}
   619  		} else {
   620  			if err := vs.AttPool.DeleteUnaggregatedAttestation(att); err != nil {
   621  				return err
   622  			}
   623  		}
   624  	}
   625  	return nil
   626  }
   627  
   628  func constructMerkleProof(trie *trieutil.SparseMerkleTrie, index int, deposit *ethpb.Deposit) (*ethpb.Deposit, error) {
   629  	proof, err := trie.MerkleProof(index)
   630  	if err != nil {
   631  		return nil, errors.Wrapf(err, "could not generate merkle proof for deposit at index %d", index)
   632  	}
   633  	// For every deposit, we construct a Merkle proof using the powchain service's
   634  	// in-memory deposits trie, which is updated only once the state's LatestETH1Data
   635  	// property changes during a state transition after a voting period.
   636  	deposit.Proof = proof
   637  	return deposit, nil
   638  }
   639  
   640  func (vs *Server) packAttestations(ctx context.Context, latestState iface.BeaconState) ([]*ethpb.Attestation, error) {
   641  	ctx, span := trace.StartSpan(ctx, "ProposerServer.packAttestations")
   642  	defer span.End()
   643  
   644  	atts := vs.AttPool.AggregatedAttestations()
   645  	atts, err := vs.filterAttestationsForBlockInclusion(ctx, latestState, atts)
   646  	if err != nil {
   647  		return nil, errors.Wrap(err, "could not filter attestations")
   648  	}
   649  
   650  	// If there is any room left in the block, consider unaggregated attestations as well.
   651  	numAtts := uint64(len(atts))
   652  	if numAtts < params.BeaconConfig().MaxAttestations {
   653  		uAtts, err := vs.AttPool.UnaggregatedAttestations()
   654  		if err != nil {
   655  			return nil, errors.Wrap(err, "could not get unaggregated attestations")
   656  		}
   657  		uAtts, err = vs.filterAttestationsForBlockInclusion(ctx, latestState, uAtts)
   658  		if err != nil {
   659  			return nil, errors.Wrap(err, "could not filter attestations")
   660  		}
   661  		atts = append(atts, uAtts...)
   662  
   663  		attsByDataRoot := make(map[[32]byte][]*ethpb.Attestation, len(atts))
   664  		for _, att := range atts {
   665  			attDataRoot, err := att.Data.HashTreeRoot()
   666  			if err != nil {
   667  				return nil, err
   668  			}
   669  			attsByDataRoot[attDataRoot] = append(attsByDataRoot[attDataRoot], att)
   670  		}
   671  
   672  		attsForInclusion := proposerAtts(make([]*ethpb.Attestation, 0))
   673  		for _, as := range attsByDataRoot {
   674  			as, err := attaggregation.Aggregate(as)
   675  			if err != nil {
   676  				return nil, err
   677  			}
   678  			attsForInclusion = append(attsForInclusion, as...)
   679  		}
   680  		deduped, err := attsForInclusion.dedup()
   681  		if err != nil {
   682  			return nil, err
   683  		}
   684  		sorted, err := deduped.sortByProfitability()
   685  		if err != nil {
   686  			return nil, err
   687  		}
   688  		atts = sorted.limitToMaxAttestations()
   689  	}
   690  	return atts, nil
   691  }