github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/eth/v1/beacon/pool_test.go (about) 1 package beacon 2 3 import ( 4 "context" 5 "reflect" 6 "strings" 7 "testing" 8 9 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 10 eth2types "github.com/prysmaticlabs/eth2-types" 11 "github.com/prysmaticlabs/go-bitfield" 12 chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 13 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 14 "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" 15 "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" 16 "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" 17 p2pMock "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" 18 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 19 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1" 20 eth "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 21 "github.com/prysmaticlabs/prysm/proto/migration" 22 "github.com/prysmaticlabs/prysm/shared/bls" 23 "github.com/prysmaticlabs/prysm/shared/bytesutil" 24 "github.com/prysmaticlabs/prysm/shared/grpcutils" 25 "github.com/prysmaticlabs/prysm/shared/params" 26 "github.com/prysmaticlabs/prysm/shared/testutil" 27 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 28 "github.com/prysmaticlabs/prysm/shared/testutil/require" 29 "google.golang.org/grpc" 30 "google.golang.org/protobuf/types/known/emptypb" 31 ) 32 33 func TestListPoolAttestations(t *testing.T) { 34 state, err := testutil.NewBeaconState() 35 require.NoError(t, err) 36 att1 := ð.Attestation{ 37 AggregationBits: []byte{1, 10}, 38 Data: ð.AttestationData{ 39 Slot: 1, 40 CommitteeIndex: 1, 41 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), 42 Source: ð.Checkpoint{ 43 Epoch: 1, 44 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 45 }, 46 Target: ð.Checkpoint{ 47 Epoch: 10, 48 Root: bytesutil.PadTo([]byte("targetroot1"), 32), 49 }, 50 }, 51 Signature: bytesutil.PadTo([]byte("signature1"), 96), 52 } 53 att2 := ð.Attestation{ 54 AggregationBits: []byte{4, 40}, 55 Data: ð.AttestationData{ 56 Slot: 4, 57 CommitteeIndex: 4, 58 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot4"), 32), 59 Source: ð.Checkpoint{ 60 Epoch: 4, 61 Root: bytesutil.PadTo([]byte("sourceroot4"), 32), 62 }, 63 Target: ð.Checkpoint{ 64 Epoch: 40, 65 Root: bytesutil.PadTo([]byte("targetroot4"), 32), 66 }, 67 }, 68 Signature: bytesutil.PadTo([]byte("signature4"), 96), 69 } 70 att3 := ð.Attestation{ 71 AggregationBits: []byte{2, 20}, 72 Data: ð.AttestationData{ 73 Slot: 2, 74 CommitteeIndex: 2, 75 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), 76 Source: ð.Checkpoint{ 77 Epoch: 2, 78 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 79 }, 80 Target: ð.Checkpoint{ 81 Epoch: 20, 82 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 83 }, 84 }, 85 Signature: bytesutil.PadTo([]byte("signature2"), 96), 86 } 87 att4 := ð.Attestation{ 88 AggregationBits: bitfield.NewBitlist(8), 89 Data: ð.AttestationData{ 90 Slot: 4, 91 CommitteeIndex: 4, 92 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), 93 Source: ð.Checkpoint{ 94 Epoch: 2, 95 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 96 }, 97 Target: ð.Checkpoint{ 98 Epoch: 20, 99 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 100 }, 101 }, 102 Signature: bytesutil.PadTo([]byte("signature2"), 96), 103 } 104 att5 := ð.Attestation{ 105 AggregationBits: bitfield.NewBitlist(8), 106 Data: ð.AttestationData{ 107 Slot: 2, 108 CommitteeIndex: 4, 109 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), 110 Source: ð.Checkpoint{ 111 Epoch: 2, 112 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 113 }, 114 Target: ð.Checkpoint{ 115 Epoch: 20, 116 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 117 }, 118 }, 119 Signature: bytesutil.PadTo([]byte("signature1"), 96), 120 } 121 att6 := ð.Attestation{ 122 AggregationBits: bitfield.NewBitlist(8), 123 Data: ð.AttestationData{ 124 Slot: 2, 125 CommitteeIndex: 4, 126 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), 127 Source: ð.Checkpoint{ 128 Epoch: 2, 129 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 130 }, 131 Target: ð.Checkpoint{ 132 Epoch: 20, 133 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 134 }, 135 }, 136 Signature: bytesutil.PadTo([]byte("signature2"), 96), 137 } 138 s := &Server{ 139 ChainInfoFetcher: &chainMock.ChainService{State: state}, 140 AttestationsPool: attestations.NewPool(), 141 } 142 require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]*eth.Attestation{att1, att2, att3})) 143 require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]*eth.Attestation{att4, att5, att6})) 144 145 t.Run("empty request", func(t *testing.T) { 146 req := ðpb.AttestationsPoolRequest{} 147 resp, err := s.ListPoolAttestations(context.Background(), req) 148 require.NoError(t, err) 149 require.Equal(t, 6, len(resp.Data)) 150 }) 151 152 t.Run("slot request", func(t *testing.T) { 153 slot := eth2types.Slot(2) 154 req := ðpb.AttestationsPoolRequest{ 155 Slot: &slot, 156 } 157 resp, err := s.ListPoolAttestations(context.Background(), req) 158 require.NoError(t, err) 159 require.Equal(t, 3, len(resp.Data)) 160 for _, datum := range resp.Data { 161 assert.DeepEqual(t, datum.Data.Slot, slot) 162 } 163 }) 164 165 t.Run("index request", func(t *testing.T) { 166 index := eth2types.CommitteeIndex(4) 167 req := ðpb.AttestationsPoolRequest{ 168 CommitteeIndex: &index, 169 } 170 resp, err := s.ListPoolAttestations(context.Background(), req) 171 require.NoError(t, err) 172 require.Equal(t, 4, len(resp.Data)) 173 for _, datum := range resp.Data { 174 assert.DeepEqual(t, datum.Data.Index, index) 175 } 176 }) 177 178 t.Run("both slot + index request", func(t *testing.T) { 179 slot := eth2types.Slot(2) 180 index := eth2types.CommitteeIndex(4) 181 req := ðpb.AttestationsPoolRequest{ 182 Slot: &slot, 183 CommitteeIndex: &index, 184 } 185 resp, err := s.ListPoolAttestations(context.Background(), req) 186 require.NoError(t, err) 187 require.Equal(t, 2, len(resp.Data)) 188 for _, datum := range resp.Data { 189 assert.DeepEqual(t, datum.Data.Index, index) 190 assert.DeepEqual(t, datum.Data.Slot, slot) 191 } 192 }) 193 } 194 195 func TestListPoolAttesterSlashings(t *testing.T) { 196 state, err := testutil.NewBeaconState() 197 require.NoError(t, err) 198 slashing1 := ð.AttesterSlashing{ 199 Attestation_1: ð.IndexedAttestation{ 200 AttestingIndices: []uint64{1, 10}, 201 Data: ð.AttestationData{ 202 Slot: 1, 203 CommitteeIndex: 1, 204 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), 205 Source: ð.Checkpoint{ 206 Epoch: 1, 207 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 208 }, 209 Target: ð.Checkpoint{ 210 Epoch: 10, 211 Root: bytesutil.PadTo([]byte("targetroot1"), 32), 212 }, 213 }, 214 Signature: bytesutil.PadTo([]byte("signature1"), 96), 215 }, 216 Attestation_2: ð.IndexedAttestation{ 217 AttestingIndices: []uint64{2, 20}, 218 Data: ð.AttestationData{ 219 Slot: 2, 220 CommitteeIndex: 2, 221 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), 222 Source: ð.Checkpoint{ 223 Epoch: 2, 224 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 225 }, 226 Target: ð.Checkpoint{ 227 Epoch: 20, 228 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 229 }, 230 }, 231 Signature: bytesutil.PadTo([]byte("signature2"), 96), 232 }, 233 } 234 slashing2 := ð.AttesterSlashing{ 235 Attestation_1: ð.IndexedAttestation{ 236 AttestingIndices: []uint64{3, 30}, 237 Data: ð.AttestationData{ 238 Slot: 3, 239 CommitteeIndex: 3, 240 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot3"), 32), 241 Source: ð.Checkpoint{ 242 Epoch: 3, 243 Root: bytesutil.PadTo([]byte("sourceroot3"), 32), 244 }, 245 Target: ð.Checkpoint{ 246 Epoch: 30, 247 Root: bytesutil.PadTo([]byte("targetroot3"), 32), 248 }, 249 }, 250 Signature: bytesutil.PadTo([]byte("signature3"), 96), 251 }, 252 Attestation_2: ð.IndexedAttestation{ 253 AttestingIndices: []uint64{4, 40}, 254 Data: ð.AttestationData{ 255 Slot: 4, 256 CommitteeIndex: 4, 257 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot4"), 32), 258 Source: ð.Checkpoint{ 259 Epoch: 4, 260 Root: bytesutil.PadTo([]byte("sourceroot4"), 32), 261 }, 262 Target: ð.Checkpoint{ 263 Epoch: 40, 264 Root: bytesutil.PadTo([]byte("targetroot4"), 32), 265 }, 266 }, 267 Signature: bytesutil.PadTo([]byte("signature4"), 96), 268 }, 269 } 270 271 s := &Server{ 272 ChainInfoFetcher: &chainMock.ChainService{State: state}, 273 SlashingsPool: &slashings.PoolMock{PendingAttSlashings: []*eth.AttesterSlashing{slashing1, slashing2}}, 274 } 275 276 resp, err := s.ListPoolAttesterSlashings(context.Background(), &emptypb.Empty{}) 277 require.NoError(t, err) 278 require.Equal(t, 2, len(resp.Data)) 279 assert.DeepEqual(t, migration.V1Alpha1AttSlashingToV1(slashing1), resp.Data[0]) 280 assert.DeepEqual(t, migration.V1Alpha1AttSlashingToV1(slashing2), resp.Data[1]) 281 } 282 283 func TestListPoolProposerSlashings(t *testing.T) { 284 state, err := testutil.NewBeaconState() 285 require.NoError(t, err) 286 slashing1 := ð.ProposerSlashing{ 287 Header_1: ð.SignedBeaconBlockHeader{ 288 Header: ð.BeaconBlockHeader{ 289 Slot: 1, 290 ProposerIndex: 1, 291 ParentRoot: bytesutil.PadTo([]byte("parentroot1"), 32), 292 StateRoot: bytesutil.PadTo([]byte("stateroot1"), 32), 293 BodyRoot: bytesutil.PadTo([]byte("bodyroot1"), 32), 294 }, 295 Signature: bytesutil.PadTo([]byte("signature1"), 96), 296 }, 297 Header_2: ð.SignedBeaconBlockHeader{ 298 Header: ð.BeaconBlockHeader{ 299 Slot: 2, 300 ProposerIndex: 2, 301 ParentRoot: bytesutil.PadTo([]byte("parentroot2"), 32), 302 StateRoot: bytesutil.PadTo([]byte("stateroot2"), 32), 303 BodyRoot: bytesutil.PadTo([]byte("bodyroot2"), 32), 304 }, 305 Signature: bytesutil.PadTo([]byte("signature2"), 96), 306 }, 307 } 308 slashing2 := ð.ProposerSlashing{ 309 Header_1: ð.SignedBeaconBlockHeader{ 310 Header: ð.BeaconBlockHeader{ 311 Slot: 3, 312 ProposerIndex: 3, 313 ParentRoot: bytesutil.PadTo([]byte("parentroot3"), 32), 314 StateRoot: bytesutil.PadTo([]byte("stateroot3"), 32), 315 BodyRoot: bytesutil.PadTo([]byte("bodyroot3"), 32), 316 }, 317 Signature: bytesutil.PadTo([]byte("signature3"), 96), 318 }, 319 Header_2: ð.SignedBeaconBlockHeader{ 320 Header: ð.BeaconBlockHeader{ 321 Slot: 4, 322 ProposerIndex: 4, 323 ParentRoot: bytesutil.PadTo([]byte("parentroot4"), 32), 324 StateRoot: bytesutil.PadTo([]byte("stateroot4"), 32), 325 BodyRoot: bytesutil.PadTo([]byte("bodyroot4"), 32), 326 }, 327 Signature: bytesutil.PadTo([]byte("signature4"), 96), 328 }, 329 } 330 331 s := &Server{ 332 ChainInfoFetcher: &chainMock.ChainService{State: state}, 333 SlashingsPool: &slashings.PoolMock{PendingPropSlashings: []*eth.ProposerSlashing{slashing1, slashing2}}, 334 } 335 336 resp, err := s.ListPoolProposerSlashings(context.Background(), &emptypb.Empty{}) 337 require.NoError(t, err) 338 require.Equal(t, 2, len(resp.Data)) 339 assert.DeepEqual(t, migration.V1Alpha1ProposerSlashingToV1(slashing1), resp.Data[0]) 340 assert.DeepEqual(t, migration.V1Alpha1ProposerSlashingToV1(slashing2), resp.Data[1]) 341 } 342 343 func TestListPoolVoluntaryExits(t *testing.T) { 344 state, err := testutil.NewBeaconState() 345 require.NoError(t, err) 346 exit1 := ð.SignedVoluntaryExit{ 347 Exit: ð.VoluntaryExit{ 348 Epoch: 1, 349 ValidatorIndex: 1, 350 }, 351 Signature: bytesutil.PadTo([]byte("signature1"), 96), 352 } 353 exit2 := ð.SignedVoluntaryExit{ 354 Exit: ð.VoluntaryExit{ 355 Epoch: 2, 356 ValidatorIndex: 2, 357 }, 358 Signature: bytesutil.PadTo([]byte("signature2"), 96), 359 } 360 361 s := &Server{ 362 ChainInfoFetcher: &chainMock.ChainService{State: state}, 363 VoluntaryExitsPool: &voluntaryexits.PoolMock{Exits: []*eth.SignedVoluntaryExit{exit1, exit2}}, 364 } 365 366 resp, err := s.ListPoolVoluntaryExits(context.Background(), &emptypb.Empty{}) 367 require.NoError(t, err) 368 require.Equal(t, 2, len(resp.Data)) 369 assert.DeepEqual(t, migration.V1Alpha1ExitToV1(exit1), resp.Data[0]) 370 assert.DeepEqual(t, migration.V1Alpha1ExitToV1(exit2), resp.Data[1]) 371 } 372 373 func TestSubmitAttesterSlashing_Ok(t *testing.T) { 374 ctx := context.Background() 375 376 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 377 require.NoError(t, err) 378 validator := ð.Validator{ 379 PublicKey: keys[0].PublicKey().Marshal(), 380 } 381 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 382 state.Validators = []*eth.Validator{validator} 383 return nil 384 }) 385 require.NoError(t, err) 386 387 slashing := ðpb.AttesterSlashing{ 388 Attestation_1: ðpb.IndexedAttestation{ 389 AttestingIndices: []uint64{0}, 390 Data: ðpb.AttestationData{ 391 Slot: 1, 392 Index: 1, 393 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), 394 Source: ðpb.Checkpoint{ 395 Epoch: 1, 396 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 397 }, 398 Target: ðpb.Checkpoint{ 399 Epoch: 10, 400 Root: bytesutil.PadTo([]byte("targetroot1"), 32), 401 }, 402 }, 403 Signature: make([]byte, 96), 404 }, 405 Attestation_2: ðpb.IndexedAttestation{ 406 AttestingIndices: []uint64{0}, 407 Data: ðpb.AttestationData{ 408 Slot: 1, 409 Index: 1, 410 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), 411 Source: ðpb.Checkpoint{ 412 Epoch: 1, 413 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 414 }, 415 Target: ðpb.Checkpoint{ 416 Epoch: 10, 417 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 418 }, 419 }, 420 Signature: make([]byte, 96), 421 }, 422 } 423 424 for _, att := range []*ethpb.IndexedAttestation{slashing.Attestation_1, slashing.Attestation_2} { 425 sb, err := helpers.ComputeDomainAndSign(state, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0]) 426 require.NoError(t, err) 427 sig, err := bls.SignatureFromBytes(sb) 428 require.NoError(t, err) 429 att.Signature = sig.Marshal() 430 } 431 432 broadcaster := &p2pMock.MockBroadcaster{} 433 s := &Server{ 434 ChainInfoFetcher: &chainMock.ChainService{State: state}, 435 SlashingsPool: &slashings.PoolMock{}, 436 Broadcaster: broadcaster, 437 } 438 439 _, err = s.SubmitAttesterSlashing(ctx, slashing) 440 require.NoError(t, err) 441 pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, state, true) 442 require.Equal(t, 1, len(pendingSlashings)) 443 assert.DeepEqual(t, migration.V1AttSlashingToV1Alpha1(slashing), pendingSlashings[0]) 444 assert.Equal(t, true, broadcaster.BroadcastCalled) 445 } 446 447 func TestSubmitAttesterSlashing_InvalidSlashing(t *testing.T) { 448 ctx := context.Background() 449 state, err := testutil.NewBeaconState() 450 require.NoError(t, err) 451 452 attestation := ðpb.IndexedAttestation{ 453 AttestingIndices: []uint64{0}, 454 Data: ðpb.AttestationData{ 455 Slot: 1, 456 Index: 1, 457 BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), 458 Source: ðpb.Checkpoint{ 459 Epoch: 1, 460 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 461 }, 462 Target: ðpb.Checkpoint{ 463 Epoch: 10, 464 Root: bytesutil.PadTo([]byte("targetroot1"), 32), 465 }, 466 }, 467 Signature: make([]byte, 96), 468 } 469 470 slashing := ðpb.AttesterSlashing{ 471 Attestation_1: attestation, 472 Attestation_2: attestation, 473 } 474 475 broadcaster := &p2pMock.MockBroadcaster{} 476 s := &Server{ 477 ChainInfoFetcher: &chainMock.ChainService{State: state}, 478 SlashingsPool: &slashings.PoolMock{}, 479 Broadcaster: broadcaster, 480 } 481 482 _, err = s.SubmitAttesterSlashing(ctx, slashing) 483 require.ErrorContains(t, "Invalid attester slashing", err) 484 assert.Equal(t, false, broadcaster.BroadcastCalled) 485 } 486 487 func TestSubmitProposerSlashing_Ok(t *testing.T) { 488 ctx := context.Background() 489 490 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 491 require.NoError(t, err) 492 validator := ð.Validator{ 493 PublicKey: keys[0].PublicKey().Marshal(), 494 WithdrawableEpoch: eth2types.Epoch(1), 495 } 496 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 497 state.Validators = []*eth.Validator{validator} 498 return nil 499 }) 500 require.NoError(t, err) 501 502 slashing := ðpb.ProposerSlashing{ 503 SignedHeader_1: ðpb.SignedBeaconBlockHeader{ 504 Message: ðpb.BeaconBlockHeader{ 505 Slot: 1, 506 ProposerIndex: 0, 507 ParentRoot: bytesutil.PadTo([]byte("parentroot1"), 32), 508 StateRoot: bytesutil.PadTo([]byte("stateroot1"), 32), 509 BodyRoot: bytesutil.PadTo([]byte("bodyroot1"), 32), 510 }, 511 Signature: make([]byte, 96), 512 }, 513 SignedHeader_2: ðpb.SignedBeaconBlockHeader{ 514 Message: ðpb.BeaconBlockHeader{ 515 Slot: 1, 516 ProposerIndex: 0, 517 ParentRoot: bytesutil.PadTo([]byte("parentroot2"), 32), 518 StateRoot: bytesutil.PadTo([]byte("stateroot2"), 32), 519 BodyRoot: bytesutil.PadTo([]byte("bodyroot2"), 32), 520 }, 521 Signature: make([]byte, 96), 522 }, 523 } 524 525 for _, h := range []*ethpb.SignedBeaconBlockHeader{slashing.SignedHeader_1, slashing.SignedHeader_2} { 526 sb, err := helpers.ComputeDomainAndSign( 527 state, 528 helpers.SlotToEpoch(h.Message.Slot), 529 h.Message, 530 params.BeaconConfig().DomainBeaconProposer, 531 keys[0], 532 ) 533 require.NoError(t, err) 534 sig, err := bls.SignatureFromBytes(sb) 535 require.NoError(t, err) 536 h.Signature = sig.Marshal() 537 } 538 539 broadcaster := &p2pMock.MockBroadcaster{} 540 s := &Server{ 541 ChainInfoFetcher: &chainMock.ChainService{State: state}, 542 SlashingsPool: &slashings.PoolMock{}, 543 Broadcaster: broadcaster, 544 } 545 546 _, err = s.SubmitProposerSlashing(ctx, slashing) 547 require.NoError(t, err) 548 pendingSlashings := s.SlashingsPool.PendingProposerSlashings(ctx, state, true) 549 require.Equal(t, 1, len(pendingSlashings)) 550 assert.DeepEqual(t, migration.V1ProposerSlashingToV1Alpha1(slashing), pendingSlashings[0]) 551 assert.Equal(t, true, broadcaster.BroadcastCalled) 552 } 553 554 func TestSubmitProposerSlashing_InvalidSlashing(t *testing.T) { 555 ctx := context.Background() 556 state, err := testutil.NewBeaconState() 557 require.NoError(t, err) 558 559 header := ðpb.SignedBeaconBlockHeader{ 560 Message: ðpb.BeaconBlockHeader{ 561 Slot: 1, 562 ProposerIndex: 0, 563 ParentRoot: bytesutil.PadTo([]byte("parentroot1"), 32), 564 StateRoot: bytesutil.PadTo([]byte("stateroot1"), 32), 565 BodyRoot: bytesutil.PadTo([]byte("bodyroot1"), 32), 566 }, 567 Signature: make([]byte, 96), 568 } 569 570 slashing := ðpb.ProposerSlashing{ 571 SignedHeader_1: header, 572 SignedHeader_2: header, 573 } 574 575 broadcaster := &p2pMock.MockBroadcaster{} 576 s := &Server{ 577 ChainInfoFetcher: &chainMock.ChainService{State: state}, 578 SlashingsPool: &slashings.PoolMock{}, 579 Broadcaster: broadcaster, 580 } 581 582 _, err = s.SubmitProposerSlashing(ctx, slashing) 583 require.ErrorContains(t, "Invalid proposer slashing", err) 584 assert.Equal(t, false, broadcaster.BroadcastCalled) 585 } 586 587 func TestSubmitVoluntaryExit_Ok(t *testing.T) { 588 ctx := context.Background() 589 590 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 591 require.NoError(t, err) 592 validator := ð.Validator{ 593 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 594 PublicKey: keys[0].PublicKey().Marshal(), 595 } 596 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 597 state.Validators = []*eth.Validator{validator} 598 // Satisfy activity time required before exiting. 599 state.Slot = params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)) 600 return nil 601 }) 602 require.NoError(t, err) 603 604 exit := ðpb.SignedVoluntaryExit{ 605 Message: ðpb.VoluntaryExit{ 606 Epoch: 0, 607 ValidatorIndex: 0, 608 }, 609 Signature: make([]byte, 96), 610 } 611 612 sb, err := helpers.ComputeDomainAndSign(state, exit.Message.Epoch, exit.Message, params.BeaconConfig().DomainVoluntaryExit, keys[0]) 613 require.NoError(t, err) 614 sig, err := bls.SignatureFromBytes(sb) 615 require.NoError(t, err) 616 exit.Signature = sig.Marshal() 617 618 broadcaster := &p2pMock.MockBroadcaster{} 619 s := &Server{ 620 ChainInfoFetcher: &chainMock.ChainService{State: state}, 621 VoluntaryExitsPool: &voluntaryexits.PoolMock{}, 622 Broadcaster: broadcaster, 623 } 624 625 _, err = s.SubmitVoluntaryExit(ctx, exit) 626 require.NoError(t, err) 627 pendingExits := s.VoluntaryExitsPool.PendingExits(state, state.Slot(), true) 628 require.Equal(t, 1, len(pendingExits)) 629 assert.DeepEqual(t, migration.V1ExitToV1Alpha1(exit), pendingExits[0]) 630 assert.Equal(t, true, broadcaster.BroadcastCalled) 631 } 632 633 func TestSubmitVoluntaryExit_InvalidValidatorIndex(t *testing.T) { 634 ctx := context.Background() 635 636 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 637 require.NoError(t, err) 638 validator := ð.Validator{ 639 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 640 PublicKey: keys[0].PublicKey().Marshal(), 641 } 642 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 643 state.Validators = []*eth.Validator{validator} 644 return nil 645 }) 646 require.NoError(t, err) 647 648 exit := ðpb.SignedVoluntaryExit{ 649 Message: ðpb.VoluntaryExit{ 650 Epoch: 0, 651 ValidatorIndex: 99, 652 }, 653 Signature: make([]byte, 96), 654 } 655 656 broadcaster := &p2pMock.MockBroadcaster{} 657 s := &Server{ 658 ChainInfoFetcher: &chainMock.ChainService{State: state}, 659 VoluntaryExitsPool: &voluntaryexits.PoolMock{}, 660 Broadcaster: broadcaster, 661 } 662 663 _, err = s.SubmitVoluntaryExit(ctx, exit) 664 require.ErrorContains(t, "Could not get exiting validator", err) 665 assert.Equal(t, false, broadcaster.BroadcastCalled) 666 } 667 668 func TestSubmitVoluntaryExit_InvalidExit(t *testing.T) { 669 ctx := context.Background() 670 671 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 672 require.NoError(t, err) 673 validator := ð.Validator{ 674 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 675 PublicKey: keys[0].PublicKey().Marshal(), 676 } 677 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 678 state.Validators = []*eth.Validator{validator} 679 return nil 680 }) 681 require.NoError(t, err) 682 683 exit := ðpb.SignedVoluntaryExit{ 684 Message: ðpb.VoluntaryExit{ 685 Epoch: 0, 686 ValidatorIndex: 0, 687 }, 688 Signature: make([]byte, 96), 689 } 690 691 broadcaster := &p2pMock.MockBroadcaster{} 692 s := &Server{ 693 ChainInfoFetcher: &chainMock.ChainService{State: state}, 694 VoluntaryExitsPool: &voluntaryexits.PoolMock{}, 695 Broadcaster: broadcaster, 696 } 697 698 _, err = s.SubmitVoluntaryExit(ctx, exit) 699 require.ErrorContains(t, "Invalid voluntary exit", err) 700 assert.Equal(t, false, broadcaster.BroadcastCalled) 701 } 702 703 func TestServer_SubmitAttestations_Ok(t *testing.T) { 704 ctx := context.Background() 705 params.SetupTestConfigCleanup(t) 706 c := params.BeaconConfig() 707 // Required for correct committee size calculation. 708 c.SlotsPerEpoch = 1 709 params.OverrideBeaconConfig(c) 710 711 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 712 require.NoError(t, err) 713 validators := []*eth.Validator{ 714 { 715 PublicKey: keys[0].PublicKey().Marshal(), 716 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 717 }, 718 } 719 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 720 state.Validators = validators 721 state.Slot = 1 722 state.PreviousJustifiedCheckpoint = ð.Checkpoint{ 723 Epoch: 0, 724 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 725 } 726 return nil 727 }) 728 require.NoError(t, err) 729 b := bitfield.NewBitlist(1) 730 b.SetBitAt(0, true) 731 732 sourceCheckpoint := ðpb.Checkpoint{ 733 Epoch: 0, 734 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 735 } 736 att1 := ðpb.Attestation{ 737 AggregationBits: b, 738 Data: ðpb.AttestationData{ 739 Slot: 0, 740 Index: 0, 741 BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot1"), 32), 742 Source: sourceCheckpoint, 743 Target: ðpb.Checkpoint{ 744 Epoch: 0, 745 Root: bytesutil.PadTo([]byte("targetroot1"), 32), 746 }, 747 }, 748 Signature: make([]byte, 96), 749 } 750 att2 := ðpb.Attestation{ 751 AggregationBits: b, 752 Data: ðpb.AttestationData{ 753 Slot: 0, 754 Index: 0, 755 BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32), 756 Source: sourceCheckpoint, 757 Target: ðpb.Checkpoint{ 758 Epoch: 0, 759 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 760 }, 761 }, 762 Signature: make([]byte, 96), 763 } 764 765 for _, att := range []*ethpb.Attestation{att1, att2} { 766 sb, err := helpers.ComputeDomainAndSign( 767 state, 768 helpers.SlotToEpoch(att.Data.Slot), 769 att.Data, 770 params.BeaconConfig().DomainBeaconAttester, 771 keys[0], 772 ) 773 require.NoError(t, err) 774 sig, err := bls.SignatureFromBytes(sb) 775 require.NoError(t, err) 776 att.Signature = sig.Marshal() 777 } 778 779 broadcaster := &p2pMock.MockBroadcaster{} 780 s := &Server{ 781 ChainInfoFetcher: &chainMock.ChainService{State: state}, 782 AttestationsPool: &attestations.PoolMock{}, 783 Broadcaster: broadcaster, 784 } 785 786 _, err = s.SubmitAttestations(ctx, ðpb.SubmitAttestationsRequest{ 787 Data: []*ethpb.Attestation{att1, att2}, 788 }) 789 require.NoError(t, err) 790 savedAtts := s.AttestationsPool.AggregatedAttestations() 791 require.Equal(t, 2, len(savedAtts)) 792 expectedAtt1, err := att1.HashTreeRoot() 793 require.NoError(t, err) 794 expectedAtt2, err := att2.HashTreeRoot() 795 require.NoError(t, err) 796 actualAtt1, err := savedAtts[0].HashTreeRoot() 797 require.NoError(t, err) 798 actualAtt2, err := savedAtts[1].HashTreeRoot() 799 require.NoError(t, err) 800 for _, r := range [][32]byte{actualAtt1, actualAtt2} { 801 assert.Equal(t, true, reflect.DeepEqual(expectedAtt1, r) || reflect.DeepEqual(expectedAtt2, r)) 802 } 803 assert.Equal(t, true, broadcaster.BroadcastCalled) 804 assert.Equal(t, 2, len(broadcaster.BroadcastMessages)) 805 } 806 807 func TestServer_SubmitAttestations_ValidAttestationSubmitted(t *testing.T) { 808 ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) 809 810 params.SetupTestConfigCleanup(t) 811 c := params.BeaconConfig() 812 // Required for correct committee size calculation. 813 c.SlotsPerEpoch = 1 814 params.OverrideBeaconConfig(c) 815 816 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 817 require.NoError(t, err) 818 validators := []*eth.Validator{ 819 { 820 PublicKey: keys[0].PublicKey().Marshal(), 821 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 822 }, 823 } 824 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 825 state.Validators = validators 826 state.Slot = 1 827 state.PreviousJustifiedCheckpoint = ð.Checkpoint{ 828 Epoch: 0, 829 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 830 } 831 return nil 832 }) 833 834 require.NoError(t, err) 835 836 sourceCheckpoint := ðpb.Checkpoint{ 837 Epoch: 0, 838 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 839 } 840 b := bitfield.NewBitlist(1) 841 b.SetBitAt(0, true) 842 attValid := ðpb.Attestation{ 843 AggregationBits: b, 844 Data: ðpb.AttestationData{ 845 Slot: 0, 846 Index: 0, 847 BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot1"), 32), 848 Source: sourceCheckpoint, 849 Target: ðpb.Checkpoint{ 850 Epoch: 0, 851 Root: bytesutil.PadTo([]byte("targetroot1"), 32), 852 }, 853 }, 854 Signature: make([]byte, 96), 855 } 856 attInvalidTarget := ðpb.Attestation{ 857 AggregationBits: b, 858 Data: ðpb.AttestationData{ 859 Slot: 0, 860 Index: 0, 861 BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32), 862 Source: ðpb.Checkpoint{ 863 Epoch: 0, 864 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 865 }, 866 Target: ðpb.Checkpoint{ 867 Epoch: 99, 868 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 869 }, 870 }, 871 Signature: make([]byte, 96), 872 } 873 attInvalidSignature := ðpb.Attestation{ 874 AggregationBits: b, 875 Data: ðpb.AttestationData{ 876 Slot: 0, 877 Index: 0, 878 BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32), 879 Source: sourceCheckpoint, 880 Target: ðpb.Checkpoint{ 881 Epoch: 0, 882 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 883 }, 884 }, 885 Signature: make([]byte, 96), 886 } 887 888 // Don't sign attInvalidSignature. 889 for _, att := range []*ethpb.Attestation{attValid, attInvalidTarget} { 890 sb, err := helpers.ComputeDomainAndSign( 891 state, 892 helpers.SlotToEpoch(att.Data.Slot), 893 att.Data, 894 params.BeaconConfig().DomainBeaconAttester, 895 keys[0], 896 ) 897 require.NoError(t, err) 898 sig, err := bls.SignatureFromBytes(sb) 899 require.NoError(t, err) 900 att.Signature = sig.Marshal() 901 } 902 903 broadcaster := &p2pMock.MockBroadcaster{} 904 s := &Server{ 905 ChainInfoFetcher: &chainMock.ChainService{State: state}, 906 AttestationsPool: &attestations.PoolMock{}, 907 Broadcaster: broadcaster, 908 } 909 910 _, err = s.SubmitAttestations(ctx, ðpb.SubmitAttestationsRequest{ 911 Data: []*ethpb.Attestation{attValid, attInvalidTarget, attInvalidSignature}, 912 }) 913 require.ErrorContains(t, "One or more attestations failed validation", err) 914 savedAtts := s.AttestationsPool.AggregatedAttestations() 915 require.Equal(t, 1, len(savedAtts)) 916 expectedAtt, err := attValid.HashTreeRoot() 917 require.NoError(t, err) 918 actualAtt, err := savedAtts[0].HashTreeRoot() 919 require.NoError(t, err) 920 assert.DeepEqual(t, expectedAtt, actualAtt) 921 assert.Equal(t, true, broadcaster.BroadcastCalled) 922 require.Equal(t, 1, len(broadcaster.BroadcastMessages)) 923 broadcastRoot, err := broadcaster.BroadcastMessages[0].(*eth.Attestation).HashTreeRoot() 924 require.NoError(t, err) 925 require.DeepEqual(t, expectedAtt, broadcastRoot) 926 } 927 928 func TestServer_SubmitAttestations_InvalidAttestationHeader(t *testing.T) { 929 ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) 930 931 params.SetupTestConfigCleanup(t) 932 c := params.BeaconConfig() 933 // Required for correct committee size calculation. 934 c.SlotsPerEpoch = 1 935 params.OverrideBeaconConfig(c) 936 937 _, keys, err := testutil.DeterministicDepositsAndKeys(1) 938 require.NoError(t, err) 939 validators := []*eth.Validator{ 940 { 941 PublicKey: keys[0].PublicKey().Marshal(), 942 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 943 }, 944 } 945 state, err := testutil.NewBeaconState(func(state *pb.BeaconState) error { 946 state.Validators = validators 947 state.Slot = 1 948 state.PreviousJustifiedCheckpoint = ð.Checkpoint{ 949 Epoch: 0, 950 Root: bytesutil.PadTo([]byte("sourceroot1"), 32), 951 } 952 return nil 953 }) 954 955 require.NoError(t, err) 956 957 b := bitfield.NewBitlist(1) 958 b.SetBitAt(0, true) 959 att := ðpb.Attestation{ 960 AggregationBits: b, 961 Data: ðpb.AttestationData{ 962 Slot: 0, 963 Index: 0, 964 BeaconBlockRoot: bytesutil.PadTo([]byte("beaconblockroot2"), 32), 965 Source: ðpb.Checkpoint{ 966 Epoch: 0, 967 Root: bytesutil.PadTo([]byte("sourceroot2"), 32), 968 }, 969 Target: ðpb.Checkpoint{ 970 Epoch: 99, 971 Root: bytesutil.PadTo([]byte("targetroot2"), 32), 972 }, 973 }, 974 Signature: make([]byte, 96), 975 } 976 977 sb, err := helpers.ComputeDomainAndSign( 978 state, 979 helpers.SlotToEpoch(att.Data.Slot), 980 att.Data, 981 params.BeaconConfig().DomainBeaconAttester, 982 keys[0], 983 ) 984 require.NoError(t, err) 985 sig, err := bls.SignatureFromBytes(sb) 986 require.NoError(t, err) 987 att.Signature = sig.Marshal() 988 989 broadcaster := &p2pMock.MockBroadcaster{} 990 s := &Server{ 991 ChainInfoFetcher: &chainMock.ChainService{State: state}, 992 AttestationsPool: &attestations.PoolMock{}, 993 Broadcaster: broadcaster, 994 } 995 996 _, err = s.SubmitAttestations(ctx, ðpb.SubmitAttestationsRequest{ 997 Data: []*ethpb.Attestation{att}, 998 }) 999 require.ErrorContains(t, "One or more attestations failed validation", err) 1000 sts, ok := grpc.ServerTransportStreamFromContext(ctx).(*runtime.ServerTransportStream) 1001 require.Equal(t, true, ok, "type assertion failed") 1002 md := sts.Header() 1003 v, ok := md[strings.ToLower(grpcutils.CustomErrorMetadataKey)] 1004 require.Equal(t, true, ok, "could not retrieve custom error metadata value") 1005 assert.DeepEqual( 1006 t, 1007 []string{"{\"failures\":[{\"index\":0,\"message\":\"expected target epoch (99) to be the previous epoch (0) or the current epoch (1)\"}]}"}, 1008 v, 1009 ) 1010 }