github.com/prysmaticlabs/prysm@v1.4.4/validator/client/attest_protect_test.go (about) 1 package client 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/golang/mock/gomock" 8 types "github.com/prysmaticlabs/eth2-types" 9 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 10 "github.com/prysmaticlabs/prysm/shared/bytesutil" 11 "github.com/prysmaticlabs/prysm/shared/featureconfig" 12 "github.com/prysmaticlabs/prysm/shared/testutil/require" 13 mockSlasher "github.com/prysmaticlabs/prysm/validator/testing" 14 ) 15 16 func Test_slashableAttestationCheck(t *testing.T) { 17 config := &featureconfig.Flags{ 18 SlasherProtection: true, 19 } 20 reset := featureconfig.InitWithReset(config) 21 defer reset() 22 validator, _, validatorKey, finish := setup(t) 23 defer finish() 24 pubKey := [48]byte{} 25 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 26 att := ðpb.IndexedAttestation{ 27 AttestingIndices: []uint64{1, 2}, 28 Data: ðpb.AttestationData{ 29 Slot: 5, 30 CommitteeIndex: 2, 31 BeaconBlockRoot: bytesutil.PadTo([]byte("great block"), 32), 32 Source: ðpb.Checkpoint{ 33 Epoch: 4, 34 Root: bytesutil.PadTo([]byte("good source"), 32), 35 }, 36 Target: ðpb.Checkpoint{ 37 Epoch: 10, 38 Root: bytesutil.PadTo([]byte("good target"), 32), 39 }, 40 }, 41 } 42 mockProtector := &mockSlasher.MockProtector{AllowAttestation: false} 43 validator.protector = mockProtector 44 err := validator.slashableAttestationCheck(context.Background(), att, pubKey, [32]byte{1}) 45 require.ErrorContains(t, failedPostAttSignExternalErr, err) 46 mockProtector.AllowAttestation = true 47 err = validator.slashableAttestationCheck(context.Background(), att, pubKey, [32]byte{1}) 48 require.NoError(t, err, "Expected allowed attestation not to throw error") 49 } 50 51 func Test_slashableAttestationCheck_UpdatesLowestSignedEpochs(t *testing.T) { 52 config := &featureconfig.Flags{ 53 SlasherProtection: true, 54 } 55 reset := featureconfig.InitWithReset(config) 56 defer reset() 57 validator, m, validatorKey, finish := setup(t) 58 defer finish() 59 ctx := context.Background() 60 pubKey := [48]byte{} 61 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 62 att := ðpb.IndexedAttestation{ 63 AttestingIndices: []uint64{1, 2}, 64 Data: ðpb.AttestationData{ 65 Slot: 5, 66 CommitteeIndex: 2, 67 BeaconBlockRoot: bytesutil.PadTo([]byte("great block"), 32), 68 Source: ðpb.Checkpoint{ 69 Epoch: 4, 70 Root: bytesutil.PadTo([]byte("good source"), 32), 71 }, 72 Target: ðpb.Checkpoint{ 73 Epoch: 10, 74 Root: bytesutil.PadTo([]byte("good target"), 32), 75 }, 76 }, 77 } 78 mockProtector := &mockSlasher.MockProtector{AllowAttestation: false} 79 validator.protector = mockProtector 80 m.validatorClient.EXPECT().DomainData( 81 gomock.Any(), // ctx 82 ðpb.DomainRequest{Epoch: 10, Domain: []byte{1, 0, 0, 0}}, 83 ).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 84 _, sr, err := validator.getDomainAndSigningRoot(ctx, att.Data) 85 require.NoError(t, err) 86 mockProtector.AllowAttestation = true 87 err = validator.slashableAttestationCheck(context.Background(), att, pubKey, sr) 88 require.NoError(t, err) 89 differentSigningRoot := [32]byte{2} 90 err = validator.slashableAttestationCheck(context.Background(), att, pubKey, differentSigningRoot) 91 require.ErrorContains(t, "could not sign attestation", err) 92 93 e, exists, err := validator.db.LowestSignedSourceEpoch(context.Background(), pubKey) 94 require.NoError(t, err) 95 require.Equal(t, true, exists) 96 require.Equal(t, types.Epoch(4), e) 97 e, exists, err = validator.db.LowestSignedTargetEpoch(context.Background(), pubKey) 98 require.NoError(t, err) 99 require.Equal(t, true, exists) 100 require.Equal(t, types.Epoch(10), e) 101 } 102 103 func Test_slashableAttestationCheck_OK(t *testing.T) { 104 config := &featureconfig.Flags{ 105 SlasherProtection: false, 106 } 107 reset := featureconfig.InitWithReset(config) 108 defer reset() 109 ctx := context.Background() 110 validator, _, _, finish := setup(t) 111 defer finish() 112 att := ðpb.IndexedAttestation{ 113 AttestingIndices: []uint64{1, 2}, 114 Data: ðpb.AttestationData{ 115 Slot: 5, 116 CommitteeIndex: 2, 117 BeaconBlockRoot: []byte("great block"), 118 Source: ðpb.Checkpoint{ 119 Epoch: 4, 120 Root: []byte("good source"), 121 }, 122 Target: ðpb.Checkpoint{ 123 Epoch: 10, 124 Root: []byte("good target"), 125 }, 126 }, 127 } 128 sr := [32]byte{1} 129 fakePubkey := bytesutil.ToBytes48([]byte("test")) 130 err := validator.slashableAttestationCheck(ctx, att, fakePubkey, sr) 131 require.NoError(t, err, "Expected allowed attestation not to throw error") 132 } 133 134 func Test_slashableAttestationCheck_GenesisEpoch(t *testing.T) { 135 config := &featureconfig.Flags{ 136 SlasherProtection: false, 137 } 138 reset := featureconfig.InitWithReset(config) 139 defer reset() 140 ctx := context.Background() 141 validator, _, _, finish := setup(t) 142 defer finish() 143 att := ðpb.IndexedAttestation{ 144 AttestingIndices: []uint64{1, 2}, 145 Data: ðpb.AttestationData{ 146 Slot: 5, 147 CommitteeIndex: 2, 148 BeaconBlockRoot: bytesutil.PadTo([]byte("great block root"), 32), 149 Source: ðpb.Checkpoint{ 150 Epoch: 0, 151 Root: bytesutil.PadTo([]byte("great root"), 32), 152 }, 153 Target: ðpb.Checkpoint{ 154 Epoch: 0, 155 Root: bytesutil.PadTo([]byte("great root"), 32), 156 }, 157 }, 158 } 159 fakePubkey := bytesutil.ToBytes48([]byte("test")) 160 err := validator.slashableAttestationCheck(ctx, att, fakePubkey, [32]byte{}) 161 require.NoError(t, err, "Expected allowed attestation not to throw error") 162 e, exists, err := validator.db.LowestSignedSourceEpoch(context.Background(), fakePubkey) 163 require.NoError(t, err) 164 require.Equal(t, true, exists) 165 require.Equal(t, types.Epoch(0), e) 166 e, exists, err = validator.db.LowestSignedTargetEpoch(context.Background(), fakePubkey) 167 require.NoError(t, err) 168 require.Equal(t, true, exists) 169 require.Equal(t, types.Epoch(0), e) 170 }