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] = &ethpb.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: &ethpb.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 := &ethpb.SignedBeaconBlockHeader{
    71  		Header: &ethpb.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 := &ethpb.SignedBeaconBlockHeader{
    83  		Header: &ethpb.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 := &ethpb.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(&ethpb.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  }