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 }