github.com/prysmaticlabs/prysm@v1.4.4/validator/client/propose_protect_test.go (about) 1 package client 2 3 import ( 4 "context" 5 "testing" 6 7 types "github.com/prysmaticlabs/eth2-types" 8 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 9 "github.com/prysmaticlabs/prysm/shared/featureconfig" 10 "github.com/prysmaticlabs/prysm/shared/testutil" 11 "github.com/prysmaticlabs/prysm/shared/testutil/require" 12 mockSlasher "github.com/prysmaticlabs/prysm/validator/testing" 13 ) 14 15 func TestPreBlockSignLocalValidation_PreventsLowerThanMinProposal(t *testing.T) { 16 ctx := context.Background() 17 validator, _, validatorKey, finish := setup(t) 18 defer finish() 19 lowestSignedSlot := types.Slot(10) 20 pubKeyBytes := [48]byte{} 21 copy(pubKeyBytes[:], validatorKey.PublicKey().Marshal()) 22 23 // We save a proposal at the lowest signed slot in the DB. 24 err := validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, lowestSignedSlot, []byte{1}) 25 require.NoError(t, err) 26 require.NoError(t, err) 27 28 // We expect the same block with a slot lower than the lowest 29 // signed slot to fail validation. 30 block := ðpb.BeaconBlock{ 31 Slot: lowestSignedSlot - 1, 32 ProposerIndex: 0, 33 } 34 err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, block, [32]byte{4}) 35 require.ErrorContains(t, "could not sign block with slot <= lowest signed", err) 36 37 // We expect the same block with a slot equal to the lowest 38 // signed slot to pass validation if signing roots are equal. 39 block = ðpb.BeaconBlock{ 40 Slot: lowestSignedSlot, 41 ProposerIndex: 0, 42 } 43 err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, block, [32]byte{1}) 44 require.NoError(t, err) 45 46 // We expect the same block with a slot equal to the lowest 47 // signed slot to fail validation if signing roots are different. 48 block = ðpb.BeaconBlock{ 49 Slot: lowestSignedSlot, 50 ProposerIndex: 0, 51 } 52 err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, block, [32]byte{4}) 53 require.ErrorContains(t, failedPreBlockSignLocalErr, err) 54 55 // We expect the same block with a slot > than the lowest 56 // signed slot to pass validation. 57 block = ðpb.BeaconBlock{ 58 Slot: lowestSignedSlot + 1, 59 ProposerIndex: 0, 60 } 61 err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, block, [32]byte{3}) 62 require.NoError(t, err) 63 } 64 65 func TestPreBlockSignLocalValidation(t *testing.T) { 66 ctx := context.Background() 67 config := &featureconfig.Flags{ 68 SlasherProtection: false, 69 } 70 reset := featureconfig.InitWithReset(config) 71 defer reset() 72 validator, _, validatorKey, finish := setup(t) 73 defer finish() 74 75 block := ðpb.BeaconBlock{ 76 Slot: 10, 77 ProposerIndex: 0, 78 } 79 pubKeyBytes := [48]byte{} 80 copy(pubKeyBytes[:], validatorKey.PublicKey().Marshal()) 81 82 // We save a proposal at slot 1 as our lowest proposal. 83 err := validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, 1, []byte{1}) 84 require.NoError(t, err) 85 86 // We save a proposal at slot 10 with a dummy signing root. 87 dummySigningRoot := [32]byte{1} 88 err = validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, 10, dummySigningRoot[:]) 89 require.NoError(t, err) 90 pubKey := [48]byte{} 91 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 92 93 // We expect the same block sent out with the same root should not be slasahble. 94 err = validator.preBlockSignValidations(context.Background(), pubKey, block, dummySigningRoot) 95 require.NoError(t, err) 96 97 // We expect the same block sent out with a different signing root should be slasahble. 98 err = validator.preBlockSignValidations(context.Background(), pubKey, block, [32]byte{2}) 99 require.ErrorContains(t, failedPreBlockSignLocalErr, err) 100 101 // We save a proposal at slot 11 with a nil signing root. 102 block.Slot = 11 103 err = validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, block.Slot, nil) 104 require.NoError(t, err) 105 106 // We expect the same block sent out should return slashable error even 107 // if we had a nil signing root stored in the database. 108 err = validator.preBlockSignValidations(context.Background(), pubKey, block, [32]byte{2}) 109 require.ErrorContains(t, failedPreBlockSignLocalErr, err) 110 111 // A block with a different slot for which we do not have a proposing history 112 // should not be failing validation. 113 block.Slot = 9 114 err = validator.preBlockSignValidations(context.Background(), pubKey, block, [32]byte{3}) 115 require.NoError(t, err, "Expected allowed block not to throw error") 116 } 117 118 func TestPreBlockSignValidation(t *testing.T) { 119 config := &featureconfig.Flags{ 120 SlasherProtection: true, 121 } 122 reset := featureconfig.InitWithReset(config) 123 defer reset() 124 validator, _, validatorKey, finish := setup(t) 125 defer finish() 126 pubKey := [48]byte{} 127 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 128 129 block := testutil.NewBeaconBlock() 130 block.Block.Slot = 10 131 mockProtector := &mockSlasher.MockProtector{AllowBlock: false} 132 validator.protector = mockProtector 133 err := validator.preBlockSignValidations(context.Background(), pubKey, block.Block, [32]byte{2}) 134 require.ErrorContains(t, failedPreBlockSignExternalErr, err) 135 mockProtector.AllowBlock = true 136 err = validator.preBlockSignValidations(context.Background(), pubKey, block.Block, [32]byte{2}) 137 require.NoError(t, err, "Expected allowed block not to throw error") 138 } 139 140 func TestPostBlockSignUpdate(t *testing.T) { 141 config := &featureconfig.Flags{ 142 SlasherProtection: true, 143 } 144 reset := featureconfig.InitWithReset(config) 145 defer reset() 146 validator, _, validatorKey, finish := setup(t) 147 defer finish() 148 pubKey := [48]byte{} 149 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 150 emptyBlock := testutil.NewBeaconBlock() 151 emptyBlock.Block.Slot = 10 152 emptyBlock.Block.ProposerIndex = 0 153 mockProtector := &mockSlasher.MockProtector{AllowBlock: false} 154 validator.protector = mockProtector 155 err := validator.postBlockSignUpdate(context.Background(), pubKey, emptyBlock, [32]byte{}) 156 require.ErrorContains(t, failedPostBlockSignErr, err, "Expected error when post signature update is detected as slashable") 157 mockProtector.AllowBlock = true 158 err = validator.postBlockSignUpdate(context.Background(), pubKey, emptyBlock, [32]byte{}) 159 require.NoError(t, err, "Expected allowed block not to throw error") 160 }