github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/mps_test.go (about)

     1  package gossip
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/unicornultrafoundation/go-u2u/common"
     9  
    10  	"github.com/unicornultrafoundation/go-helios/hash"
    11  	"github.com/unicornultrafoundation/go-helios/native/idx"
    12  	"github.com/unicornultrafoundation/go-u2u/eventcheck/basiccheck"
    13  	"github.com/unicornultrafoundation/go-u2u/eventcheck/heavycheck"
    14  	"github.com/unicornultrafoundation/go-u2u/logger"
    15  	"github.com/unicornultrafoundation/go-u2u/native"
    16  )
    17  
    18  func copyBvs(bvs native.LlrSignedBlockVotes) native.LlrSignedBlockVotes {
    19  	cp := make([]hash.Hash, 0, len(bvs.Val.Votes))
    20  	for _, v := range bvs.Val.Votes {
    21  		cp = append(cp, v)
    22  	}
    23  	bvs.Val.Votes = cp
    24  	return bvs
    25  }
    26  
    27  func copyMP(mp native.MisbehaviourProof) native.MisbehaviourProof {
    28  	if mp.EventsDoublesign != nil {
    29  		cp := *mp.EventsDoublesign
    30  		mp.EventsDoublesign = &cp
    31  	}
    32  	if mp.BlockVoteDoublesign != nil {
    33  		cp := *mp.BlockVoteDoublesign
    34  		mp.BlockVoteDoublesign = &cp
    35  		for i := range mp.BlockVoteDoublesign.Pair {
    36  			mp.BlockVoteDoublesign.Pair[i] = copyBvs(mp.BlockVoteDoublesign.Pair[i])
    37  		}
    38  	}
    39  	if mp.WrongBlockVote != nil {
    40  		cp := *mp.WrongBlockVote
    41  		mp.WrongBlockVote = &cp
    42  		for i := range mp.WrongBlockVote.Pals {
    43  			mp.WrongBlockVote.Pals[i] = copyBvs(mp.WrongBlockVote.Pals[i])
    44  		}
    45  	}
    46  	if mp.EpochVoteDoublesign != nil {
    47  		cp := *mp.EpochVoteDoublesign
    48  		mp.EpochVoteDoublesign = &cp
    49  	}
    50  	if mp.WrongEpochVote != nil {
    51  		cp := *mp.WrongEpochVote
    52  		mp.WrongEpochVote = &cp
    53  	}
    54  	return mp
    55  }
    56  
    57  func TestMisbehaviourProofsEventsDoublesign(t *testing.T) {
    58  	logger.SetTestMode(t)
    59  	require := require.New(t)
    60  
    61  	const validatorsNum = 3
    62  
    63  	startEpoch := idx.Epoch(basiccheck.MaxLiableEpochs)
    64  	env := newTestEnv(startEpoch, validatorsNum)
    65  	defer env.Close()
    66  
    67  	// move epoch further
    68  	_, err := env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
    69  	require.NoError(err)
    70  	_, err = env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
    71  	require.NoError(err)
    72  	require.Greater(env.store.GetEpoch(), startEpoch)
    73  
    74  	correctMp := native.MisbehaviourProof{
    75  		EventsDoublesign: &native.EventsDoublesign{
    76  			Pair: [2]native.SignedEventLocator{
    77  				{
    78  					Locator: native.EventLocator{
    79  						Epoch:   startEpoch,
    80  						Seq:     1,
    81  						Lamport: 1,
    82  						Creator: 1,
    83  					},
    84  				},
    85  				{
    86  					Locator: native.EventLocator{
    87  						Epoch:   startEpoch,
    88  						Seq:     1,
    89  						Lamport: 2,
    90  						Creator: 1,
    91  					},
    92  				},
    93  			},
    94  		},
    95  	}
    96  
    97  	// sign
    98  	for i, p := range correctMp.EventsDoublesign.Pair {
    99  		sig, err := env.signer.Sign(env.pubkeys[0], p.Locator.HashToSign().Bytes())
   100  		require.NoError(err)
   101  		copy(correctMp.EventsDoublesign.Pair[i].Sig[:], sig)
   102  	}
   103  
   104  	tooLateMp := copyMP(correctMp)
   105  	tooLateMp.EventsDoublesign.Pair[0].Locator.Epoch = 1
   106  	tooLateMp.EventsDoublesign.Pair[1].Locator.Epoch = 1
   107  	err = env.ApplyMPs(nextEpoch, tooLateMp)
   108  	require.ErrorIs(err, basiccheck.ErrMPTooLate)
   109  
   110  	wrongEpochMp := copyMP(correctMp)
   111  	wrongEpochMp.EventsDoublesign.Pair[0].Locator.Epoch--
   112  	err = env.ApplyMPs(nextEpoch, wrongEpochMp)
   113  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   114  
   115  	wrongSeqMp := copyMP(correctMp)
   116  	wrongSeqMp.EventsDoublesign.Pair[0].Locator.Seq--
   117  	err = env.ApplyMPs(nextEpoch, wrongSeqMp)
   118  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   119  
   120  	wrongCreatorMp := copyMP(correctMp)
   121  	wrongCreatorMp.EventsDoublesign.Pair[0].Locator.Creator++
   122  	err = env.ApplyMPs(nextEpoch, wrongCreatorMp)
   123  	require.ErrorIs(err, basiccheck.ErrWrongCreatorMP)
   124  
   125  	sameEventsMp := copyMP(correctMp)
   126  	sameEventsMp.EventsDoublesign.Pair[0] = sameEventsMp.EventsDoublesign.Pair[1]
   127  	err = env.ApplyMPs(nextEpoch, sameEventsMp)
   128  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   129  
   130  	for i := range correctMp.EventsDoublesign.Pair {
   131  		wrongSigMp := copyMP(correctMp)
   132  		wrongSigMp.EventsDoublesign.Pair[i].Sig[0]++
   133  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   134  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   135  	}
   136  
   137  	for i := range correctMp.EventsDoublesign.Pair {
   138  		wrongSigMp := copyMP(correctMp)
   139  		wrongSigMp.EventsDoublesign.Pair[i].Locator.BaseHash = hash.HexToHash("0x10")
   140  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   141  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   142  	}
   143  
   144  	wrongAuthEpochMp := copyMP(correctMp)
   145  	wrongAuthEpochMp.EventsDoublesign.Pair[0].Locator.Epoch = startEpoch - 1
   146  	wrongAuthEpochMp.EventsDoublesign.Pair[1].Locator.Epoch = startEpoch - 1
   147  	err = env.ApplyMPs(nextEpoch, wrongAuthEpochMp)
   148  	require.ErrorIs(err, heavycheck.ErrUnknownEpochEventLocator)
   149  
   150  	err = env.ApplyMPs(nextEpoch, correctMp)
   151  	require.NoError(err)
   152  	require.Equal(idx.Validator(2), env.store.GetValidators().Len())
   153  	require.False(env.store.GetValidators().Exists(1))
   154  }
   155  
   156  func TestMisbehaviourProofsBlockVoteDoublesign(t *testing.T) {
   157  	logger.SetTestMode(t)
   158  	require := require.New(t)
   159  
   160  	const validatorsNum = 3
   161  
   162  	startEpoch := idx.Epoch(basiccheck.MaxLiableEpochs)
   163  	env := newTestEnv(basiccheck.MaxLiableEpochs, validatorsNum)
   164  	defer env.Close()
   165  
   166  	// move epoch further
   167  	_, err := env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   168  	require.NoError(err)
   169  	_, err = env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   170  	require.NoError(err)
   171  	require.Greater(env.store.GetEpoch(), startEpoch)
   172  
   173  	correctMp := native.MisbehaviourProof{
   174  		BlockVoteDoublesign: &native.BlockVoteDoublesign{
   175  			Block: env.store.GetLatestBlockIndex(),
   176  			Pair: [2]native.LlrSignedBlockVotes{
   177  				{
   178  					Val: native.LlrBlockVotes{
   179  						Start: env.store.GetLatestBlockIndex() - 1,
   180  						Epoch: startEpoch,
   181  						Votes: []hash.Hash{
   182  							hash.Zero,
   183  							hash.HexToHash("0x01"),
   184  						},
   185  					},
   186  				},
   187  				{
   188  					Val: native.LlrBlockVotes{
   189  						Start: env.store.GetLatestBlockIndex(),
   190  						Epoch: startEpoch,
   191  						Votes: []hash.Hash{
   192  							hash.HexToHash("0x02"),
   193  						},
   194  					},
   195  				},
   196  			},
   197  		},
   198  	}
   199  
   200  	// sign
   201  	for i, p := range correctMp.BlockVoteDoublesign.Pair {
   202  		e := &native.MutableEventPayload{}
   203  		e.SetVersion(1)
   204  		e.SetBlockVotes(p.Val)
   205  		e.SetEpoch(env.store.GetEpoch() - idx.Epoch(i))
   206  		e.SetCreator(2)
   207  		e.SetPayloadHash(native.CalcPayloadHash(e))
   208  
   209  		sig, err := env.signer.Sign(env.pubkeys[1], e.HashToSign().Bytes())
   210  		require.NoError(err)
   211  		sSig := native.Signature{}
   212  		copy(sSig[:], sig)
   213  		e.SetSig(sSig)
   214  
   215  		correctMp.BlockVoteDoublesign.Pair[i] = native.AsSignedBlockVotes(e)
   216  	}
   217  
   218  	sameVotesMp := copyMP(correctMp)
   219  	sameVotesMp.BlockVoteDoublesign.Pair[0].Val.Votes[1] = sameVotesMp.BlockVoteDoublesign.Pair[1].Val.Votes[0]
   220  	err = env.ApplyMPs(nextEpoch, sameVotesMp)
   221  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   222  
   223  	differentEpochsMp := sameVotesMp
   224  	differentEpochsMp.BlockVoteDoublesign.Pair[0].Val.Epoch++
   225  	err = env.ApplyMPs(nextEpoch, sameVotesMp)
   226  	require.ErrorIs(err, heavycheck.ErrWrongPayloadHash)
   227  
   228  	for i := range correctMp.BlockVoteDoublesign.Pair {
   229  		malformedVotesMp := copyMP(correctMp)
   230  		malformedVotesMp.BlockVoteDoublesign.Pair[i].Val.Votes = []hash.Hash{}
   231  		err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   232  		require.ErrorIs(err, basiccheck.MalformedBVs)
   233  	}
   234  	for i := range correctMp.BlockVoteDoublesign.Pair {
   235  		malformedVotesMp := copyMP(correctMp)
   236  		malformedVotesMp.BlockVoteDoublesign.Pair[i].Val.Start -= 2
   237  		err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   238  		require.ErrorIs(err, basiccheck.ErrWrongMP)
   239  	}
   240  	malformedVotesMp := copyMP(correctMp)
   241  	malformedVotesMp.BlockVoteDoublesign.Pair[1].Val.Start--
   242  	err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   243  	require.ErrorIs(err, basiccheck.ErrWrongMP)
   244  
   245  	for i := range correctMp.BlockVoteDoublesign.Pair {
   246  		tooLateMp := copyMP(correctMp)
   247  		tooLateMp.BlockVoteDoublesign.Pair[i].Val.Epoch = 1
   248  		err = env.ApplyMPs(nextEpoch, tooLateMp)
   249  		require.ErrorIs(err, basiccheck.ErrMPTooLate)
   250  	}
   251  
   252  	for i := range correctMp.BlockVoteDoublesign.Pair {
   253  		futureEpochMp := copyMP(correctMp)
   254  		futureEpochMp.BlockVoteDoublesign.Pair[i].Signed.Locator.Epoch = futureEpochMp.BlockVoteDoublesign.Pair[i].Val.Epoch - 1
   255  		err = env.ApplyMPs(nextEpoch, futureEpochMp)
   256  		require.ErrorIs(err, basiccheck.FutureBVsEpoch)
   257  	}
   258  
   259  	wrongCreatorMp := copyMP(correctMp)
   260  	wrongCreatorMp.BlockVoteDoublesign.Pair[0].Signed.Locator.Creator++
   261  	err = env.ApplyMPs(nextEpoch, wrongCreatorMp)
   262  	require.ErrorIs(err, basiccheck.ErrWrongCreatorMP)
   263  
   264  	sameEventsMp := copyMP(correctMp)
   265  	sameEventsMp.BlockVoteDoublesign.Pair[0] = sameEventsMp.BlockVoteDoublesign.Pair[1]
   266  	err = env.ApplyMPs(nextEpoch, sameEventsMp)
   267  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   268  
   269  	for i := range correctMp.BlockVoteDoublesign.Pair {
   270  		wrongSigMp := copyMP(correctMp)
   271  		wrongSigMp.BlockVoteDoublesign.Pair[i].Signed.Sig[0]++
   272  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   273  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   274  	}
   275  
   276  	for i := range correctMp.BlockVoteDoublesign.Pair {
   277  		wrongSigMp := copyMP(correctMp)
   278  		wrongSigMp.BlockVoteDoublesign.Pair[i].Signed.Locator.BaseHash = hash.HexToHash("0x10")
   279  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   280  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   281  	}
   282  
   283  	wrongAuthEpochMp := copyMP(correctMp)
   284  	wrongAuthEpochMp.BlockVoteDoublesign.Pair[0].Signed.Locator.Epoch = startEpoch - 1
   285  	wrongAuthEpochMp.BlockVoteDoublesign.Pair[0].Val.Epoch = startEpoch - 1
   286  	wrongAuthEpochMp.BlockVoteDoublesign.Pair[1].Signed.Locator.Epoch = startEpoch - 1
   287  	wrongAuthEpochMp.BlockVoteDoublesign.Pair[1].Val.Epoch = startEpoch - 1
   288  	err = env.ApplyMPs(nextEpoch, wrongAuthEpochMp)
   289  	require.ErrorIs(err, heavycheck.ErrUnknownEpochBVs)
   290  
   291  	err = env.ApplyMPs(nextEpoch, correctMp)
   292  	require.NoError(err)
   293  	require.Equal(idx.Validator(2), env.store.GetValidators().Len())
   294  	require.False(env.store.GetValidators().Exists(2))
   295  }
   296  
   297  func TestMisbehaviourProofsWrongBlockVote(t *testing.T) {
   298  	logger.SetTestMode(t)
   299  	require := require.New(t)
   300  
   301  	const validatorsNum = 3
   302  
   303  	startEpoch := idx.Epoch(basiccheck.MaxLiableEpochs)
   304  	env := newTestEnv(startEpoch, validatorsNum)
   305  	defer env.Close()
   306  
   307  	// move epoch further
   308  	_, err := env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   309  	require.NoError(err)
   310  	_, err = env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   311  	require.NoError(err)
   312  	require.Greater(env.store.GetEpoch(), startEpoch)
   313  
   314  	correctMp := native.MisbehaviourProof{
   315  		WrongBlockVote: &native.WrongBlockVote{
   316  			Block: env.store.GetLatestBlockIndex(),
   317  			Pals: [2]native.LlrSignedBlockVotes{
   318  				{
   319  					Val: native.LlrBlockVotes{
   320  						Start: env.store.GetLatestBlockIndex() - 1,
   321  						Epoch: startEpoch,
   322  						Votes: []hash.Hash{
   323  							hash.Zero,
   324  							hash.HexToHash("0x01"),
   325  						},
   326  					},
   327  				},
   328  				{
   329  					Val: native.LlrBlockVotes{
   330  						Start: env.store.GetLatestBlockIndex(),
   331  						Epoch: startEpoch + 1,
   332  						Votes: []hash.Hash{
   333  							hash.HexToHash("0x01"),
   334  						},
   335  					},
   336  				},
   337  			},
   338  			WrongEpoch: false,
   339  		},
   340  	}
   341  
   342  	sign := func(mp *native.MisbehaviourProof) {
   343  		// sign
   344  		for i, p := range mp.WrongBlockVote.Pals {
   345  			e := &native.MutableEventPayload{}
   346  			e.SetVersion(1)
   347  			e.SetBlockVotes(p.Val)
   348  			e.SetEpoch(env.store.GetEpoch() - idx.Epoch(i))
   349  			e.SetCreator(idx.ValidatorID(i + 1))
   350  			e.SetPayloadHash(native.CalcPayloadHash(e))
   351  
   352  			sig, err := env.signer.Sign(env.pubkeys[i], e.HashToSign().Bytes())
   353  			require.NoError(err)
   354  			sSig := native.Signature{}
   355  			copy(sSig[:], sig)
   356  			e.SetSig(sSig)
   357  
   358  			mp.WrongBlockVote.Pals[i] = native.AsSignedBlockVotes(e)
   359  		}
   360  	}
   361  	sign(&correctMp)
   362  
   363  	differentVotesMp := copyMP(correctMp)
   364  	differentVotesMp.WrongBlockVote.Pals[0].Val.Votes[1] = hash.HexToHash("0x02")
   365  	err = env.ApplyMPs(nextEpoch, differentVotesMp)
   366  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   367  
   368  	for i := range correctMp.WrongBlockVote.Pals {
   369  		malformedVotesMp := copyMP(correctMp)
   370  		malformedVotesMp.WrongBlockVote.Pals[i].Val.Votes = []hash.Hash{}
   371  		err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   372  		require.ErrorIs(err, basiccheck.MalformedBVs)
   373  	}
   374  	for i := range correctMp.WrongBlockVote.Pals {
   375  		malformedVotesMp := copyMP(correctMp)
   376  		malformedVotesMp.WrongBlockVote.Pals[i].Val.Start -= 2
   377  		err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   378  		require.ErrorIs(err, basiccheck.ErrWrongMP)
   379  	}
   380  	malformedVotesMp := copyMP(correctMp)
   381  	malformedVotesMp.WrongBlockVote.Pals[1].Val.Start--
   382  	err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   383  	require.ErrorIs(err, basiccheck.ErrWrongMP)
   384  
   385  	for i := range correctMp.WrongBlockVote.Pals {
   386  		tooLateMp := copyMP(correctMp)
   387  		tooLateMp.WrongBlockVote.Pals[i].Val.Epoch = 1
   388  		err = env.ApplyMPs(nextEpoch, tooLateMp)
   389  		require.ErrorIs(err, basiccheck.ErrMPTooLate)
   390  	}
   391  
   392  	for i := range correctMp.WrongBlockVote.Pals {
   393  		futureEpochMp := copyMP(correctMp)
   394  		futureEpochMp.WrongBlockVote.Pals[i].Signed.Locator.Epoch = futureEpochMp.WrongBlockVote.Pals[i].Val.Epoch - 1
   395  		err = env.ApplyMPs(nextEpoch, futureEpochMp)
   396  		require.ErrorIs(err, basiccheck.FutureBVsEpoch)
   397  	}
   398  
   399  	sameCreatorMp := copyMP(correctMp)
   400  	sameCreatorMp.WrongBlockVote.Pals[0].Signed.Locator.Creator = sameCreatorMp.WrongBlockVote.Pals[1].Signed.Locator.Creator
   401  	err = env.ApplyMPs(nextEpoch, sameCreatorMp)
   402  	require.ErrorIs(err, basiccheck.ErrWrongCreatorMP)
   403  
   404  	for i := range correctMp.WrongBlockVote.Pals {
   405  		wrongSigMp := copyMP(correctMp)
   406  		wrongSigMp.WrongBlockVote.Pals[i].Signed.Sig[0]++
   407  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   408  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   409  	}
   410  
   411  	for i := range correctMp.WrongBlockVote.Pals {
   412  		wrongSigMp := copyMP(correctMp)
   413  		wrongSigMp.WrongBlockVote.Pals[i].Signed.Locator.BaseHash = hash.HexToHash("0x10")
   414  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   415  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   416  	}
   417  
   418  	wrongAuthEpochMp := copyMP(correctMp)
   419  	wrongAuthEpochMp.WrongBlockVote.Pals[0].Signed.Locator.Epoch = startEpoch - 1
   420  	wrongAuthEpochMp.WrongBlockVote.Pals[0].Val.Epoch = startEpoch - 1
   421  	wrongAuthEpochMp.WrongBlockVote.Pals[1].Signed.Locator.Epoch = startEpoch - 1
   422  	wrongAuthEpochMp.WrongBlockVote.Pals[1].Val.Epoch = startEpoch - 1
   423  	err = env.ApplyMPs(nextEpoch, wrongAuthEpochMp)
   424  	require.ErrorIs(err, heavycheck.ErrUnknownEpochBVs)
   425  
   426  	goodVotesMp := copyMP(correctMp)
   427  	goodVotesMp.WrongBlockVote.Pals[0].Val.Votes[1] = env.store.GetFullBlockRecord(goodVotesMp.WrongBlockVote.Block).Hash()
   428  	goodVotesMp.WrongBlockVote.Pals[1].Val.Votes[0] = env.store.GetFullBlockRecord(goodVotesMp.WrongBlockVote.Block).Hash()
   429  	err = env.ApplyMPs(nextEpoch, goodVotesMp)
   430  	require.ErrorIs(err, heavycheck.ErrWrongPayloadHash)
   431  	sign(&goodVotesMp)
   432  	err = env.ApplyMPs(nextEpoch, goodVotesMp)
   433  	require.NoError(err)
   434  	require.Equal(idx.Validator(3), env.store.GetValidators().Len())
   435  
   436  	err = env.ApplyMPs(nextEpoch, correctMp)
   437  	require.NoError(err)
   438  	require.Equal(idx.Validator(1), env.store.GetValidators().Len())
   439  	require.False(env.store.GetValidators().Exists(1))
   440  	require.False(env.store.GetValidators().Exists(2))
   441  }
   442  
   443  func TestMisbehaviourProofsWrongBlockEpoch(t *testing.T) {
   444  	logger.SetTestMode(t)
   445  	require := require.New(t)
   446  
   447  	const validatorsNum = 3
   448  
   449  	startEpoch := idx.Epoch(basiccheck.MaxLiableEpochs)
   450  	env := newTestEnv(startEpoch, validatorsNum)
   451  	defer env.Close()
   452  
   453  	// move epoch further
   454  	_, err := env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   455  	require.NoError(err)
   456  	_, err = env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   457  	require.NoError(err)
   458  	require.Greater(env.store.GetEpoch(), startEpoch)
   459  
   460  	correctMp := native.MisbehaviourProof{
   461  		WrongBlockVote: &native.WrongBlockVote{
   462  			Block: env.store.GetLatestBlockIndex(),
   463  			Pals: [2]native.LlrSignedBlockVotes{
   464  				{
   465  					Val: native.LlrBlockVotes{
   466  						Start: env.store.GetLatestBlockIndex() - 1,
   467  						Epoch: startEpoch,
   468  						Votes: []hash.Hash{
   469  							hash.Zero,
   470  							hash.HexToHash("0x01"),
   471  						},
   472  					},
   473  				},
   474  				{
   475  					Val: native.LlrBlockVotes{
   476  						Start: env.store.GetLatestBlockIndex(),
   477  						Epoch: startEpoch,
   478  						Votes: []hash.Hash{
   479  							hash.HexToHash("0x02"),
   480  						},
   481  					},
   482  				},
   483  			},
   484  			WrongEpoch: true,
   485  		},
   486  	}
   487  	require.Greater(env.store.GetEpoch(), correctMp.WrongBlockVote.Pals[0].Val.Epoch)
   488  
   489  	// sign
   490  	sign := func(mp *native.MisbehaviourProof) {
   491  		for i, p := range mp.WrongBlockVote.Pals {
   492  			e := &native.MutableEventPayload{}
   493  			e.SetVersion(1)
   494  			e.SetBlockVotes(p.Val)
   495  			e.SetEpoch(env.store.GetEpoch() - idx.Epoch(i))
   496  			e.SetCreator(idx.ValidatorID(i + 1))
   497  			e.SetPayloadHash(native.CalcPayloadHash(e))
   498  
   499  			sig, err := env.signer.Sign(env.pubkeys[i], e.HashToSign().Bytes())
   500  			require.NoError(err)
   501  			sSig := native.Signature{}
   502  			copy(sSig[:], sig)
   503  			e.SetSig(sSig)
   504  
   505  			mp.WrongBlockVote.Pals[i] = native.AsSignedBlockVotes(e)
   506  		}
   507  	}
   508  	sign(&correctMp)
   509  
   510  	// it allows same votes, as it failed verification only on last step
   511  	sameVotesMp := copyMP(correctMp)
   512  	sameVotesMp.WrongBlockVote.Pals[0].Val.Votes[1] = sameVotesMp.WrongBlockVote.Pals[1].Val.Votes[0]
   513  	err = env.ApplyMPs(nextEpoch, sameVotesMp)
   514  	require.ErrorIs(err, heavycheck.ErrWrongPayloadHash)
   515  
   516  	differentEpochsMp := copyMP(correctMp)
   517  	differentEpochsMp.WrongBlockVote.Pals[0].Val.Epoch++
   518  	err = env.ApplyMPs(nextEpoch, differentEpochsMp)
   519  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   520  
   521  	for i := range correctMp.WrongBlockVote.Pals {
   522  		malformedVotesMp := copyMP(correctMp)
   523  		malformedVotesMp.WrongBlockVote.Pals[i].Val.Votes = []hash.Hash{}
   524  		err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   525  		require.ErrorIs(err, basiccheck.MalformedBVs)
   526  	}
   527  	for i := range correctMp.WrongBlockVote.Pals {
   528  		malformedVotesMp := copyMP(correctMp)
   529  		malformedVotesMp.WrongBlockVote.Pals[i].Val.Start -= 2
   530  		err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   531  		require.ErrorIs(err, basiccheck.ErrWrongMP)
   532  	}
   533  	malformedVotesMp := copyMP(correctMp)
   534  	malformedVotesMp.WrongBlockVote.Pals[1].Val.Start--
   535  	err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   536  	require.ErrorIs(err, basiccheck.ErrWrongMP)
   537  
   538  	for i := range correctMp.WrongBlockVote.Pals {
   539  		tooLateMp := copyMP(correctMp)
   540  		tooLateMp.WrongBlockVote.Pals[i].Val.Epoch = 1
   541  		err = env.ApplyMPs(nextEpoch, tooLateMp)
   542  		require.ErrorIs(err, basiccheck.ErrMPTooLate)
   543  	}
   544  
   545  	for i := range correctMp.WrongBlockVote.Pals {
   546  		futureEpochMp := copyMP(correctMp)
   547  		futureEpochMp.WrongBlockVote.Pals[i].Signed.Locator.Epoch = futureEpochMp.WrongBlockVote.Pals[i].Val.Epoch - 1
   548  		err = env.ApplyMPs(nextEpoch, futureEpochMp)
   549  		require.ErrorIs(err, basiccheck.FutureBVsEpoch)
   550  	}
   551  
   552  	sameCreatorMp := copyMP(correctMp)
   553  	sameCreatorMp.WrongBlockVote.Pals[0].Signed.Locator.Creator = sameCreatorMp.WrongBlockVote.Pals[1].Signed.Locator.Creator
   554  	err = env.ApplyMPs(nextEpoch, sameCreatorMp)
   555  	require.ErrorIs(err, basiccheck.ErrWrongCreatorMP)
   556  
   557  	for i := range correctMp.WrongBlockVote.Pals {
   558  		wrongSigMp := copyMP(correctMp)
   559  		wrongSigMp.WrongBlockVote.Pals[i].Signed.Sig[0]++
   560  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   561  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   562  	}
   563  
   564  	for i := range correctMp.WrongBlockVote.Pals {
   565  		wrongSigMp := copyMP(correctMp)
   566  		wrongSigMp.WrongBlockVote.Pals[i].Signed.Locator.BaseHash = hash.HexToHash("0x10")
   567  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   568  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   569  	}
   570  
   571  	wrongAuthEpochMp := copyMP(correctMp)
   572  	wrongAuthEpochMp.WrongBlockVote.Pals[0].Signed.Locator.Epoch = startEpoch - 1
   573  	wrongAuthEpochMp.WrongBlockVote.Pals[0].Val.Epoch = startEpoch - 1
   574  	wrongAuthEpochMp.WrongBlockVote.Pals[1].Signed.Locator.Epoch = startEpoch - 1
   575  	wrongAuthEpochMp.WrongBlockVote.Pals[1].Val.Epoch = startEpoch - 1
   576  	err = env.ApplyMPs(nextEpoch, wrongAuthEpochMp)
   577  	require.ErrorIs(err, heavycheck.ErrUnknownEpochBVs)
   578  
   579  	goodEpochMp := copyMP(correctMp)
   580  	goodEpochMp.WrongBlockVote.Pals[0].Val.Epoch = env.store.FindBlockEpoch(goodEpochMp.WrongBlockVote.Block)
   581  	goodEpochMp.WrongBlockVote.Pals[1].Val.Epoch = env.store.FindBlockEpoch(goodEpochMp.WrongBlockVote.Block)
   582  	err = env.ApplyMPs(nextEpoch, goodEpochMp)
   583  	require.ErrorIs(err, heavycheck.ErrWrongPayloadHash)
   584  	sign(&goodEpochMp)
   585  	err = env.ApplyMPs(nextEpoch, goodEpochMp)
   586  	require.NoError(err)
   587  	require.Equal(idx.Validator(3), env.store.GetValidators().Len())
   588  
   589  	err = env.ApplyMPs(nextEpoch, correctMp)
   590  	require.NoError(err)
   591  	require.Equal(idx.Validator(1), env.store.GetValidators().Len())
   592  	require.False(env.store.GetValidators().Exists(1))
   593  	require.False(env.store.GetValidators().Exists(2))
   594  }
   595  
   596  func TestMisbehaviourProofsEpochVoteDoublesign(t *testing.T) {
   597  	logger.SetTestMode(t)
   598  	require := require.New(t)
   599  
   600  	const validatorsNum = 3
   601  
   602  	startEpoch := idx.Epoch(basiccheck.MaxLiableEpochs)
   603  	env := newTestEnv(startEpoch, validatorsNum)
   604  	defer env.Close()
   605  
   606  	// move epoch further
   607  	_, err := env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   608  	require.NoError(err)
   609  	_, err = env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   610  	require.NoError(err)
   611  	require.Greater(env.store.GetEpoch(), startEpoch)
   612  
   613  	correctMp := native.MisbehaviourProof{
   614  		EpochVoteDoublesign: &native.EpochVoteDoublesign{
   615  			Pair: [2]native.LlrSignedEpochVote{
   616  				{
   617  					Val: native.LlrEpochVote{
   618  						Epoch: startEpoch + 1,
   619  						Vote:  hash.HexToHash("0x01"),
   620  					},
   621  				},
   622  				{
   623  					Val: native.LlrEpochVote{
   624  						Epoch: startEpoch + 1,
   625  						Vote:  hash.HexToHash("0x02"),
   626  					},
   627  				},
   628  			},
   629  		},
   630  	}
   631  
   632  	// sign
   633  	for i, p := range correctMp.EpochVoteDoublesign.Pair {
   634  		e := &native.MutableEventPayload{}
   635  		e.SetVersion(1)
   636  		e.SetEpochVote(p.Val)
   637  		e.SetEpoch(env.store.GetEpoch() - idx.Epoch(i))
   638  		e.SetCreator(3)
   639  		e.SetPayloadHash(native.CalcPayloadHash(e))
   640  
   641  		sig, err := env.signer.Sign(env.pubkeys[2], e.HashToSign().Bytes())
   642  		require.NoError(err)
   643  		sSig := native.Signature{}
   644  		copy(sSig[:], sig)
   645  		e.SetSig(sSig)
   646  
   647  		correctMp.EpochVoteDoublesign.Pair[i] = native.AsSignedEpochVote(e)
   648  	}
   649  
   650  	sameVotesMp := copyMP(correctMp)
   651  	sameVotesMp.EpochVoteDoublesign.Pair[0].Val.Vote = sameVotesMp.EpochVoteDoublesign.Pair[1].Val.Vote
   652  	err = env.ApplyMPs(nextEpoch, sameVotesMp)
   653  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   654  
   655  	differentEpochsMp := copyMP(correctMp)
   656  	differentEpochsMp.EpochVoteDoublesign.Pair[0].Val.Epoch++
   657  	err = env.ApplyMPs(nextEpoch, differentEpochsMp)
   658  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   659  
   660  	malformedVotesMp := copyMP(correctMp)
   661  	malformedVotesMp.EpochVoteDoublesign.Pair[1].Val.Epoch = 0
   662  	err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   663  	require.ErrorIs(err, basiccheck.MalformedEV)
   664  
   665  	tooLateMp := copyMP(correctMp)
   666  	tooLateMp.EpochVoteDoublesign.Pair[0].Val.Epoch = 1
   667  	tooLateMp.EpochVoteDoublesign.Pair[1].Val.Epoch = 1
   668  	err = env.ApplyMPs(nextEpoch, tooLateMp)
   669  	require.ErrorIs(err, basiccheck.ErrMPTooLate)
   670  
   671  	for i := range correctMp.EpochVoteDoublesign.Pair {
   672  		futureEpochMp := copyMP(correctMp)
   673  		futureEpochMp.EpochVoteDoublesign.Pair[i].Signed.Locator.Epoch = futureEpochMp.EpochVoteDoublesign.Pair[i].Val.Epoch - 1
   674  		err = env.ApplyMPs(nextEpoch, futureEpochMp)
   675  		require.ErrorIs(err, basiccheck.FutureEVEpoch)
   676  	}
   677  
   678  	wrongCreatorMp := copyMP(correctMp)
   679  	wrongCreatorMp.EpochVoteDoublesign.Pair[0].Signed.Locator.Creator++
   680  	err = env.ApplyMPs(nextEpoch, wrongCreatorMp)
   681  	require.ErrorIs(err, basiccheck.ErrWrongCreatorMP)
   682  
   683  	sameEventsMp := copyMP(correctMp)
   684  	sameEventsMp.EpochVoteDoublesign.Pair[0] = sameEventsMp.EpochVoteDoublesign.Pair[1]
   685  	err = env.ApplyMPs(nextEpoch, sameEventsMp)
   686  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   687  
   688  	for i := range correctMp.EpochVoteDoublesign.Pair {
   689  		wrongSigMp := copyMP(correctMp)
   690  		wrongSigMp.EpochVoteDoublesign.Pair[i].Signed.Sig[0]++
   691  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   692  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   693  	}
   694  
   695  	for i := range correctMp.EpochVoteDoublesign.Pair {
   696  		wrongSigMp := copyMP(correctMp)
   697  		wrongSigMp.EpochVoteDoublesign.Pair[i].Signed.Locator.BaseHash = hash.HexToHash("0x10")
   698  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   699  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   700  	}
   701  
   702  	wrongAuthEpochMp := copyMP(correctMp)
   703  	wrongAuthEpochMp.EpochVoteDoublesign.Pair[0].Signed.Locator.Epoch = startEpoch - 1
   704  	wrongAuthEpochMp.EpochVoteDoublesign.Pair[0].Val.Epoch = startEpoch - 1
   705  	wrongAuthEpochMp.EpochVoteDoublesign.Pair[1].Signed.Locator.Epoch = startEpoch - 1
   706  	wrongAuthEpochMp.EpochVoteDoublesign.Pair[1].Val.Epoch = startEpoch - 1
   707  	err = env.ApplyMPs(nextEpoch, wrongAuthEpochMp)
   708  	require.ErrorIs(err, heavycheck.ErrUnknownEpochEV)
   709  
   710  	err = env.ApplyMPs(nextEpoch, correctMp)
   711  	require.NoError(err)
   712  	require.Equal(idx.Validator(2), env.store.GetValidators().Len())
   713  	require.False(env.store.GetValidators().Exists(3))
   714  }
   715  
   716  func TestMisbehaviourProofsWrongVote(t *testing.T) {
   717  	logger.SetTestMode(t)
   718  	require := require.New(t)
   719  
   720  	const validatorsNum = 3
   721  
   722  	startEpoch := idx.Epoch(basiccheck.MaxLiableEpochs)
   723  	env := newTestEnv(startEpoch, validatorsNum)
   724  	defer env.Close()
   725  
   726  	// move epoch further
   727  	_, err := env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   728  	require.NoError(err)
   729  	_, err = env.ApplyTxs(nextEpoch, env.Transfer(1, 1, common.Big0))
   730  	require.NoError(err)
   731  	require.Greater(env.store.GetEpoch(), startEpoch)
   732  
   733  	correctMp := native.MisbehaviourProof{
   734  		WrongEpochVote: &native.WrongEpochVote{
   735  			Pals: [2]native.LlrSignedEpochVote{
   736  				{
   737  					Val: native.LlrEpochVote{
   738  						Epoch: startEpoch + 1,
   739  						Vote:  hash.HexToHash("0x01"),
   740  					},
   741  				},
   742  				{
   743  					Val: native.LlrEpochVote{
   744  						Epoch: startEpoch + 1,
   745  						Vote:  hash.HexToHash("0x01"),
   746  					},
   747  				},
   748  			},
   749  		},
   750  	}
   751  
   752  	// sign
   753  	sign := func(mp *native.MisbehaviourProof) {
   754  		for i, p := range mp.WrongEpochVote.Pals {
   755  			e := &native.MutableEventPayload{}
   756  			e.SetVersion(1)
   757  			e.SetEpochVote(p.Val)
   758  			e.SetEpoch(env.store.GetEpoch() - idx.Epoch(i))
   759  			e.SetCreator(idx.ValidatorID(i + 1))
   760  			e.SetPayloadHash(native.CalcPayloadHash(e))
   761  
   762  			sig, err := env.signer.Sign(env.pubkeys[i], e.HashToSign().Bytes())
   763  			require.NoError(err)
   764  			sSig := native.Signature{}
   765  			copy(sSig[:], sig)
   766  			e.SetSig(sSig)
   767  
   768  			mp.WrongEpochVote.Pals[i] = native.AsSignedEpochVote(e)
   769  		}
   770  	}
   771  	sign(&correctMp)
   772  
   773  	differentVotesMp := copyMP(correctMp)
   774  	differentVotesMp.WrongEpochVote.Pals[0].Val.Vote = hash.HexToHash("0x02")
   775  	err = env.ApplyMPs(nextEpoch, differentVotesMp)
   776  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   777  
   778  	differentEpochsMp := copyMP(correctMp)
   779  	differentEpochsMp.WrongEpochVote.Pals[0].Val.Epoch++
   780  	err = env.ApplyMPs(nextEpoch, differentEpochsMp)
   781  	require.ErrorIs(err, basiccheck.ErrNoCrimeInMP)
   782  
   783  	malformedVotesMp := copyMP(correctMp)
   784  	malformedVotesMp.WrongEpochVote.Pals[1].Val.Epoch = 0
   785  	err = env.ApplyMPs(nextEpoch, malformedVotesMp)
   786  	require.ErrorIs(err, basiccheck.MalformedEV)
   787  
   788  	tooLateMp := copyMP(correctMp)
   789  	tooLateMp.WrongEpochVote.Pals[0].Val.Epoch = 1
   790  	tooLateMp.WrongEpochVote.Pals[1].Val.Epoch = 1
   791  	err = env.ApplyMPs(nextEpoch, tooLateMp)
   792  	require.ErrorIs(err, basiccheck.ErrMPTooLate)
   793  
   794  	for i := range correctMp.WrongEpochVote.Pals {
   795  		futureEpochMp := copyMP(correctMp)
   796  		futureEpochMp.WrongEpochVote.Pals[i].Signed.Locator.Epoch = futureEpochMp.WrongEpochVote.Pals[i].Val.Epoch - 1
   797  		err = env.ApplyMPs(nextEpoch, futureEpochMp)
   798  		require.ErrorIs(err, basiccheck.FutureEVEpoch)
   799  	}
   800  
   801  	sameCreatorMp := copyMP(correctMp)
   802  	sameCreatorMp.WrongEpochVote.Pals[0].Signed.Locator.Creator = sameCreatorMp.WrongEpochVote.Pals[1].Signed.Locator.Creator
   803  	err = env.ApplyMPs(nextEpoch, sameCreatorMp)
   804  	require.ErrorIs(err, basiccheck.ErrWrongCreatorMP)
   805  
   806  	for i := range correctMp.WrongEpochVote.Pals {
   807  		wrongSigMp := copyMP(correctMp)
   808  		wrongSigMp.WrongEpochVote.Pals[i].Signed.Sig[0]++
   809  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   810  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   811  	}
   812  
   813  	for i := range correctMp.WrongEpochVote.Pals {
   814  		wrongSigMp := copyMP(correctMp)
   815  		wrongSigMp.WrongEpochVote.Pals[i].Signed.Locator.BaseHash = hash.HexToHash("0x10")
   816  		err = env.ApplyMPs(nextEpoch, wrongSigMp)
   817  		require.ErrorIs(err, heavycheck.ErrWrongEventSig)
   818  	}
   819  
   820  	wrongAuthEpochMp := copyMP(correctMp)
   821  	wrongAuthEpochMp.WrongEpochVote.Pals[0].Signed.Locator.Epoch = startEpoch - 1
   822  	wrongAuthEpochMp.WrongEpochVote.Pals[0].Val.Epoch = startEpoch - 1
   823  	wrongAuthEpochMp.WrongEpochVote.Pals[1].Signed.Locator.Epoch = startEpoch - 1
   824  	wrongAuthEpochMp.WrongEpochVote.Pals[1].Val.Epoch = startEpoch - 1
   825  	err = env.ApplyMPs(nextEpoch, wrongAuthEpochMp)
   826  	require.ErrorIs(err, heavycheck.ErrUnknownEpochEV)
   827  
   828  	goodVotesMp := copyMP(correctMp)
   829  	goodVotesMp.WrongEpochVote.Pals[0].Val.Vote = env.store.GetFullEpochRecord(goodVotesMp.WrongEpochVote.Pals[0].Val.Epoch).Hash()
   830  	goodVotesMp.WrongEpochVote.Pals[1].Val.Vote = env.store.GetFullEpochRecord(goodVotesMp.WrongEpochVote.Pals[1].Val.Epoch).Hash()
   831  	err = env.ApplyMPs(nextEpoch, goodVotesMp)
   832  	require.ErrorIs(err, heavycheck.ErrWrongPayloadHash)
   833  	sign(&goodVotesMp)
   834  	err = env.ApplyMPs(nextEpoch, goodVotesMp)
   835  	require.NoError(err)
   836  	require.Equal(idx.Validator(3), env.store.GetValidators().Len())
   837  
   838  	err = env.ApplyMPs(nextEpoch, correctMp)
   839  	require.NoError(err)
   840  	require.Equal(idx.Validator(1), env.store.GetValidators().Len())
   841  	require.False(env.store.GetValidators().Exists(1))
   842  	require.False(env.store.GetValidators().Exists(2))
   843  }