github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/validate_voluntary_exit_test.go (about)

     1  package sync
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/rand"
     7  	"reflect"
     8  	"testing"
     9  
    10  	lru "github.com/hashicorp/golang-lru"
    11  	pubsub "github.com/libp2p/go-libp2p-pubsub"
    12  	pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
    13  	mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
    14  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    15  	"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
    16  	p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
    17  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    18  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    19  	mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
    20  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    21  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    22  	"github.com/prysmaticlabs/prysm/shared/bls"
    23  	"github.com/prysmaticlabs/prysm/shared/params"
    24  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    25  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    26  )
    27  
    28  func setupValidExit(t *testing.T) (*ethpb.SignedVoluntaryExit, iface.BeaconState) {
    29  	exit := &ethpb.SignedVoluntaryExit{
    30  		Exit: &ethpb.VoluntaryExit{
    31  			ValidatorIndex: 0,
    32  			Epoch:          1 + params.BeaconConfig().ShardCommitteePeriod,
    33  		},
    34  	}
    35  	registry := []*ethpb.Validator{
    36  		{
    37  			ExitEpoch:       params.BeaconConfig().FarFutureEpoch,
    38  			ActivationEpoch: 0,
    39  		},
    40  	}
    41  	state, err := v1.InitializeFromProto(&pb.BeaconState{
    42  		Validators: registry,
    43  		Fork: &pb.Fork{
    44  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
    45  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
    46  		},
    47  		Slot: params.BeaconConfig().SlotsPerEpoch * 5,
    48  	})
    49  	require.NoError(t, err)
    50  	err = state.SetSlot(state.Slot() + params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)))
    51  	require.NoError(t, err)
    52  
    53  	priv, err := bls.RandKey()
    54  	require.NoError(t, err)
    55  	exit.Signature, err = helpers.ComputeDomainAndSign(state, helpers.CurrentEpoch(state), exit.Exit, params.BeaconConfig().DomainVoluntaryExit, priv)
    56  	require.NoError(t, err)
    57  
    58  	val, err := state.ValidatorAtIndex(0)
    59  	require.NoError(t, err)
    60  	val.PublicKey = priv.PublicKey().Marshal()
    61  	require.NoError(t, state.UpdateValidatorAtIndex(0, val))
    62  
    63  	b := make([]byte, 32)
    64  	_, err = rand.Read(b)
    65  	require.NoError(t, err)
    66  
    67  	return exit, state
    68  }
    69  
    70  func TestValidateVoluntaryExit_ValidExit(t *testing.T) {
    71  	p := p2ptest.NewTestP2P(t)
    72  	ctx := context.Background()
    73  
    74  	exit, s := setupValidExit(t)
    75  
    76  	c, err := lru.New(10)
    77  	require.NoError(t, err)
    78  	r := &Service{
    79  		cfg: &Config{
    80  			P2P: p,
    81  			Chain: &mock.ChainService{
    82  				State: s,
    83  			},
    84  			InitialSync: &mockSync.Sync{IsSyncing: false},
    85  		},
    86  		seenExitCache: c,
    87  	}
    88  
    89  	buf := new(bytes.Buffer)
    90  	_, err = p.Encoding().EncodeGossip(buf, exit)
    91  	require.NoError(t, err)
    92  	topic := p2p.GossipTypeMapping[reflect.TypeOf(exit)]
    93  	m := &pubsub.Message{
    94  		Message: &pubsubpb.Message{
    95  			Data:  buf.Bytes(),
    96  			Topic: &topic,
    97  		},
    98  	}
    99  	valid := r.validateVoluntaryExit(ctx, "", m) == pubsub.ValidationAccept
   100  	assert.Equal(t, true, valid, "Failed validation")
   101  	assert.NotNil(t, m.ValidatorData, "Decoded message was not set on the message validator data")
   102  }
   103  
   104  func TestValidateVoluntaryExit_InvalidExitSlot(t *testing.T) {
   105  	p := p2ptest.NewTestP2P(t)
   106  	ctx := context.Background()
   107  
   108  	exit, s := setupValidExit(t)
   109  	// Set state slot to 1 to cause exit object fail to verify.
   110  	require.NoError(t, s.SetSlot(1))
   111  	c, err := lru.New(10)
   112  	require.NoError(t, err)
   113  	r := &Service{
   114  		cfg: &Config{
   115  			P2P: p,
   116  			Chain: &mock.ChainService{
   117  				State: s,
   118  			},
   119  			InitialSync: &mockSync.Sync{IsSyncing: false},
   120  		},
   121  		seenExitCache: c,
   122  	}
   123  
   124  	buf := new(bytes.Buffer)
   125  	_, err = p.Encoding().EncodeGossip(buf, exit)
   126  	require.NoError(t, err)
   127  	topic := p2p.GossipTypeMapping[reflect.TypeOf(exit)]
   128  	m := &pubsub.Message{
   129  		Message: &pubsubpb.Message{
   130  			Data:  buf.Bytes(),
   131  			Topic: &topic,
   132  		},
   133  	}
   134  	valid := r.validateVoluntaryExit(ctx, "", m) == pubsub.ValidationAccept
   135  	assert.Equal(t, false, valid, "passed validation")
   136  }
   137  
   138  func TestValidateVoluntaryExit_ValidExit_Syncing(t *testing.T) {
   139  	p := p2ptest.NewTestP2P(t)
   140  	ctx := context.Background()
   141  
   142  	exit, s := setupValidExit(t)
   143  
   144  	r := &Service{
   145  		cfg: &Config{
   146  			P2P: p,
   147  			Chain: &mock.ChainService{
   148  				State: s,
   149  			},
   150  			InitialSync: &mockSync.Sync{IsSyncing: true},
   151  		},
   152  	}
   153  	buf := new(bytes.Buffer)
   154  	_, err := p.Encoding().EncodeGossip(buf, exit)
   155  	require.NoError(t, err)
   156  	topic := p2p.GossipTypeMapping[reflect.TypeOf(exit)]
   157  	m := &pubsub.Message{
   158  		Message: &pubsubpb.Message{
   159  			Data:  buf.Bytes(),
   160  			Topic: &topic,
   161  		},
   162  	}
   163  	valid := r.validateVoluntaryExit(ctx, "", m) == pubsub.ValidationAccept
   164  	assert.Equal(t, false, valid, "Validation should have failed")
   165  }