diff --git a/beacon-chain/blockchain/chain_info.go b/beacon-chain/blockchain/chain_info.go index c3934c88975..2cfc28d4e40 100644 --- a/beacon-chain/blockchain/chain_info.go +++ b/beacon-chain/blockchain/chain_info.go @@ -45,6 +45,7 @@ type HeadFetcher interface { HeadValidatorsIndices(epoch uint64) ([]uint64, error) HeadSeed(epoch uint64) ([32]byte, error) HeadGenesisValidatorRoot() [32]byte + HeadETH1Data() *ethpb.Eth1Data } // ForkFetcher retrieves the current fork information of the Ethereum beacon chain. @@ -196,6 +197,14 @@ func (s *Service) HeadGenesisValidatorRoot() [32]byte { return s.headGenesisValidatorRoot() } +// HeadETH1Data returns the eth1data of the current head state. +func (s *Service) HeadETH1Data() *ethpb.Eth1Data { + if !s.hasHeadState() { + return ðpb.Eth1Data{} + } + return s.head.state.Eth1Data() +} + // GenesisTime returns the genesis time of beacon chain. func (s *Service) GenesisTime() time.Time { return s.genesisTime diff --git a/beacon-chain/blockchain/testing/mock.go b/beacon-chain/blockchain/testing/mock.go index d3f064554a9..49c46f7d5fc 100644 --- a/beacon-chain/blockchain/testing/mock.go +++ b/beacon-chain/blockchain/testing/mock.go @@ -36,6 +36,7 @@ type ChainService struct { Genesis time.Time ValidatorsRoot [32]byte Fork *pb.Fork + ETH1Data *ethpb.Eth1Data DB db.Database stateNotifier statefeed.Notifier blockNotifier blockfeed.Notifier @@ -220,6 +221,11 @@ func (ms *ChainService) HeadSeed(epoch uint64) ([32]byte, error) { return helpers.Seed(ms.State, epoch, params.BeaconConfig().DomainBeaconAttester) } +// HeadETH1Data provides the current ETH1Data of the head state. +func (ms *ChainService) HeadETH1Data() *ethpb.Eth1Data { + return ms.ETH1Data +} + // GenesisTime mocks the same method in the chain service. func (ms *ChainService) GenesisTime() time.Time { return ms.Genesis diff --git a/beacon-chain/rpc/validator/proposer.go b/beacon-chain/rpc/validator/proposer.go index 590159b9748..82afe2a4a92 100644 --- a/beacon-chain/rpc/validator/proposer.go +++ b/beacon-chain/rpc/validator/proposer.go @@ -383,6 +383,11 @@ func (vs *Server) defaultEth1DataResponse(ctx context.Context, currentHeight *bi if depositsTillHeight == 0 { return vs.ChainStartFetcher.ChainStartEth1Data(), nil } + // Check for the validity of deposit count. + currentETH1Data := vs.HeadFetcher.HeadETH1Data() + if depositsTillHeight < currentETH1Data.DepositCount { + return currentETH1Data, nil + } return ðpb.Eth1Data{ DepositRoot: depositRoot[:], BlockHash: blockHash[:], diff --git a/beacon-chain/rpc/validator/proposer_test.go b/beacon-chain/rpc/validator/proposer_test.go index d6c0d7906a9..518fc6b01c6 100644 --- a/beacon-chain/rpc/validator/proposer_test.go +++ b/beacon-chain/rpc/validator/proposer_test.go @@ -1239,6 +1239,71 @@ func TestEth1Data(t *testing.T) { } } +func TestEth1Data_SmallerDepositCount(t *testing.T) { + slot := uint64(10000) + deps := []*dbpb.DepositContainer{ + { + Index: 0, + Eth1BlockHeight: 8, + Deposit: ðpb.Deposit{ + Data: ðpb.Deposit_Data{ + PublicKey: []byte("a"), + Signature: make([]byte, 96), + WithdrawalCredentials: make([]byte, 32), + }}, + }, + { + Index: 1, + Eth1BlockHeight: 14, + Deposit: ðpb.Deposit{ + Data: ðpb.Deposit_Data{ + PublicKey: []byte("b"), + Signature: make([]byte, 96), + WithdrawalCredentials: make([]byte, 32), + }}, + }, + } + depositTrie, err := trieutil.NewTrie(int(params.BeaconConfig().DepositContractTreeDepth)) + if err != nil { + t.Fatalf("could not setup deposit trie: %v", err) + } + depositCache := depositcache.NewDepositCache() + for _, dp := range deps { + depositCache.InsertDeposit(context.Background(), dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.Root()) + } + + p := &mockPOW.POWChain{ + BlockNumberByHeight: map[uint64]*big.Int{ + slot * params.BeaconConfig().SecondsPerSlot: big.NewInt(4096), + }, + HashesByHeight: map[int][]byte{ + 4080: []byte("4080"), + }, + Eth1Data: ðpb.Eth1Data{ + DepositCount: 55, + }, + } + ps := &Server{ + ChainStartFetcher: p, + Eth1InfoFetcher: p, + Eth1BlockFetcher: p, + HeadFetcher: &mock.ChainService{ETH1Data: ðpb.Eth1Data{DepositCount: 10}}, + DepositFetcher: depositCache, + } + + ctx := context.Background() + eth1Data, err := ps.eth1Data(ctx, slot) + if err != nil { + t.Fatal(err) + } + + // Will default to 10 as the current deposit count in the + // cache is only 2. + if eth1Data.DepositCount != 10 { + t.Errorf("Expected deposit count to be 10 but got %d", eth1Data.DepositCount) + } +} + func TestEth1Data_MockEnabled(t *testing.T) { db := dbutil.SetupDB(t) // If a mock eth1 data votes is specified, we use the following for the