github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/eth/v1/beacon/pool_test.go (about)

     1  package beacon
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    10  	eth2types "github.com/prysmaticlabs/eth2-types"
    11  	"github.com/prysmaticlabs/go-bitfield"
    12  	chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
    13  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    14  	"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
    15  	"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
    16  	"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
    17  	p2pMock "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
    18  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    19  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1"
    20  	eth "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    21  	"github.com/prysmaticlabs/prysm/proto/migration"
    22  	"github.com/prysmaticlabs/prysm/shared/bls"
    23  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    24  	"github.com/prysmaticlabs/prysm/shared/grpcutils"
    25  	"github.com/prysmaticlabs/prysm/shared/params"
    26  	"github.com/prysmaticlabs/prysm/shared/testutil"
    27  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    28  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/protobuf/types/known/emptypb"
    31  )
    32  
    33  func TestListPoolAttestations(t *testing.T) {
    34  	state, err := testutil.NewBeaconState()
    35  	require.NoError(t, err)
    36  	att1 := &eth.Attestation{
    37  		AggregationBits: []byte{1, 10},
    38  		Data: &eth.AttestationData{
    39  			Slot:            1,
    40  			CommitteeIndex:  1,
    41  			BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32),
    42  			Source: &eth.Checkpoint{
    43  				Epoch: 1,
    44  				Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
    45  			},
    46  			Target: &eth.Checkpoint{
    47  				Epoch: 10,
    48  				Root:  bytesutil.PadTo([]byte("targetroot1"), 32),
    49  			},
    50  		},
    51  		Signature: bytesutil.PadTo([]byte("signature1"), 96),
    52  	}
    53  	att2 := &eth.Attestation{
    54  		AggregationBits: []byte{4, 40},
    55  		Data: &eth.AttestationData{
    56  			Slot:            4,
    57  			CommitteeIndex:  4,
    58  			BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot4"), 32),
    59  			Source: &eth.Checkpoint{
    60  				Epoch: 4,
    61  				Root:  bytesutil.PadTo([]byte("sourceroot4"), 32),
    62  			},
    63  			Target: &eth.Checkpoint{
    64  				Epoch: 40,
    65  				Root:  bytesutil.PadTo([]byte("targetroot4"), 32),
    66  			},
    67  		},
    68  		Signature: bytesutil.PadTo([]byte("signature4"), 96),
    69  	}
    70  	att3 := &eth.Attestation{
    71  		AggregationBits: []byte{2, 20},
    72  		Data: &eth.AttestationData{
    73  			Slot:            2,
    74  			CommitteeIndex:  2,
    75  			BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32),
    76  			Source: &eth.Checkpoint{
    77  				Epoch: 2,
    78  				Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
    79  			},
    80  			Target: &eth.Checkpoint{
    81  				Epoch: 20,
    82  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
    83  			},
    84  		},
    85  		Signature: bytesutil.PadTo([]byte("signature2"), 96),
    86  	}
    87  	att4 := &eth.Attestation{
    88  		AggregationBits: bitfield.NewBitlist(8),
    89  		Data: &eth.AttestationData{
    90  			Slot:            4,
    91  			CommitteeIndex:  4,
    92  			BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32),
    93  			Source: &eth.Checkpoint{
    94  				Epoch: 2,
    95  				Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
    96  			},
    97  			Target: &eth.Checkpoint{
    98  				Epoch: 20,
    99  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   100  			},
   101  		},
   102  		Signature: bytesutil.PadTo([]byte("signature2"), 96),
   103  	}
   104  	att5 := &eth.Attestation{
   105  		AggregationBits: bitfield.NewBitlist(8),
   106  		Data: &eth.AttestationData{
   107  			Slot:            2,
   108  			CommitteeIndex:  4,
   109  			BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32),
   110  			Source: &eth.Checkpoint{
   111  				Epoch: 2,
   112  				Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
   113  			},
   114  			Target: &eth.Checkpoint{
   115  				Epoch: 20,
   116  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   117  			},
   118  		},
   119  		Signature: bytesutil.PadTo([]byte("signature1"), 96),
   120  	}
   121  	att6 := &eth.Attestation{
   122  		AggregationBits: bitfield.NewBitlist(8),
   123  		Data: &eth.AttestationData{
   124  			Slot:            2,
   125  			CommitteeIndex:  4,
   126  			BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32),
   127  			Source: &eth.Checkpoint{
   128  				Epoch: 2,
   129  				Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
   130  			},
   131  			Target: &eth.Checkpoint{
   132  				Epoch: 20,
   133  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   134  			},
   135  		},
   136  		Signature: bytesutil.PadTo([]byte("signature2"), 96),
   137  	}
   138  	s := &Server{
   139  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   140  		AttestationsPool: attestations.NewPool(),
   141  	}
   142  	require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]*eth.Attestation{att1, att2, att3}))
   143  	require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]*eth.Attestation{att4, att5, att6}))
   144  
   145  	t.Run("empty request", func(t *testing.T) {
   146  		req := &ethpb.AttestationsPoolRequest{}
   147  		resp, err := s.ListPoolAttestations(context.Background(), req)
   148  		require.NoError(t, err)
   149  		require.Equal(t, 6, len(resp.Data))
   150  	})
   151  
   152  	t.Run("slot request", func(t *testing.T) {
   153  		slot := eth2types.Slot(2)
   154  		req := &ethpb.AttestationsPoolRequest{
   155  			Slot: &slot,
   156  		}
   157  		resp, err := s.ListPoolAttestations(context.Background(), req)
   158  		require.NoError(t, err)
   159  		require.Equal(t, 3, len(resp.Data))
   160  		for _, datum := range resp.Data {
   161  			assert.DeepEqual(t, datum.Data.Slot, slot)
   162  		}
   163  	})
   164  
   165  	t.Run("index request", func(t *testing.T) {
   166  		index := eth2types.CommitteeIndex(4)
   167  		req := &ethpb.AttestationsPoolRequest{
   168  			CommitteeIndex: &index,
   169  		}
   170  		resp, err := s.ListPoolAttestations(context.Background(), req)
   171  		require.NoError(t, err)
   172  		require.Equal(t, 4, len(resp.Data))
   173  		for _, datum := range resp.Data {
   174  			assert.DeepEqual(t, datum.Data.Index, index)
   175  		}
   176  	})
   177  
   178  	t.Run("both slot + index request", func(t *testing.T) {
   179  		slot := eth2types.Slot(2)
   180  		index := eth2types.CommitteeIndex(4)
   181  		req := &ethpb.AttestationsPoolRequest{
   182  			Slot:           &slot,
   183  			CommitteeIndex: &index,
   184  		}
   185  		resp, err := s.ListPoolAttestations(context.Background(), req)
   186  		require.NoError(t, err)
   187  		require.Equal(t, 2, len(resp.Data))
   188  		for _, datum := range resp.Data {
   189  			assert.DeepEqual(t, datum.Data.Index, index)
   190  			assert.DeepEqual(t, datum.Data.Slot, slot)
   191  		}
   192  	})
   193  }
   194  
   195  func TestListPoolAttesterSlashings(t *testing.T) {
   196  	state, err := testutil.NewBeaconState()
   197  	require.NoError(t, err)
   198  	slashing1 := &eth.AttesterSlashing{
   199  		Attestation_1: &eth.IndexedAttestation{
   200  			AttestingIndices: []uint64{1, 10},
   201  			Data: &eth.AttestationData{
   202  				Slot:            1,
   203  				CommitteeIndex:  1,
   204  				BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32),
   205  				Source: &eth.Checkpoint{
   206  					Epoch: 1,
   207  					Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   208  				},
   209  				Target: &eth.Checkpoint{
   210  					Epoch: 10,
   211  					Root:  bytesutil.PadTo([]byte("targetroot1"), 32),
   212  				},
   213  			},
   214  			Signature: bytesutil.PadTo([]byte("signature1"), 96),
   215  		},
   216  		Attestation_2: &eth.IndexedAttestation{
   217  			AttestingIndices: []uint64{2, 20},
   218  			Data: &eth.AttestationData{
   219  				Slot:            2,
   220  				CommitteeIndex:  2,
   221  				BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32),
   222  				Source: &eth.Checkpoint{
   223  					Epoch: 2,
   224  					Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
   225  				},
   226  				Target: &eth.Checkpoint{
   227  					Epoch: 20,
   228  					Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   229  				},
   230  			},
   231  			Signature: bytesutil.PadTo([]byte("signature2"), 96),
   232  		},
   233  	}
   234  	slashing2 := &eth.AttesterSlashing{
   235  		Attestation_1: &eth.IndexedAttestation{
   236  			AttestingIndices: []uint64{3, 30},
   237  			Data: &eth.AttestationData{
   238  				Slot:            3,
   239  				CommitteeIndex:  3,
   240  				BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot3"), 32),
   241  				Source: &eth.Checkpoint{
   242  					Epoch: 3,
   243  					Root:  bytesutil.PadTo([]byte("sourceroot3"), 32),
   244  				},
   245  				Target: &eth.Checkpoint{
   246  					Epoch: 30,
   247  					Root:  bytesutil.PadTo([]byte("targetroot3"), 32),
   248  				},
   249  			},
   250  			Signature: bytesutil.PadTo([]byte("signature3"), 96),
   251  		},
   252  		Attestation_2: &eth.IndexedAttestation{
   253  			AttestingIndices: []uint64{4, 40},
   254  			Data: &eth.AttestationData{
   255  				Slot:            4,
   256  				CommitteeIndex:  4,
   257  				BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot4"), 32),
   258  				Source: &eth.Checkpoint{
   259  					Epoch: 4,
   260  					Root:  bytesutil.PadTo([]byte("sourceroot4"), 32),
   261  				},
   262  				Target: &eth.Checkpoint{
   263  					Epoch: 40,
   264  					Root:  bytesutil.PadTo([]byte("targetroot4"), 32),
   265  				},
   266  			},
   267  			Signature: bytesutil.PadTo([]byte("signature4"), 96),
   268  		},
   269  	}
   270  
   271  	s := &Server{
   272  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   273  		SlashingsPool:    &slashings.PoolMock{PendingAttSlashings: []*eth.AttesterSlashing{slashing1, slashing2}},
   274  	}
   275  
   276  	resp, err := s.ListPoolAttesterSlashings(context.Background(), &emptypb.Empty{})
   277  	require.NoError(t, err)
   278  	require.Equal(t, 2, len(resp.Data))
   279  	assert.DeepEqual(t, migration.V1Alpha1AttSlashingToV1(slashing1), resp.Data[0])
   280  	assert.DeepEqual(t, migration.V1Alpha1AttSlashingToV1(slashing2), resp.Data[1])
   281  }
   282  
   283  func TestListPoolProposerSlashings(t *testing.T) {
   284  	state, err := testutil.NewBeaconState()
   285  	require.NoError(t, err)
   286  	slashing1 := &eth.ProposerSlashing{
   287  		Header_1: &eth.SignedBeaconBlockHeader{
   288  			Header: &eth.BeaconBlockHeader{
   289  				Slot:          1,
   290  				ProposerIndex: 1,
   291  				ParentRoot:    bytesutil.PadTo([]byte("parentroot1"), 32),
   292  				StateRoot:     bytesutil.PadTo([]byte("stateroot1"), 32),
   293  				BodyRoot:      bytesutil.PadTo([]byte("bodyroot1"), 32),
   294  			},
   295  			Signature: bytesutil.PadTo([]byte("signature1"), 96),
   296  		},
   297  		Header_2: &eth.SignedBeaconBlockHeader{
   298  			Header: &eth.BeaconBlockHeader{
   299  				Slot:          2,
   300  				ProposerIndex: 2,
   301  				ParentRoot:    bytesutil.PadTo([]byte("parentroot2"), 32),
   302  				StateRoot:     bytesutil.PadTo([]byte("stateroot2"), 32),
   303  				BodyRoot:      bytesutil.PadTo([]byte("bodyroot2"), 32),
   304  			},
   305  			Signature: bytesutil.PadTo([]byte("signature2"), 96),
   306  		},
   307  	}
   308  	slashing2 := &eth.ProposerSlashing{
   309  		Header_1: &eth.SignedBeaconBlockHeader{
   310  			Header: &eth.BeaconBlockHeader{
   311  				Slot:          3,
   312  				ProposerIndex: 3,
   313  				ParentRoot:    bytesutil.PadTo([]byte("parentroot3"), 32),
   314  				StateRoot:     bytesutil.PadTo([]byte("stateroot3"), 32),
   315  				BodyRoot:      bytesutil.PadTo([]byte("bodyroot3"), 32),
   316  			},
   317  			Signature: bytesutil.PadTo([]byte("signature3"), 96),
   318  		},
   319  		Header_2: &eth.SignedBeaconBlockHeader{
   320  			Header: &eth.BeaconBlockHeader{
   321  				Slot:          4,
   322  				ProposerIndex: 4,
   323  				ParentRoot:    bytesutil.PadTo([]byte("parentroot4"), 32),
   324  				StateRoot:     bytesutil.PadTo([]byte("stateroot4"), 32),
   325  				BodyRoot:      bytesutil.PadTo([]byte("bodyroot4"), 32),
   326  			},
   327  			Signature: bytesutil.PadTo([]byte("signature4"), 96),
   328  		},
   329  	}
   330  
   331  	s := &Server{
   332  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   333  		SlashingsPool:    &slashings.PoolMock{PendingPropSlashings: []*eth.ProposerSlashing{slashing1, slashing2}},
   334  	}
   335  
   336  	resp, err := s.ListPoolProposerSlashings(context.Background(), &emptypb.Empty{})
   337  	require.NoError(t, err)
   338  	require.Equal(t, 2, len(resp.Data))
   339  	assert.DeepEqual(t, migration.V1Alpha1ProposerSlashingToV1(slashing1), resp.Data[0])
   340  	assert.DeepEqual(t, migration.V1Alpha1ProposerSlashingToV1(slashing2), resp.Data[1])
   341  }
   342  
   343  func TestListPoolVoluntaryExits(t *testing.T) {
   344  	state, err := testutil.NewBeaconState()
   345  	require.NoError(t, err)
   346  	exit1 := &eth.SignedVoluntaryExit{
   347  		Exit: &eth.VoluntaryExit{
   348  			Epoch:          1,
   349  			ValidatorIndex: 1,
   350  		},
   351  		Signature: bytesutil.PadTo([]byte("signature1"), 96),
   352  	}
   353  	exit2 := &eth.SignedVoluntaryExit{
   354  		Exit: &eth.VoluntaryExit{
   355  			Epoch:          2,
   356  			ValidatorIndex: 2,
   357  		},
   358  		Signature: bytesutil.PadTo([]byte("signature2"), 96),
   359  	}
   360  
   361  	s := &Server{
   362  		ChainInfoFetcher:   &chainMock.ChainService{State: state},
   363  		VoluntaryExitsPool: &voluntaryexits.PoolMock{Exits: []*eth.SignedVoluntaryExit{exit1, exit2}},
   364  	}
   365  
   366  	resp, err := s.ListPoolVoluntaryExits(context.Background(), &emptypb.Empty{})
   367  	require.NoError(t, err)
   368  	require.Equal(t, 2, len(resp.Data))
   369  	assert.DeepEqual(t, migration.V1Alpha1ExitToV1(exit1), resp.Data[0])
   370  	assert.DeepEqual(t, migration.V1Alpha1ExitToV1(exit2), resp.Data[1])
   371  }
   372  
   373  func TestSubmitAttesterSlashing_Ok(t *testing.T) {
   374  	ctx := context.Background()
   375  
   376  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   377  	require.NoError(t, err)
   378  	validator := &eth.Validator{
   379  		PublicKey: keys[0].PublicKey().Marshal(),
   380  	}
   381  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   382  		state.Validators = []*eth.Validator{validator}
   383  		return nil
   384  	})
   385  	require.NoError(t, err)
   386  
   387  	slashing := &ethpb.AttesterSlashing{
   388  		Attestation_1: &ethpb.IndexedAttestation{
   389  			AttestingIndices: []uint64{0},
   390  			Data: &ethpb.AttestationData{
   391  				Slot:            1,
   392  				Index:           1,
   393  				BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32),
   394  				Source: &ethpb.Checkpoint{
   395  					Epoch: 1,
   396  					Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   397  				},
   398  				Target: &ethpb.Checkpoint{
   399  					Epoch: 10,
   400  					Root:  bytesutil.PadTo([]byte("targetroot1"), 32),
   401  				},
   402  			},
   403  			Signature: make([]byte, 96),
   404  		},
   405  		Attestation_2: &ethpb.IndexedAttestation{
   406  			AttestingIndices: []uint64{0},
   407  			Data: &ethpb.AttestationData{
   408  				Slot:            1,
   409  				Index:           1,
   410  				BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32),
   411  				Source: &ethpb.Checkpoint{
   412  					Epoch: 1,
   413  					Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
   414  				},
   415  				Target: &ethpb.Checkpoint{
   416  					Epoch: 10,
   417  					Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   418  				},
   419  			},
   420  			Signature: make([]byte, 96),
   421  		},
   422  	}
   423  
   424  	for _, att := range []*ethpb.IndexedAttestation{slashing.Attestation_1, slashing.Attestation_2} {
   425  		sb, err := helpers.ComputeDomainAndSign(state, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0])
   426  		require.NoError(t, err)
   427  		sig, err := bls.SignatureFromBytes(sb)
   428  		require.NoError(t, err)
   429  		att.Signature = sig.Marshal()
   430  	}
   431  
   432  	broadcaster := &p2pMock.MockBroadcaster{}
   433  	s := &Server{
   434  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   435  		SlashingsPool:    &slashings.PoolMock{},
   436  		Broadcaster:      broadcaster,
   437  	}
   438  
   439  	_, err = s.SubmitAttesterSlashing(ctx, slashing)
   440  	require.NoError(t, err)
   441  	pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, state, true)
   442  	require.Equal(t, 1, len(pendingSlashings))
   443  	assert.DeepEqual(t, migration.V1AttSlashingToV1Alpha1(slashing), pendingSlashings[0])
   444  	assert.Equal(t, true, broadcaster.BroadcastCalled)
   445  }
   446  
   447  func TestSubmitAttesterSlashing_InvalidSlashing(t *testing.T) {
   448  	ctx := context.Background()
   449  	state, err := testutil.NewBeaconState()
   450  	require.NoError(t, err)
   451  
   452  	attestation := &ethpb.IndexedAttestation{
   453  		AttestingIndices: []uint64{0},
   454  		Data: &ethpb.AttestationData{
   455  			Slot:            1,
   456  			Index:           1,
   457  			BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32),
   458  			Source: &ethpb.Checkpoint{
   459  				Epoch: 1,
   460  				Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   461  			},
   462  			Target: &ethpb.Checkpoint{
   463  				Epoch: 10,
   464  				Root:  bytesutil.PadTo([]byte("targetroot1"), 32),
   465  			},
   466  		},
   467  		Signature: make([]byte, 96),
   468  	}
   469  
   470  	slashing := &ethpb.AttesterSlashing{
   471  		Attestation_1: attestation,
   472  		Attestation_2: attestation,
   473  	}
   474  
   475  	broadcaster := &p2pMock.MockBroadcaster{}
   476  	s := &Server{
   477  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   478  		SlashingsPool:    &slashings.PoolMock{},
   479  		Broadcaster:      broadcaster,
   480  	}
   481  
   482  	_, err = s.SubmitAttesterSlashing(ctx, slashing)
   483  	require.ErrorContains(t, "Invalid attester slashing", err)
   484  	assert.Equal(t, false, broadcaster.BroadcastCalled)
   485  }
   486  
   487  func TestSubmitProposerSlashing_Ok(t *testing.T) {
   488  	ctx := context.Background()
   489  
   490  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   491  	require.NoError(t, err)
   492  	validator := &eth.Validator{
   493  		PublicKey:         keys[0].PublicKey().Marshal(),
   494  		WithdrawableEpoch: eth2types.Epoch(1),
   495  	}
   496  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   497  		state.Validators = []*eth.Validator{validator}
   498  		return nil
   499  	})
   500  	require.NoError(t, err)
   501  
   502  	slashing := &ethpb.ProposerSlashing{
   503  		SignedHeader_1: &ethpb.SignedBeaconBlockHeader{
   504  			Message: &ethpb.BeaconBlockHeader{
   505  				Slot:          1,
   506  				ProposerIndex: 0,
   507  				ParentRoot:    bytesutil.PadTo([]byte("parentroot1"), 32),
   508  				StateRoot:     bytesutil.PadTo([]byte("stateroot1"), 32),
   509  				BodyRoot:      bytesutil.PadTo([]byte("bodyroot1"), 32),
   510  			},
   511  			Signature: make([]byte, 96),
   512  		},
   513  		SignedHeader_2: &ethpb.SignedBeaconBlockHeader{
   514  			Message: &ethpb.BeaconBlockHeader{
   515  				Slot:          1,
   516  				ProposerIndex: 0,
   517  				ParentRoot:    bytesutil.PadTo([]byte("parentroot2"), 32),
   518  				StateRoot:     bytesutil.PadTo([]byte("stateroot2"), 32),
   519  				BodyRoot:      bytesutil.PadTo([]byte("bodyroot2"), 32),
   520  			},
   521  			Signature: make([]byte, 96),
   522  		},
   523  	}
   524  
   525  	for _, h := range []*ethpb.SignedBeaconBlockHeader{slashing.SignedHeader_1, slashing.SignedHeader_2} {
   526  		sb, err := helpers.ComputeDomainAndSign(
   527  			state,
   528  			helpers.SlotToEpoch(h.Message.Slot),
   529  			h.Message,
   530  			params.BeaconConfig().DomainBeaconProposer,
   531  			keys[0],
   532  		)
   533  		require.NoError(t, err)
   534  		sig, err := bls.SignatureFromBytes(sb)
   535  		require.NoError(t, err)
   536  		h.Signature = sig.Marshal()
   537  	}
   538  
   539  	broadcaster := &p2pMock.MockBroadcaster{}
   540  	s := &Server{
   541  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   542  		SlashingsPool:    &slashings.PoolMock{},
   543  		Broadcaster:      broadcaster,
   544  	}
   545  
   546  	_, err = s.SubmitProposerSlashing(ctx, slashing)
   547  	require.NoError(t, err)
   548  	pendingSlashings := s.SlashingsPool.PendingProposerSlashings(ctx, state, true)
   549  	require.Equal(t, 1, len(pendingSlashings))
   550  	assert.DeepEqual(t, migration.V1ProposerSlashingToV1Alpha1(slashing), pendingSlashings[0])
   551  	assert.Equal(t, true, broadcaster.BroadcastCalled)
   552  }
   553  
   554  func TestSubmitProposerSlashing_InvalidSlashing(t *testing.T) {
   555  	ctx := context.Background()
   556  	state, err := testutil.NewBeaconState()
   557  	require.NoError(t, err)
   558  
   559  	header := &ethpb.SignedBeaconBlockHeader{
   560  		Message: &ethpb.BeaconBlockHeader{
   561  			Slot:          1,
   562  			ProposerIndex: 0,
   563  			ParentRoot:    bytesutil.PadTo([]byte("parentroot1"), 32),
   564  			StateRoot:     bytesutil.PadTo([]byte("stateroot1"), 32),
   565  			BodyRoot:      bytesutil.PadTo([]byte("bodyroot1"), 32),
   566  		},
   567  		Signature: make([]byte, 96),
   568  	}
   569  
   570  	slashing := &ethpb.ProposerSlashing{
   571  		SignedHeader_1: header,
   572  		SignedHeader_2: header,
   573  	}
   574  
   575  	broadcaster := &p2pMock.MockBroadcaster{}
   576  	s := &Server{
   577  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   578  		SlashingsPool:    &slashings.PoolMock{},
   579  		Broadcaster:      broadcaster,
   580  	}
   581  
   582  	_, err = s.SubmitProposerSlashing(ctx, slashing)
   583  	require.ErrorContains(t, "Invalid proposer slashing", err)
   584  	assert.Equal(t, false, broadcaster.BroadcastCalled)
   585  }
   586  
   587  func TestSubmitVoluntaryExit_Ok(t *testing.T) {
   588  	ctx := context.Background()
   589  
   590  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   591  	require.NoError(t, err)
   592  	validator := &eth.Validator{
   593  		ExitEpoch: params.BeaconConfig().FarFutureEpoch,
   594  		PublicKey: keys[0].PublicKey().Marshal(),
   595  	}
   596  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   597  		state.Validators = []*eth.Validator{validator}
   598  		// Satisfy activity time required before exiting.
   599  		state.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod))
   600  		return nil
   601  	})
   602  	require.NoError(t, err)
   603  
   604  	exit := &ethpb.SignedVoluntaryExit{
   605  		Message: &ethpb.VoluntaryExit{
   606  			Epoch:          0,
   607  			ValidatorIndex: 0,
   608  		},
   609  		Signature: make([]byte, 96),
   610  	}
   611  
   612  	sb, err := helpers.ComputeDomainAndSign(state, exit.Message.Epoch, exit.Message, params.BeaconConfig().DomainVoluntaryExit, keys[0])
   613  	require.NoError(t, err)
   614  	sig, err := bls.SignatureFromBytes(sb)
   615  	require.NoError(t, err)
   616  	exit.Signature = sig.Marshal()
   617  
   618  	broadcaster := &p2pMock.MockBroadcaster{}
   619  	s := &Server{
   620  		ChainInfoFetcher:   &chainMock.ChainService{State: state},
   621  		VoluntaryExitsPool: &voluntaryexits.PoolMock{},
   622  		Broadcaster:        broadcaster,
   623  	}
   624  
   625  	_, err = s.SubmitVoluntaryExit(ctx, exit)
   626  	require.NoError(t, err)
   627  	pendingExits := s.VoluntaryExitsPool.PendingExits(state, state.Slot(), true)
   628  	require.Equal(t, 1, len(pendingExits))
   629  	assert.DeepEqual(t, migration.V1ExitToV1Alpha1(exit), pendingExits[0])
   630  	assert.Equal(t, true, broadcaster.BroadcastCalled)
   631  }
   632  
   633  func TestSubmitVoluntaryExit_InvalidValidatorIndex(t *testing.T) {
   634  	ctx := context.Background()
   635  
   636  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   637  	require.NoError(t, err)
   638  	validator := &eth.Validator{
   639  		ExitEpoch: params.BeaconConfig().FarFutureEpoch,
   640  		PublicKey: keys[0].PublicKey().Marshal(),
   641  	}
   642  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   643  		state.Validators = []*eth.Validator{validator}
   644  		return nil
   645  	})
   646  	require.NoError(t, err)
   647  
   648  	exit := &ethpb.SignedVoluntaryExit{
   649  		Message: &ethpb.VoluntaryExit{
   650  			Epoch:          0,
   651  			ValidatorIndex: 99,
   652  		},
   653  		Signature: make([]byte, 96),
   654  	}
   655  
   656  	broadcaster := &p2pMock.MockBroadcaster{}
   657  	s := &Server{
   658  		ChainInfoFetcher:   &chainMock.ChainService{State: state},
   659  		VoluntaryExitsPool: &voluntaryexits.PoolMock{},
   660  		Broadcaster:        broadcaster,
   661  	}
   662  
   663  	_, err = s.SubmitVoluntaryExit(ctx, exit)
   664  	require.ErrorContains(t, "Could not get exiting validator", err)
   665  	assert.Equal(t, false, broadcaster.BroadcastCalled)
   666  }
   667  
   668  func TestSubmitVoluntaryExit_InvalidExit(t *testing.T) {
   669  	ctx := context.Background()
   670  
   671  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   672  	require.NoError(t, err)
   673  	validator := &eth.Validator{
   674  		ExitEpoch: params.BeaconConfig().FarFutureEpoch,
   675  		PublicKey: keys[0].PublicKey().Marshal(),
   676  	}
   677  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   678  		state.Validators = []*eth.Validator{validator}
   679  		return nil
   680  	})
   681  	require.NoError(t, err)
   682  
   683  	exit := &ethpb.SignedVoluntaryExit{
   684  		Message: &ethpb.VoluntaryExit{
   685  			Epoch:          0,
   686  			ValidatorIndex: 0,
   687  		},
   688  		Signature: make([]byte, 96),
   689  	}
   690  
   691  	broadcaster := &p2pMock.MockBroadcaster{}
   692  	s := &Server{
   693  		ChainInfoFetcher:   &chainMock.ChainService{State: state},
   694  		VoluntaryExitsPool: &voluntaryexits.PoolMock{},
   695  		Broadcaster:        broadcaster,
   696  	}
   697  
   698  	_, err = s.SubmitVoluntaryExit(ctx, exit)
   699  	require.ErrorContains(t, "Invalid voluntary exit", err)
   700  	assert.Equal(t, false, broadcaster.BroadcastCalled)
   701  }
   702  
   703  func TestServer_SubmitAttestations_Ok(t *testing.T) {
   704  	ctx := context.Background()
   705  	params.SetupTestConfigCleanup(t)
   706  	c := params.BeaconConfig()
   707  	// Required for correct committee size calculation.
   708  	c.SlotsPerEpoch = 1
   709  	params.OverrideBeaconConfig(c)
   710  
   711  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   712  	require.NoError(t, err)
   713  	validators := []*eth.Validator{
   714  		{
   715  			PublicKey: keys[0].PublicKey().Marshal(),
   716  			ExitEpoch: params.BeaconConfig().FarFutureEpoch,
   717  		},
   718  	}
   719  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   720  		state.Validators = validators
   721  		state.Slot = 1
   722  		state.PreviousJustifiedCheckpoint = &eth.Checkpoint{
   723  			Epoch: 0,
   724  			Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   725  		}
   726  		return nil
   727  	})
   728  	require.NoError(t, err)
   729  	b := bitfield.NewBitlist(1)
   730  	b.SetBitAt(0, true)
   731  
   732  	sourceCheckpoint := &ethpb.Checkpoint{
   733  		Epoch: 0,
   734  		Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   735  	}
   736  	att1 := &ethpb.Attestation{
   737  		AggregationBits: b,
   738  		Data: &ethpb.AttestationData{
   739  			Slot:            0,
   740  			Index:           0,
   741  			BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot1"), 32),
   742  			Source:          sourceCheckpoint,
   743  			Target: &ethpb.Checkpoint{
   744  				Epoch: 0,
   745  				Root:  bytesutil.PadTo([]byte("targetroot1"), 32),
   746  			},
   747  		},
   748  		Signature: make([]byte, 96),
   749  	}
   750  	att2 := &ethpb.Attestation{
   751  		AggregationBits: b,
   752  		Data: &ethpb.AttestationData{
   753  			Slot:            0,
   754  			Index:           0,
   755  			BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32),
   756  			Source:          sourceCheckpoint,
   757  			Target: &ethpb.Checkpoint{
   758  				Epoch: 0,
   759  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   760  			},
   761  		},
   762  		Signature: make([]byte, 96),
   763  	}
   764  
   765  	for _, att := range []*ethpb.Attestation{att1, att2} {
   766  		sb, err := helpers.ComputeDomainAndSign(
   767  			state,
   768  			helpers.SlotToEpoch(att.Data.Slot),
   769  			att.Data,
   770  			params.BeaconConfig().DomainBeaconAttester,
   771  			keys[0],
   772  		)
   773  		require.NoError(t, err)
   774  		sig, err := bls.SignatureFromBytes(sb)
   775  		require.NoError(t, err)
   776  		att.Signature = sig.Marshal()
   777  	}
   778  
   779  	broadcaster := &p2pMock.MockBroadcaster{}
   780  	s := &Server{
   781  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   782  		AttestationsPool: &attestations.PoolMock{},
   783  		Broadcaster:      broadcaster,
   784  	}
   785  
   786  	_, err = s.SubmitAttestations(ctx, &ethpb.SubmitAttestationsRequest{
   787  		Data: []*ethpb.Attestation{att1, att2},
   788  	})
   789  	require.NoError(t, err)
   790  	savedAtts := s.AttestationsPool.AggregatedAttestations()
   791  	require.Equal(t, 2, len(savedAtts))
   792  	expectedAtt1, err := att1.HashTreeRoot()
   793  	require.NoError(t, err)
   794  	expectedAtt2, err := att2.HashTreeRoot()
   795  	require.NoError(t, err)
   796  	actualAtt1, err := savedAtts[0].HashTreeRoot()
   797  	require.NoError(t, err)
   798  	actualAtt2, err := savedAtts[1].HashTreeRoot()
   799  	require.NoError(t, err)
   800  	for _, r := range [][32]byte{actualAtt1, actualAtt2} {
   801  		assert.Equal(t, true, reflect.DeepEqual(expectedAtt1, r) || reflect.DeepEqual(expectedAtt2, r))
   802  	}
   803  	assert.Equal(t, true, broadcaster.BroadcastCalled)
   804  	assert.Equal(t, 2, len(broadcaster.BroadcastMessages))
   805  }
   806  
   807  func TestServer_SubmitAttestations_ValidAttestationSubmitted(t *testing.T) {
   808  	ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{})
   809  
   810  	params.SetupTestConfigCleanup(t)
   811  	c := params.BeaconConfig()
   812  	// Required for correct committee size calculation.
   813  	c.SlotsPerEpoch = 1
   814  	params.OverrideBeaconConfig(c)
   815  
   816  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   817  	require.NoError(t, err)
   818  	validators := []*eth.Validator{
   819  		{
   820  			PublicKey: keys[0].PublicKey().Marshal(),
   821  			ExitEpoch: params.BeaconConfig().FarFutureEpoch,
   822  		},
   823  	}
   824  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   825  		state.Validators = validators
   826  		state.Slot = 1
   827  		state.PreviousJustifiedCheckpoint = &eth.Checkpoint{
   828  			Epoch: 0,
   829  			Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   830  		}
   831  		return nil
   832  	})
   833  
   834  	require.NoError(t, err)
   835  
   836  	sourceCheckpoint := &ethpb.Checkpoint{
   837  		Epoch: 0,
   838  		Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   839  	}
   840  	b := bitfield.NewBitlist(1)
   841  	b.SetBitAt(0, true)
   842  	attValid := &ethpb.Attestation{
   843  		AggregationBits: b,
   844  		Data: &ethpb.AttestationData{
   845  			Slot:            0,
   846  			Index:           0,
   847  			BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot1"), 32),
   848  			Source:          sourceCheckpoint,
   849  			Target: &ethpb.Checkpoint{
   850  				Epoch: 0,
   851  				Root:  bytesutil.PadTo([]byte("targetroot1"), 32),
   852  			},
   853  		},
   854  		Signature: make([]byte, 96),
   855  	}
   856  	attInvalidTarget := &ethpb.Attestation{
   857  		AggregationBits: b,
   858  		Data: &ethpb.AttestationData{
   859  			Slot:            0,
   860  			Index:           0,
   861  			BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32),
   862  			Source: &ethpb.Checkpoint{
   863  				Epoch: 0,
   864  				Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
   865  			},
   866  			Target: &ethpb.Checkpoint{
   867  				Epoch: 99,
   868  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   869  			},
   870  		},
   871  		Signature: make([]byte, 96),
   872  	}
   873  	attInvalidSignature := &ethpb.Attestation{
   874  		AggregationBits: b,
   875  		Data: &ethpb.AttestationData{
   876  			Slot:            0,
   877  			Index:           0,
   878  			BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32),
   879  			Source:          sourceCheckpoint,
   880  			Target: &ethpb.Checkpoint{
   881  				Epoch: 0,
   882  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   883  			},
   884  		},
   885  		Signature: make([]byte, 96),
   886  	}
   887  
   888  	// Don't sign attInvalidSignature.
   889  	for _, att := range []*ethpb.Attestation{attValid, attInvalidTarget} {
   890  		sb, err := helpers.ComputeDomainAndSign(
   891  			state,
   892  			helpers.SlotToEpoch(att.Data.Slot),
   893  			att.Data,
   894  			params.BeaconConfig().DomainBeaconAttester,
   895  			keys[0],
   896  		)
   897  		require.NoError(t, err)
   898  		sig, err := bls.SignatureFromBytes(sb)
   899  		require.NoError(t, err)
   900  		att.Signature = sig.Marshal()
   901  	}
   902  
   903  	broadcaster := &p2pMock.MockBroadcaster{}
   904  	s := &Server{
   905  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   906  		AttestationsPool: &attestations.PoolMock{},
   907  		Broadcaster:      broadcaster,
   908  	}
   909  
   910  	_, err = s.SubmitAttestations(ctx, &ethpb.SubmitAttestationsRequest{
   911  		Data: []*ethpb.Attestation{attValid, attInvalidTarget, attInvalidSignature},
   912  	})
   913  	require.ErrorContains(t, "One or more attestations failed validation", err)
   914  	savedAtts := s.AttestationsPool.AggregatedAttestations()
   915  	require.Equal(t, 1, len(savedAtts))
   916  	expectedAtt, err := attValid.HashTreeRoot()
   917  	require.NoError(t, err)
   918  	actualAtt, err := savedAtts[0].HashTreeRoot()
   919  	require.NoError(t, err)
   920  	assert.DeepEqual(t, expectedAtt, actualAtt)
   921  	assert.Equal(t, true, broadcaster.BroadcastCalled)
   922  	require.Equal(t, 1, len(broadcaster.BroadcastMessages))
   923  	broadcastRoot, err := broadcaster.BroadcastMessages[0].(*eth.Attestation).HashTreeRoot()
   924  	require.NoError(t, err)
   925  	require.DeepEqual(t, expectedAtt, broadcastRoot)
   926  }
   927  
   928  func TestServer_SubmitAttestations_InvalidAttestationHeader(t *testing.T) {
   929  	ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{})
   930  
   931  	params.SetupTestConfigCleanup(t)
   932  	c := params.BeaconConfig()
   933  	// Required for correct committee size calculation.
   934  	c.SlotsPerEpoch = 1
   935  	params.OverrideBeaconConfig(c)
   936  
   937  	_, keys, err := testutil.DeterministicDepositsAndKeys(1)
   938  	require.NoError(t, err)
   939  	validators := []*eth.Validator{
   940  		{
   941  			PublicKey: keys[0].PublicKey().Marshal(),
   942  			ExitEpoch: params.BeaconConfig().FarFutureEpoch,
   943  		},
   944  	}
   945  	state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error {
   946  		state.Validators = validators
   947  		state.Slot = 1
   948  		state.PreviousJustifiedCheckpoint = &eth.Checkpoint{
   949  			Epoch: 0,
   950  			Root:  bytesutil.PadTo([]byte("sourceroot1"), 32),
   951  		}
   952  		return nil
   953  	})
   954  
   955  	require.NoError(t, err)
   956  
   957  	b := bitfield.NewBitlist(1)
   958  	b.SetBitAt(0, true)
   959  	att := &ethpb.Attestation{
   960  		AggregationBits: b,
   961  		Data: &ethpb.AttestationData{
   962  			Slot:            0,
   963  			Index:           0,
   964  			BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32),
   965  			Source: &ethpb.Checkpoint{
   966  				Epoch: 0,
   967  				Root:  bytesutil.PadTo([]byte("sourceroot2"), 32),
   968  			},
   969  			Target: &ethpb.Checkpoint{
   970  				Epoch: 99,
   971  				Root:  bytesutil.PadTo([]byte("targetroot2"), 32),
   972  			},
   973  		},
   974  		Signature: make([]byte, 96),
   975  	}
   976  
   977  	sb, err := helpers.ComputeDomainAndSign(
   978  		state,
   979  		helpers.SlotToEpoch(att.Data.Slot),
   980  		att.Data,
   981  		params.BeaconConfig().DomainBeaconAttester,
   982  		keys[0],
   983  	)
   984  	require.NoError(t, err)
   985  	sig, err := bls.SignatureFromBytes(sb)
   986  	require.NoError(t, err)
   987  	att.Signature = sig.Marshal()
   988  
   989  	broadcaster := &p2pMock.MockBroadcaster{}
   990  	s := &Server{
   991  		ChainInfoFetcher: &chainMock.ChainService{State: state},
   992  		AttestationsPool: &attestations.PoolMock{},
   993  		Broadcaster:      broadcaster,
   994  	}
   995  
   996  	_, err = s.SubmitAttestations(ctx, &ethpb.SubmitAttestationsRequest{
   997  		Data: []*ethpb.Attestation{att},
   998  	})
   999  	require.ErrorContains(t, "One or more attestations failed validation", err)
  1000  	sts, ok := grpc.ServerTransportStreamFromContext(ctx).(*runtime.ServerTransportStream)
  1001  	require.Equal(t, true, ok, "type assertion failed")
  1002  	md := sts.Header()
  1003  	v, ok := md[strings.ToLower(grpcutils.CustomErrorMetadataKey)]
  1004  	require.Equal(t, true, ok, "could not retrieve custom error metadata value")
  1005  	assert.DeepEqual(
  1006  		t,
  1007  		[]string{"{\"failures\":[{\"index\":0,\"message\":\"expected target epoch (99) to be the previous epoch (0) or the current epoch (1)\"}]}"},
  1008  		v,
  1009  	)
  1010  }