github.com/prysmaticlabs/prysm@v1.4.4/validator/client/attest_test.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"errors"
     7  	"reflect"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/golang/mock/gomock"
    13  	types "github.com/prysmaticlabs/eth2-types"
    14  	"github.com/prysmaticlabs/go-bitfield"
    15  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    16  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    17  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    18  	validatorpb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
    19  	"github.com/prysmaticlabs/prysm/shared/bls"
    20  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    21  	"github.com/prysmaticlabs/prysm/shared/event"
    22  	"github.com/prysmaticlabs/prysm/shared/featureconfig"
    23  	"github.com/prysmaticlabs/prysm/shared/params"
    24  	"github.com/prysmaticlabs/prysm/shared/testutil"
    25  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    26  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    27  	"github.com/prysmaticlabs/prysm/shared/timeutils"
    28  	logTest "github.com/sirupsen/logrus/hooks/test"
    29  	grpc "google.golang.org/grpc"
    30  	"gopkg.in/d4l3k/messagediff.v1"
    31  )
    32  
    33  func TestRequestAttestation_ValidatorDutiesRequestFailure(t *testing.T) {
    34  	hook := logTest.NewGlobal()
    35  	validator, _, validatorKey, finish := setup(t)
    36  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{}}
    37  	defer finish()
    38  
    39  	pubKey := [48]byte{}
    40  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
    41  	validator.SubmitAttestation(context.Background(), 30, pubKey)
    42  	require.LogsContain(t, hook, "Could not fetch validator assignment")
    43  }
    44  
    45  func TestAttestToBlockHead_SubmitAttestation_EmptyCommittee(t *testing.T) {
    46  	hook := logTest.NewGlobal()
    47  
    48  	validator, _, validatorKey, finish := setup(t)
    49  	defer finish()
    50  	pubKey := [48]byte{}
    51  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
    52  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
    53  		{
    54  			PublicKey:      validatorKey.PublicKey().Marshal(),
    55  			CommitteeIndex: 0,
    56  			Committee:      make([]types.ValidatorIndex, 0),
    57  			ValidatorIndex: 0,
    58  		}}}
    59  	validator.SubmitAttestation(context.Background(), 0, pubKey)
    60  	require.LogsContain(t, hook, "Empty committee")
    61  }
    62  
    63  func TestAttestToBlockHead_SubmitAttestation_RequestFailure(t *testing.T) {
    64  	hook := logTest.NewGlobal()
    65  
    66  	validator, m, validatorKey, finish := setup(t)
    67  	defer finish()
    68  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
    69  		{
    70  			PublicKey:      validatorKey.PublicKey().Marshal(),
    71  			CommitteeIndex: 5,
    72  			Committee:      make([]types.ValidatorIndex, 111),
    73  			ValidatorIndex: 0,
    74  		}}}
    75  	m.validatorClient.EXPECT().GetAttestationData(
    76  		gomock.Any(), // ctx
    77  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
    78  	).Return(&ethpb.AttestationData{
    79  		BeaconBlockRoot: make([]byte, 32),
    80  		Target:          &ethpb.Checkpoint{Root: make([]byte, 32)},
    81  		Source:          &ethpb.Checkpoint{Root: make([]byte, 32)},
    82  	}, nil)
    83  	m.validatorClient.EXPECT().DomainData(
    84  		gomock.Any(), // ctx
    85  		gomock.Any(), // epoch2
    86  	).Times(2).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
    87  	m.validatorClient.EXPECT().ProposeAttestation(
    88  		gomock.Any(), // ctx
    89  		gomock.AssignableToTypeOf(&ethpb.Attestation{}),
    90  	).Return(nil, errors.New("something went wrong"))
    91  
    92  	pubKey := [48]byte{}
    93  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
    94  	validator.SubmitAttestation(context.Background(), 30, pubKey)
    95  	require.LogsContain(t, hook, "Could not submit attestation to beacon node")
    96  }
    97  
    98  func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) {
    99  	validator, m, validatorKey, finish := setup(t)
   100  	defer finish()
   101  	hook := logTest.NewGlobal()
   102  	validatorIndex := types.ValidatorIndex(7)
   103  	committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
   104  	pubKey := [48]byte{}
   105  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
   106  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
   107  		{
   108  			PublicKey:      validatorKey.PublicKey().Marshal(),
   109  			CommitteeIndex: 5,
   110  			Committee:      committee,
   111  			ValidatorIndex: validatorIndex,
   112  		},
   113  	}}
   114  
   115  	beaconBlockRoot := bytesutil.ToBytes32([]byte("A"))
   116  	targetRoot := bytesutil.ToBytes32([]byte("B"))
   117  	sourceRoot := bytesutil.ToBytes32([]byte("C"))
   118  	m.validatorClient.EXPECT().GetAttestationData(
   119  		gomock.Any(), // ctx
   120  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   121  	).Return(&ethpb.AttestationData{
   122  		BeaconBlockRoot: beaconBlockRoot[:],
   123  		Target:          &ethpb.Checkpoint{Root: targetRoot[:]},
   124  		Source:          &ethpb.Checkpoint{Root: sourceRoot[:], Epoch: 3},
   125  	}, nil)
   126  
   127  	m.validatorClient.EXPECT().DomainData(
   128  		gomock.Any(), // ctx
   129  		gomock.Any(), // epoch
   130  	).Times(2).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
   131  
   132  	var generatedAttestation *ethpb.Attestation
   133  	m.validatorClient.EXPECT().ProposeAttestation(
   134  		gomock.Any(), // ctx
   135  		gomock.AssignableToTypeOf(&ethpb.Attestation{}),
   136  	).Do(func(_ context.Context, att *ethpb.Attestation, opts ...grpc.CallOption) {
   137  		generatedAttestation = att
   138  	}).Return(&ethpb.AttestResponse{}, nil /* error */)
   139  
   140  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   141  
   142  	aggregationBitfield := bitfield.NewBitlist(uint64(len(committee)))
   143  	aggregationBitfield.SetBitAt(4, true)
   144  	expectedAttestation := &ethpb.Attestation{
   145  		Data: &ethpb.AttestationData{
   146  			BeaconBlockRoot: beaconBlockRoot[:],
   147  			Target:          &ethpb.Checkpoint{Root: targetRoot[:]},
   148  			Source:          &ethpb.Checkpoint{Root: sourceRoot[:], Epoch: 3},
   149  		},
   150  		AggregationBits: aggregationBitfield,
   151  		Signature:       make([]byte, 96),
   152  	}
   153  
   154  	root, err := helpers.ComputeSigningRoot(expectedAttestation.Data, make([]byte, 32))
   155  	require.NoError(t, err)
   156  
   157  	sig, err := validator.keyManager.Sign(context.Background(), &validatorpb.SignRequest{
   158  		PublicKey:   validatorKey.PublicKey().Marshal(),
   159  		SigningRoot: root[:],
   160  	})
   161  	require.NoError(t, err)
   162  	expectedAttestation.Signature = sig.Marshal()
   163  	if !reflect.DeepEqual(generatedAttestation, expectedAttestation) {
   164  		t.Errorf("Incorrectly attested head, wanted %v, received %v", expectedAttestation, generatedAttestation)
   165  		diff, _ := messagediff.PrettyDiff(expectedAttestation, generatedAttestation)
   166  		t.Log(diff)
   167  	}
   168  	require.LogsDoNotContain(t, hook, "Could not")
   169  }
   170  
   171  func TestAttestToBlockHead_BlocksDoubleAtt(t *testing.T) {
   172  	hook := logTest.NewGlobal()
   173  	validator, m, validatorKey, finish := setup(t)
   174  	defer finish()
   175  	validatorIndex := types.ValidatorIndex(7)
   176  	committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
   177  	pubKey := [48]byte{}
   178  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
   179  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
   180  		{
   181  			PublicKey:      validatorKey.PublicKey().Marshal(),
   182  			CommitteeIndex: 5,
   183  			Committee:      committee,
   184  			ValidatorIndex: validatorIndex,
   185  		},
   186  	}}
   187  	beaconBlockRoot := bytesutil.ToBytes32([]byte("A"))
   188  	targetRoot := bytesutil.ToBytes32([]byte("B"))
   189  	sourceRoot := bytesutil.ToBytes32([]byte("C"))
   190  	beaconBlockRoot2 := bytesutil.ToBytes32([]byte("D"))
   191  
   192  	m.validatorClient.EXPECT().GetAttestationData(
   193  		gomock.Any(), // ctx
   194  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   195  	).Return(&ethpb.AttestationData{
   196  		BeaconBlockRoot: beaconBlockRoot[:],
   197  		Target:          &ethpb.Checkpoint{Root: targetRoot[:], Epoch: 4},
   198  		Source:          &ethpb.Checkpoint{Root: sourceRoot[:], Epoch: 3},
   199  	}, nil)
   200  	m.validatorClient.EXPECT().GetAttestationData(
   201  		gomock.Any(), // ctx
   202  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   203  	).Return(&ethpb.AttestationData{
   204  		BeaconBlockRoot: beaconBlockRoot2[:],
   205  		Target:          &ethpb.Checkpoint{Root: targetRoot[:], Epoch: 4},
   206  		Source:          &ethpb.Checkpoint{Root: sourceRoot[:], Epoch: 3},
   207  	}, nil)
   208  	m.validatorClient.EXPECT().DomainData(
   209  		gomock.Any(), // ctx
   210  		gomock.Any(), // epoch
   211  	).Times(4).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
   212  
   213  	m.validatorClient.EXPECT().ProposeAttestation(
   214  		gomock.Any(), // ctx
   215  		gomock.AssignableToTypeOf(&ethpb.Attestation{}),
   216  	).Return(&ethpb.AttestResponse{AttestationDataRoot: make([]byte, 32)}, nil /* error */)
   217  
   218  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   219  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   220  	require.LogsContain(t, hook, "Failed attestation slashing protection")
   221  }
   222  
   223  func TestAttestToBlockHead_BlocksSurroundAtt(t *testing.T) {
   224  	hook := logTest.NewGlobal()
   225  	validator, m, validatorKey, finish := setup(t)
   226  	defer finish()
   227  	validatorIndex := types.ValidatorIndex(7)
   228  	committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
   229  	pubKey := [48]byte{}
   230  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
   231  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
   232  		{
   233  			PublicKey:      validatorKey.PublicKey().Marshal(),
   234  			CommitteeIndex: 5,
   235  			Committee:      committee,
   236  			ValidatorIndex: validatorIndex,
   237  		},
   238  	}}
   239  	beaconBlockRoot := bytesutil.ToBytes32([]byte("A"))
   240  	targetRoot := bytesutil.ToBytes32([]byte("B"))
   241  	sourceRoot := bytesutil.ToBytes32([]byte("C"))
   242  
   243  	m.validatorClient.EXPECT().GetAttestationData(
   244  		gomock.Any(), // ctx
   245  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   246  	).Return(&ethpb.AttestationData{
   247  		BeaconBlockRoot: beaconBlockRoot[:],
   248  		Target:          &ethpb.Checkpoint{Root: targetRoot[:], Epoch: 2},
   249  		Source:          &ethpb.Checkpoint{Root: sourceRoot[:], Epoch: 1},
   250  	}, nil)
   251  	m.validatorClient.EXPECT().GetAttestationData(
   252  		gomock.Any(), // ctx
   253  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   254  	).Return(&ethpb.AttestationData{
   255  		BeaconBlockRoot: beaconBlockRoot[:],
   256  		Target:          &ethpb.Checkpoint{Root: targetRoot[:], Epoch: 3},
   257  		Source:          &ethpb.Checkpoint{Root: sourceRoot[:], Epoch: 0},
   258  	}, nil)
   259  
   260  	m.validatorClient.EXPECT().DomainData(
   261  		gomock.Any(), // ctx
   262  		gomock.Any(), // epoch
   263  	).Times(4).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
   264  
   265  	m.validatorClient.EXPECT().ProposeAttestation(
   266  		gomock.Any(), // ctx
   267  		gomock.AssignableToTypeOf(&ethpb.Attestation{}),
   268  	).Return(&ethpb.AttestResponse{}, nil /* error */)
   269  
   270  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   271  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   272  	require.LogsContain(t, hook, "Failed attestation slashing protection")
   273  }
   274  
   275  func TestAttestToBlockHead_BlocksSurroundedAtt(t *testing.T) {
   276  	hook := logTest.NewGlobal()
   277  	validator, m, validatorKey, finish := setup(t)
   278  	defer finish()
   279  	validatorIndex := types.ValidatorIndex(7)
   280  	pubKey := [48]byte{}
   281  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
   282  	committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
   283  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
   284  		{
   285  			PublicKey:      validatorKey.PublicKey().Marshal(),
   286  			CommitteeIndex: 5,
   287  			Committee:      committee,
   288  			ValidatorIndex: validatorIndex,
   289  		},
   290  	}}
   291  	beaconBlockRoot := bytesutil.ToBytes32([]byte("A"))
   292  	targetRoot := bytesutil.ToBytes32([]byte("B"))
   293  	sourceRoot := bytesutil.ToBytes32([]byte("C"))
   294  
   295  	m.validatorClient.EXPECT().GetAttestationData(
   296  		gomock.Any(), // ctx
   297  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   298  	).Return(&ethpb.AttestationData{
   299  		BeaconBlockRoot: beaconBlockRoot[:],
   300  		Target:          &ethpb.Checkpoint{Root: targetRoot[:], Epoch: 3},
   301  		Source:          &ethpb.Checkpoint{Root: sourceRoot[:], Epoch: 0},
   302  	}, nil)
   303  
   304  	m.validatorClient.EXPECT().DomainData(
   305  		gomock.Any(), // ctx
   306  		gomock.Any(), // epoch
   307  	).Times(4).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
   308  
   309  	m.validatorClient.EXPECT().ProposeAttestation(
   310  		gomock.Any(), // ctx
   311  		gomock.AssignableToTypeOf(&ethpb.Attestation{}),
   312  	).Return(&ethpb.AttestResponse{}, nil /* error */)
   313  
   314  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   315  	require.LogsDoNotContain(t, hook, failedAttLocalProtectionErr)
   316  
   317  	m.validatorClient.EXPECT().GetAttestationData(
   318  		gomock.Any(), // ctx
   319  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   320  	).Return(&ethpb.AttestationData{
   321  		BeaconBlockRoot: bytesutil.PadTo([]byte("A"), 32),
   322  		Target:          &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte("B"), 32), Epoch: 2},
   323  		Source:          &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte("C"), 32), Epoch: 1},
   324  	}, nil)
   325  
   326  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   327  	require.LogsContain(t, hook, "Failed attestation slashing protection")
   328  }
   329  
   330  func TestAttestToBlockHead_DoesNotAttestBeforeDelay(t *testing.T) {
   331  	validator, m, validatorKey, finish := setup(t)
   332  	defer finish()
   333  
   334  	pubKey := [48]byte{}
   335  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
   336  	validator.genesisTime = uint64(timeutils.Now().Unix())
   337  	m.validatorClient.EXPECT().GetDuties(
   338  		gomock.Any(), // ctx
   339  		gomock.AssignableToTypeOf(&ethpb.DutiesRequest{}),
   340  		gomock.Any(),
   341  	).Times(0)
   342  
   343  	m.validatorClient.EXPECT().GetAttestationData(
   344  		gomock.Any(), // ctx
   345  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   346  	).Times(0)
   347  
   348  	m.validatorClient.EXPECT().ProposeAttestation(
   349  		gomock.Any(), // ctx
   350  		gomock.AssignableToTypeOf(&ethpb.Attestation{}),
   351  	).Return(&ethpb.AttestResponse{}, nil /* error */).Times(0)
   352  
   353  	timer := time.NewTimer(1 * time.Second)
   354  	go validator.SubmitAttestation(context.Background(), 0, pubKey)
   355  	<-timer.C
   356  }
   357  
   358  func TestAttestToBlockHead_DoesAttestAfterDelay(t *testing.T) {
   359  	validator, m, validatorKey, finish := setup(t)
   360  	defer finish()
   361  
   362  	var wg sync.WaitGroup
   363  	wg.Add(1)
   364  	defer wg.Wait()
   365  
   366  	validator.genesisTime = uint64(timeutils.Now().Unix())
   367  	validatorIndex := types.ValidatorIndex(5)
   368  	committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
   369  	pubKey := [48]byte{}
   370  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
   371  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
   372  		{
   373  			PublicKey:      validatorKey.PublicKey().Marshal(),
   374  			CommitteeIndex: 5,
   375  			Committee:      committee,
   376  			ValidatorIndex: validatorIndex,
   377  		}}}
   378  
   379  	m.validatorClient.EXPECT().GetAttestationData(
   380  		gomock.Any(), // ctx
   381  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   382  	).Return(&ethpb.AttestationData{
   383  		BeaconBlockRoot: bytesutil.PadTo([]byte("A"), 32),
   384  		Target:          &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte("B"), 32)},
   385  		Source:          &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte("C"), 32), Epoch: 3},
   386  	}, nil).Do(func(arg0, arg1 interface{}, arg2 ...grpc.CallOption) {
   387  		wg.Done()
   388  	})
   389  
   390  	m.validatorClient.EXPECT().DomainData(
   391  		gomock.Any(), // ctx
   392  		gomock.Any(), // epoch
   393  	).Times(2).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
   394  
   395  	m.validatorClient.EXPECT().ProposeAttestation(
   396  		gomock.Any(), // ctx
   397  		gomock.Any(),
   398  	).Return(&ethpb.AttestResponse{}, nil).Times(1)
   399  
   400  	validator.SubmitAttestation(context.Background(), 0, pubKey)
   401  }
   402  
   403  func TestAttestToBlockHead_CorrectBitfieldLength(t *testing.T) {
   404  	validator, m, validatorKey, finish := setup(t)
   405  	defer finish()
   406  	validatorIndex := types.ValidatorIndex(2)
   407  	committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
   408  	pubKey := [48]byte{}
   409  	copy(pubKey[:], validatorKey.PublicKey().Marshal())
   410  	validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
   411  		{
   412  			PublicKey:      validatorKey.PublicKey().Marshal(),
   413  			CommitteeIndex: 5,
   414  			Committee:      committee,
   415  			ValidatorIndex: validatorIndex,
   416  		}}}
   417  	m.validatorClient.EXPECT().GetAttestationData(
   418  		gomock.Any(), // ctx
   419  		gomock.AssignableToTypeOf(&ethpb.AttestationDataRequest{}),
   420  	).Return(&ethpb.AttestationData{
   421  		Target:          &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte("B"), 32)},
   422  		Source:          &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte("C"), 32), Epoch: 3},
   423  		BeaconBlockRoot: make([]byte, 32),
   424  	}, nil)
   425  
   426  	m.validatorClient.EXPECT().DomainData(
   427  		gomock.Any(), // ctx
   428  		gomock.Any(), // epoch
   429  	).Times(2).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
   430  
   431  	var generatedAttestation *ethpb.Attestation
   432  	m.validatorClient.EXPECT().ProposeAttestation(
   433  		gomock.Any(), // ctx
   434  		gomock.AssignableToTypeOf(&ethpb.Attestation{}),
   435  	).Do(func(_ context.Context, att *ethpb.Attestation, arg2 ...grpc.CallOption) {
   436  		generatedAttestation = att
   437  	}).Return(&ethpb.AttestResponse{}, nil /* error */)
   438  
   439  	validator.SubmitAttestation(context.Background(), 30, pubKey)
   440  
   441  	assert.Equal(t, 2, len(generatedAttestation.AggregationBits))
   442  }
   443  
   444  func TestSignAttestation(t *testing.T) {
   445  	validator, m, _, finish := setup(t)
   446  	defer finish()
   447  
   448  	secretKey, err := bls.SecretKeyFromBytes(bytesutil.PadTo([]byte{1}, 32))
   449  	require.NoError(t, err, "Failed to generate key from bytes")
   450  	publicKey := secretKey.PublicKey()
   451  	wantedFork := &pb.Fork{
   452  		PreviousVersion: []byte{'a', 'b', 'c', 'd'},
   453  		CurrentVersion:  []byte{'d', 'e', 'f', 'f'},
   454  		Epoch:           0,
   455  	}
   456  	genesisValidatorRoot := [32]byte{0x01, 0x02}
   457  	attesterDomain, err := helpers.Domain(wantedFork, 0, params.BeaconConfig().DomainBeaconAttester, genesisValidatorRoot[:])
   458  	require.NoError(t, err)
   459  	m.validatorClient.EXPECT().
   460  		DomainData(gomock.Any(), gomock.Any()).
   461  		Return(&ethpb.DomainResponse{SignatureDomain: attesterDomain}, nil)
   462  	ctx := context.Background()
   463  	att := testutil.NewAttestation()
   464  	att.Data.Source.Epoch = 100
   465  	att.Data.Target.Epoch = 200
   466  	att.Data.Slot = 999
   467  	att.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("blockRoot"), 32)
   468  	var pubKey [48]byte
   469  	copy(pubKey[:], publicKey.Marshal())
   470  	km := &mockKeymanager{
   471  		keysMap: map[[48]byte]bls.SecretKey{
   472  			pubKey: secretKey,
   473  		},
   474  	}
   475  	validator.keyManager = km
   476  	sig, sr, err := validator.signAtt(ctx, pubKey, att.Data)
   477  	require.NoError(t, err, "%x,%x,%v", sig, sr, err)
   478  	require.Equal(t, "b6a60f8497bd328908be83634d045"+
   479  		"dd7a32f5e246b2c4031fc2f316983f362e36fc27fd3d6d5a2b15"+
   480  		"b4dbff38804ffb10b1719b7ebc54e9cbf3293fd37082bc0fc91f"+
   481  		"79d70ce5b04ff13de3c8e10bb41305bfdbe921a43792c12624f2"+
   482  		"25ee865", hex.EncodeToString(sig))
   483  	// proposer domain
   484  	require.DeepEqual(t, "02bbdb88056d6cbafd6e94575540"+
   485  		"e74b8cf2c0f2c1b79b8e17e7b21ed1694305", hex.EncodeToString(sr[:]))
   486  }
   487  
   488  func TestServer_WaitToSlotOneThird_CanWait(t *testing.T) {
   489  	currentTime := uint64(time.Now().Unix())
   490  	currentSlot := types.Slot(4)
   491  	genesisTime := currentTime - uint64(currentSlot.Mul(params.BeaconConfig().SecondsPerSlot))
   492  
   493  	v := &validator{
   494  		genesisTime: genesisTime,
   495  		blockFeed:   new(event.Feed),
   496  	}
   497  
   498  	timeToSleep := params.BeaconConfig().SecondsPerSlot / 3
   499  	oneThird := currentTime + timeToSleep
   500  	v.waitOneThirdOrValidBlock(context.Background(), currentSlot)
   501  
   502  	if oneThird != uint64(time.Now().Unix()) {
   503  		t.Errorf("Wanted %d time for slot one third but got %d", oneThird, currentTime)
   504  	}
   505  }
   506  
   507  func TestServer_WaitToSlotOneThird_SameReqSlot(t *testing.T) {
   508  	currentTime := uint64(time.Now().Unix())
   509  	currentSlot := types.Slot(4)
   510  	genesisTime := currentTime - uint64(currentSlot.Mul(params.BeaconConfig().SecondsPerSlot))
   511  
   512  	v := &validator{
   513  		genesisTime:      genesisTime,
   514  		blockFeed:        new(event.Feed),
   515  		highestValidSlot: currentSlot,
   516  	}
   517  
   518  	v.waitOneThirdOrValidBlock(context.Background(), currentSlot)
   519  
   520  	if currentTime != uint64(time.Now().Unix()) {
   521  		t.Errorf("Wanted %d time for slot one third but got %d", uint64(time.Now().Unix()), currentTime)
   522  	}
   523  }
   524  
   525  func TestServer_WaitToSlotOneThird_ReceiveBlockSlot(t *testing.T) {
   526  	resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{AttestTimely: true})
   527  	defer resetCfg()
   528  
   529  	currentTime := uint64(time.Now().Unix())
   530  	currentSlot := types.Slot(4)
   531  	genesisTime := currentTime - uint64(currentSlot.Mul(params.BeaconConfig().SecondsPerSlot))
   532  
   533  	v := &validator{
   534  		genesisTime: genesisTime,
   535  		blockFeed:   new(event.Feed),
   536  	}
   537  
   538  	wg := &sync.WaitGroup{}
   539  	wg.Add(1)
   540  	go func() {
   541  		v.blockFeed.Send(&ethpb.SignedBeaconBlock{
   542  			Block: &ethpb.BeaconBlock{Slot: currentSlot},
   543  		})
   544  		wg.Done()
   545  	}()
   546  
   547  	v.waitOneThirdOrValidBlock(context.Background(), currentSlot)
   548  
   549  	if currentTime != uint64(time.Now().Unix()) {
   550  		t.Errorf("Wanted %d time for slot one third but got %d", uint64(time.Now().Unix()), currentTime)
   551  	}
   552  }