github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/validate_proposer_slashing_test.go (about) 1 package sync 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/rand" 7 "reflect" 8 "testing" 9 "time" 10 11 lru "github.com/hashicorp/golang-lru" 12 pubsub "github.com/libp2p/go-libp2p-pubsub" 13 pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb" 14 types "github.com/prysmaticlabs/eth2-types" 15 "github.com/prysmaticlabs/go-bitfield" 16 mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 17 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 18 "github.com/prysmaticlabs/prysm/beacon-chain/p2p" 19 p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" 20 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 21 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" 22 mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" 23 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 24 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 25 "github.com/prysmaticlabs/prysm/shared/bls" 26 "github.com/prysmaticlabs/prysm/shared/params" 27 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 28 "github.com/prysmaticlabs/prysm/shared/testutil/require" 29 ) 30 31 func setupValidProposerSlashing(t *testing.T) (*ethpb.ProposerSlashing, iface.BeaconState) { 32 validators := make([]*ethpb.Validator, 100) 33 for i := 0; i < len(validators); i++ { 34 validators[i] = ðpb.Validator{ 35 EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, 36 Slashed: false, 37 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 38 WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, 39 ActivationEpoch: 0, 40 } 41 } 42 validatorBalances := make([]uint64, len(validators)) 43 for i := 0; i < len(validatorBalances); i++ { 44 validatorBalances[i] = params.BeaconConfig().MaxEffectiveBalance 45 } 46 47 currentSlot := types.Slot(0) 48 state, err := v1.InitializeFromProto(&pb.BeaconState{ 49 Validators: validators, 50 Slot: currentSlot, 51 Balances: validatorBalances, 52 Fork: &pb.Fork{ 53 CurrentVersion: params.BeaconConfig().GenesisForkVersion, 54 PreviousVersion: params.BeaconConfig().GenesisForkVersion, 55 Epoch: 0, 56 }, 57 Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), 58 RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), 59 60 StateRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot), 61 BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot), 62 LatestBlockHeader: ðpb.BeaconBlockHeader{}, 63 }) 64 require.NoError(t, err) 65 66 privKey, err := bls.RandKey() 67 require.NoError(t, err) 68 someRoot := [32]byte{1, 2, 3} 69 someRoot2 := [32]byte{4, 5, 6} 70 header1 := ðpb.SignedBeaconBlockHeader{ 71 Header: ðpb.BeaconBlockHeader{ 72 ProposerIndex: 1, 73 Slot: 0, 74 ParentRoot: someRoot[:], 75 StateRoot: someRoot[:], 76 BodyRoot: someRoot[:], 77 }, 78 } 79 header1.Signature, err = helpers.ComputeDomainAndSign(state, helpers.CurrentEpoch(state), header1.Header, params.BeaconConfig().DomainBeaconProposer, privKey) 80 require.NoError(t, err) 81 82 header2 := ðpb.SignedBeaconBlockHeader{ 83 Header: ðpb.BeaconBlockHeader{ 84 ProposerIndex: 1, 85 Slot: 0, 86 ParentRoot: someRoot2[:], 87 StateRoot: someRoot2[:], 88 BodyRoot: someRoot2[:], 89 }, 90 } 91 header2.Signature, err = helpers.ComputeDomainAndSign(state, helpers.CurrentEpoch(state), header2.Header, params.BeaconConfig().DomainBeaconProposer, privKey) 92 require.NoError(t, err) 93 94 slashing := ðpb.ProposerSlashing{ 95 Header_1: header1, 96 Header_2: header2, 97 } 98 val, err := state.ValidatorAtIndex(1) 99 require.NoError(t, err) 100 val.PublicKey = privKey.PublicKey().Marshal() 101 require.NoError(t, state.UpdateValidatorAtIndex(1, val)) 102 103 b := make([]byte, 32) 104 _, err = rand.Read(b) 105 require.NoError(t, err) 106 107 return slashing, state 108 } 109 110 func TestValidateProposerSlashing_ValidSlashing(t *testing.T) { 111 p := p2ptest.NewTestP2P(t) 112 ctx := context.Background() 113 114 slashing, s := setupValidProposerSlashing(t) 115 116 c, err := lru.New(10) 117 require.NoError(t, err) 118 r := &Service{ 119 cfg: &Config{ 120 P2P: p, 121 Chain: &mock.ChainService{State: s}, 122 InitialSync: &mockSync.Sync{IsSyncing: false}, 123 }, 124 seenProposerSlashingCache: c, 125 } 126 127 buf := new(bytes.Buffer) 128 _, err = p.Encoding().EncodeGossip(buf, slashing) 129 require.NoError(t, err) 130 topic := p2p.GossipTypeMapping[reflect.TypeOf(slashing)] 131 m := &pubsub.Message{ 132 Message: &pubsubpb.Message{ 133 Data: buf.Bytes(), 134 Topic: &topic, 135 }, 136 } 137 138 valid := r.validateProposerSlashing(ctx, "", m) == pubsub.ValidationAccept 139 assert.Equal(t, true, valid, "Failed validation") 140 assert.NotNil(t, m.ValidatorData, "Decoded message was not set on the message validator data") 141 } 142 143 func TestValidateProposerSlashing_ContextTimeout(t *testing.T) { 144 p := p2ptest.NewTestP2P(t) 145 146 slashing, state := setupValidProposerSlashing(t) 147 slashing.Header_1.Header.Slot = 100000000 148 err := state.SetJustificationBits(bitfield.Bitvector4{0x0F}) // 0b1111 149 require.NoError(t, err) 150 err = state.SetPreviousJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 0, Root: []byte{}}) 151 require.NoError(t, err) 152 ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) 153 defer cancel() 154 155 c, err := lru.New(10) 156 require.NoError(t, err) 157 r := &Service{ 158 cfg: &Config{ 159 P2P: p, 160 Chain: &mock.ChainService{State: state}, 161 InitialSync: &mockSync.Sync{IsSyncing: false}, 162 }, 163 seenProposerSlashingCache: c, 164 } 165 166 buf := new(bytes.Buffer) 167 _, err = p.Encoding().EncodeGossip(buf, slashing) 168 require.NoError(t, err) 169 topic := p2p.GossipTypeMapping[reflect.TypeOf(slashing)] 170 m := &pubsub.Message{ 171 Message: &pubsubpb.Message{ 172 Data: buf.Bytes(), 173 Topic: &topic, 174 }, 175 } 176 valid := r.validateProposerSlashing(ctx, "", m) == pubsub.ValidationAccept 177 assert.Equal(t, false, valid, "Slashing from the far distant future should have timed out and returned false") 178 } 179 180 func TestValidateProposerSlashing_Syncing(t *testing.T) { 181 p := p2ptest.NewTestP2P(t) 182 ctx := context.Background() 183 184 slashing, s := setupValidProposerSlashing(t) 185 186 r := &Service{ 187 cfg: &Config{ 188 P2P: p, 189 Chain: &mock.ChainService{State: s}, 190 InitialSync: &mockSync.Sync{IsSyncing: true}, 191 }, 192 } 193 194 buf := new(bytes.Buffer) 195 _, err := p.Encoding().EncodeGossip(buf, slashing) 196 require.NoError(t, err) 197 topic := p2p.GossipTypeMapping[reflect.TypeOf(slashing)] 198 m := &pubsub.Message{ 199 Message: &pubsubpb.Message{ 200 Data: buf.Bytes(), 201 Topic: &topic, 202 }, 203 } 204 valid := r.validateProposerSlashing(ctx, "", m) == pubsub.ValidationAccept 205 assert.Equal(t, false, valid, "Did not fail validation") 206 }