github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/eth/v1/beacon/blocks_test.go (about) 1 package beacon 2 3 import ( 4 "context" 5 "reflect" 6 "testing" 7 8 types "github.com/prysmaticlabs/eth2-types" 9 mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 10 "github.com/prysmaticlabs/prysm/beacon-chain/db" 11 dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 12 mockp2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" 13 p2ppb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 14 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1" 15 ethpb_alpha "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 16 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 17 "github.com/prysmaticlabs/prysm/proto/interfaces" 18 "github.com/prysmaticlabs/prysm/proto/migration" 19 "github.com/prysmaticlabs/prysm/shared/bytesutil" 20 "github.com/prysmaticlabs/prysm/shared/params" 21 "github.com/prysmaticlabs/prysm/shared/testutil" 22 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 23 "github.com/prysmaticlabs/prysm/shared/testutil/require" 24 ) 25 26 func fillDBTestBlocks(ctx context.Context, t *testing.T, beaconDB db.Database) (*ethpb_alpha.SignedBeaconBlock, []*ethpb_alpha.BeaconBlockContainer) { 27 parentRoot := [32]byte{1, 2, 3} 28 genBlk := testutil.NewBeaconBlock() 29 genBlk.Block.ParentRoot = parentRoot[:] 30 root, err := genBlk.Block.HashTreeRoot() 31 require.NoError(t, err) 32 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genBlk))) 33 require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, root)) 34 35 count := types.Slot(100) 36 blks := make([]interfaces.SignedBeaconBlock, count) 37 blkContainers := make([]*ethpb_alpha.BeaconBlockContainer, count) 38 for i := types.Slot(0); i < count; i++ { 39 b := testutil.NewBeaconBlock() 40 b.Block.Slot = i 41 b.Block.ParentRoot = bytesutil.PadTo([]byte{uint8(i)}, 32) 42 att1 := testutil.NewAttestation() 43 att1.Data.Slot = i 44 att1.Data.CommitteeIndex = types.CommitteeIndex(i) 45 att2 := testutil.NewAttestation() 46 att2.Data.Slot = i 47 att2.Data.CommitteeIndex = types.CommitteeIndex(i + 1) 48 b.Block.Body.Attestations = []*ethpb_alpha.Attestation{att1, att2} 49 root, err := b.Block.HashTreeRoot() 50 require.NoError(t, err) 51 blks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) 52 blkContainers[i] = ðpb_alpha.BeaconBlockContainer{Block: b, BlockRoot: root[:]} 53 } 54 require.NoError(t, beaconDB.SaveBlocks(ctx, blks)) 55 headRoot := bytesutil.ToBytes32(blkContainers[len(blks)-1].BlockRoot) 56 summary := &p2ppb.StateSummary{ 57 Root: headRoot[:], 58 Slot: blkContainers[len(blks)-1].Block.Block.Slot, 59 } 60 require.NoError(t, beaconDB.SaveStateSummary(ctx, summary)) 61 require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, headRoot)) 62 return genBlk, blkContainers 63 } 64 65 func TestServer_GetBlockHeader(t *testing.T) { 66 beaconDB := dbTest.SetupDB(t) 67 ctx := context.Background() 68 69 genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 70 root, err := genBlk.Block.HashTreeRoot() 71 require.NoError(t, err) 72 headBlock := blkContainers[len(blkContainers)-1] 73 74 b2 := testutil.NewBeaconBlock() 75 b2.Block.Slot = 30 76 b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) 77 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) 78 b3 := testutil.NewBeaconBlock() 79 b3.Block.Slot = 30 80 b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) 81 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) 82 83 bs := &Server{ 84 BeaconDB: beaconDB, 85 ChainInfoFetcher: &mock.ChainService{ 86 DB: beaconDB, 87 Block: wrapper.WrappedPhase0SignedBeaconBlock(headBlock.Block), 88 Root: headBlock.BlockRoot, 89 FinalizedCheckPoint: ðpb_alpha.Checkpoint{Root: blkContainers[64].BlockRoot}, 90 }, 91 } 92 93 tests := []struct { 94 name string 95 blockID []byte 96 want *ethpb_alpha.SignedBeaconBlock 97 wantErr bool 98 }{ 99 { 100 name: "slot", 101 blockID: []byte("30"), 102 want: blkContainers[30].Block, 103 }, 104 { 105 name: "root", 106 blockID: blkContainers[20].BlockRoot, 107 want: blkContainers[20].Block, 108 }, 109 { 110 name: "canonical", 111 blockID: []byte("30"), 112 want: blkContainers[30].Block, 113 }, 114 { 115 name: "genesis", 116 blockID: []byte("genesis"), 117 want: genBlk, 118 }, 119 { 120 name: "genesis root", 121 blockID: root[:], 122 want: genBlk, 123 }, 124 { 125 name: "head", 126 blockID: []byte("head"), 127 want: headBlock.Block, 128 }, 129 { 130 name: "finalized", 131 blockID: []byte("finalized"), 132 want: blkContainers[64].Block, 133 }, 134 { 135 name: "no block", 136 blockID: []byte("105"), 137 wantErr: true, 138 }, 139 } 140 for _, tt := range tests { 141 t.Run(tt.name, func(t *testing.T) { 142 header, err := bs.GetBlockHeader(ctx, ðpb.BlockRequest{ 143 BlockId: tt.blockID, 144 }) 145 if !tt.wantErr { 146 require.NoError(t, err) 147 } else { 148 require.NotEqual(t, err, nil) 149 return 150 } 151 152 blkHdr, err := migration.V1Alpha1BlockToV1BlockHeader(tt.want) 153 require.NoError(t, err) 154 155 if !reflect.DeepEqual(header.Data.Header.Message, blkHdr.Message) { 156 t.Error("Expected blocks to equal") 157 } 158 }) 159 } 160 } 161 162 func TestServer_ListBlockHeaders(t *testing.T) { 163 beaconDB := dbTest.SetupDB(t) 164 ctx := context.Background() 165 166 _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 167 headBlock := blkContainers[len(blkContainers)-1] 168 bs := &Server{ 169 BeaconDB: beaconDB, 170 ChainInfoFetcher: &mock.ChainService{ 171 DB: beaconDB, 172 Block: wrapper.WrappedPhase0SignedBeaconBlock(headBlock.Block), 173 Root: headBlock.BlockRoot, 174 FinalizedCheckPoint: ðpb_alpha.Checkpoint{Root: blkContainers[64].BlockRoot}, 175 }, 176 } 177 178 b2 := testutil.NewBeaconBlock() 179 b2.Block.Slot = 30 180 b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) 181 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) 182 b3 := testutil.NewBeaconBlock() 183 b3.Block.Slot = 30 184 b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) 185 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) 186 b4 := testutil.NewBeaconBlock() 187 b4.Block.Slot = 31 188 b4.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) 189 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b4))) 190 b5 := testutil.NewBeaconBlock() 191 b5.Block.Slot = 28 192 b5.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) 193 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b5))) 194 195 tests := []struct { 196 name string 197 slot types.Slot 198 parentRoot []byte 199 want []*ethpb_alpha.SignedBeaconBlock 200 wantErr bool 201 }{ 202 { 203 name: "slot", 204 slot: types.Slot(30), 205 want: []*ethpb_alpha.SignedBeaconBlock{ 206 blkContainers[30].Block, 207 b2, 208 b3, 209 }, 210 }, 211 { 212 name: "parent root", 213 parentRoot: b2.Block.ParentRoot, 214 want: []*ethpb_alpha.SignedBeaconBlock{ 215 blkContainers[1].Block, 216 b2, 217 b4, 218 b5, 219 }, 220 }, 221 } 222 for _, tt := range tests { 223 t.Run(tt.name, func(t *testing.T) { 224 headers, err := bs.ListBlockHeaders(ctx, ðpb.BlockHeadersRequest{ 225 Slot: &tt.slot, 226 ParentRoot: tt.parentRoot, 227 }) 228 require.NoError(t, err) 229 230 require.Equal(t, len(tt.want), len(headers.Data)) 231 for i, blk := range tt.want { 232 signedHdr, err := migration.V1Alpha1BlockToV1BlockHeader(blk) 233 require.NoError(t, err) 234 235 if !reflect.DeepEqual(headers.Data[i].Header.Message, signedHdr.Message) { 236 t.Error("Expected blocks to equal") 237 } 238 } 239 }) 240 } 241 } 242 243 func TestServer_ProposeBlock_OK(t *testing.T) { 244 beaconDB := dbTest.SetupDB(t) 245 ctx := context.Background() 246 params.SetupTestConfigCleanup(t) 247 params.OverrideBeaconConfig(params.MainnetConfig()) 248 249 genesis := testutil.NewBeaconBlock() 250 require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(genesis)), "Could not save genesis block") 251 252 numDeposits := uint64(64) 253 beaconState, _ := testutil.DeterministicGenesisState(t, numDeposits) 254 bsRoot, err := beaconState.HashTreeRoot(ctx) 255 require.NoError(t, err) 256 genesisRoot, err := genesis.Block.HashTreeRoot() 257 require.NoError(t, err) 258 require.NoError(t, beaconDB.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state") 259 260 c := &mock.ChainService{Root: bsRoot[:], State: beaconState} 261 beaconChainServer := &Server{ 262 BeaconDB: beaconDB, 263 BlockReceiver: c, 264 ChainInfoFetcher: c, 265 BlockNotifier: c.BlockNotifier(), 266 Broadcaster: mockp2p.NewTestP2P(t), 267 } 268 req := testutil.NewBeaconBlock() 269 req.Block.Slot = 5 270 req.Block.ParentRoot = bsRoot[:] 271 v1Block, err := migration.V1Alpha1ToV1Block(req) 272 require.NoError(t, err) 273 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(req))) 274 blockReq := ðpb.BeaconBlockContainer{ 275 Message: v1Block.Block, 276 Signature: v1Block.Signature, 277 } 278 _, err = beaconChainServer.SubmitBlock(context.Background(), blockReq) 279 assert.NoError(t, err, "Could not propose block correctly") 280 } 281 282 func TestServer_GetBlock(t *testing.T) { 283 beaconDB := dbTest.SetupDB(t) 284 ctx := context.Background() 285 286 _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 287 headBlock := blkContainers[len(blkContainers)-1] 288 289 b2 := testutil.NewBeaconBlock() 290 b2.Block.Slot = 30 291 b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) 292 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) 293 b3 := testutil.NewBeaconBlock() 294 b3.Block.Slot = 30 295 b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) 296 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) 297 298 bs := &Server{ 299 BeaconDB: beaconDB, 300 ChainInfoFetcher: &mock.ChainService{ 301 DB: beaconDB, 302 Block: wrapper.WrappedPhase0SignedBeaconBlock(headBlock.Block), 303 Root: headBlock.BlockRoot, 304 FinalizedCheckPoint: ðpb_alpha.Checkpoint{Root: blkContainers[64].BlockRoot}, 305 }, 306 } 307 308 genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 309 root, err := genBlk.Block.HashTreeRoot() 310 require.NoError(t, err) 311 312 tests := []struct { 313 name string 314 blockID []byte 315 want *ethpb_alpha.SignedBeaconBlock 316 wantErr bool 317 }{ 318 { 319 name: "slot", 320 blockID: []byte("30"), 321 want: blkContainers[30].Block, 322 }, 323 { 324 name: "bad formatting", 325 blockID: []byte("3bad0"), 326 wantErr: true, 327 }, 328 { 329 name: "canonical", 330 blockID: []byte("30"), 331 want: blkContainers[30].Block, 332 }, 333 { 334 name: "head", 335 blockID: []byte("head"), 336 want: headBlock.Block, 337 }, 338 { 339 name: "finalized", 340 blockID: []byte("finalized"), 341 want: blkContainers[64].Block, 342 }, 343 { 344 name: "genesis", 345 blockID: []byte("genesis"), 346 want: genBlk, 347 }, 348 { 349 name: "genesis root", 350 blockID: root[:], 351 want: genBlk, 352 }, 353 { 354 name: "root", 355 blockID: blkContainers[20].BlockRoot, 356 want: blkContainers[20].Block, 357 }, 358 { 359 name: "non-existent root", 360 blockID: bytesutil.PadTo([]byte("hi there"), 32), 361 wantErr: true, 362 }, 363 { 364 name: "slot", 365 blockID: []byte("40"), 366 want: blkContainers[40].Block, 367 }, 368 { 369 name: "no block", 370 blockID: []byte("105"), 371 wantErr: true, 372 }, 373 } 374 for _, tt := range tests { 375 t.Run(tt.name, func(t *testing.T) { 376 block, err := bs.GetBlock(ctx, ðpb.BlockRequest{ 377 BlockId: tt.blockID, 378 }) 379 if tt.wantErr { 380 require.NotEqual(t, err, nil) 381 return 382 } 383 require.NoError(t, err) 384 385 v1Block, err := migration.V1Alpha1ToV1Block(tt.want) 386 require.NoError(t, err) 387 388 if !reflect.DeepEqual(block.Data.Message, v1Block.Block) { 389 t.Error("Expected blocks to equal") 390 } 391 }) 392 } 393 } 394 395 func TestServer_GetBlockSSZ(t *testing.T) { 396 beaconDB := dbTest.SetupDB(t) 397 ctx := context.Background() 398 399 _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 400 headBlock := blkContainers[len(blkContainers)-1] 401 402 b2 := testutil.NewBeaconBlock() 403 b2.Block.Slot = 30 404 b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) 405 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) 406 407 bs := &Server{ 408 BeaconDB: beaconDB, 409 ChainInfoFetcher: &mock.ChainService{ 410 DB: beaconDB, 411 Block: wrapper.WrappedPhase0SignedBeaconBlock(headBlock.Block), 412 Root: headBlock.BlockRoot, 413 FinalizedCheckPoint: ðpb_alpha.Checkpoint{Root: blkContainers[64].BlockRoot}, 414 }, 415 } 416 417 ok, blocks, err := beaconDB.BlocksBySlot(ctx, 30) 418 require.Equal(t, true, ok) 419 require.NoError(t, err) 420 sszBlock, err := blocks[0].MarshalSSZ() 421 require.NoError(t, err) 422 423 resp, err := bs.GetBlockSSZ(ctx, ðpb.BlockRequest{BlockId: []byte("30")}) 424 require.NoError(t, err) 425 assert.NotNil(t, resp) 426 assert.DeepEqual(t, sszBlock, resp.Data) 427 } 428 429 func TestServer_GetBlockRoot(t *testing.T) { 430 beaconDB := dbTest.SetupDB(t) 431 ctx := context.Background() 432 433 genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 434 headBlock := blkContainers[len(blkContainers)-1] 435 b2 := testutil.NewBeaconBlock() 436 b2.Block.Slot = 30 437 b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) 438 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) 439 b3 := testutil.NewBeaconBlock() 440 b3.Block.Slot = 30 441 b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) 442 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) 443 444 bs := &Server{ 445 BeaconDB: beaconDB, 446 ChainInfoFetcher: &mock.ChainService{ 447 DB: beaconDB, 448 Block: wrapper.WrappedPhase0SignedBeaconBlock(headBlock.Block), 449 Root: headBlock.BlockRoot, 450 FinalizedCheckPoint: ðpb_alpha.Checkpoint{Root: blkContainers[64].BlockRoot}, 451 }, 452 } 453 454 root, err := genBlk.Block.HashTreeRoot() 455 require.NoError(t, err) 456 457 tests := []struct { 458 name string 459 blockID []byte 460 want []byte 461 wantErr bool 462 }{ 463 { 464 name: "bad formatting", 465 blockID: []byte("3bad0"), 466 wantErr: true, 467 }, 468 { 469 name: "canonical slot", 470 blockID: []byte("30"), 471 want: blkContainers[30].BlockRoot, 472 }, 473 { 474 name: "head", 475 blockID: []byte("head"), 476 want: headBlock.BlockRoot, 477 }, 478 { 479 name: "finalized", 480 blockID: []byte("finalized"), 481 want: blkContainers[64].BlockRoot, 482 }, 483 { 484 name: "genesis", 485 blockID: []byte("genesis"), 486 want: root[:], 487 }, 488 { 489 name: "genesis root", 490 blockID: root[:], 491 want: root[:], 492 }, 493 { 494 name: "root", 495 blockID: blkContainers[20].BlockRoot, 496 want: blkContainers[20].BlockRoot, 497 }, 498 { 499 name: "non-existent root", 500 blockID: bytesutil.PadTo([]byte("hi there"), 32), 501 wantErr: true, 502 }, 503 { 504 name: "slot", 505 blockID: []byte("40"), 506 want: blkContainers[40].BlockRoot, 507 }, 508 { 509 name: "no block", 510 blockID: []byte("105"), 511 wantErr: true, 512 }, 513 } 514 for _, tt := range tests { 515 t.Run(tt.name, func(t *testing.T) { 516 blockRootResp, err := bs.GetBlockRoot(ctx, ðpb.BlockRequest{ 517 BlockId: tt.blockID, 518 }) 519 if tt.wantErr { 520 require.NotEqual(t, err, nil) 521 return 522 } 523 require.NoError(t, err) 524 assert.DeepEqual(t, tt.want, blockRootResp.Data.Root) 525 }) 526 } 527 } 528 529 func TestServer_ListBlockAttestations(t *testing.T) { 530 beaconDB := dbTest.SetupDB(t) 531 ctx := context.Background() 532 533 _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 534 headBlock := blkContainers[len(blkContainers)-1] 535 bs := &Server{ 536 BeaconDB: beaconDB, 537 ChainInfoFetcher: &mock.ChainService{ 538 DB: beaconDB, 539 Block: wrapper.WrappedPhase0SignedBeaconBlock(headBlock.Block), 540 Root: headBlock.BlockRoot, 541 FinalizedCheckPoint: ðpb_alpha.Checkpoint{Root: blkContainers[64].BlockRoot}, 542 }, 543 } 544 545 genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) 546 root, err := genBlk.Block.HashTreeRoot() 547 require.NoError(t, err) 548 549 tests := []struct { 550 name string 551 blockID []byte 552 want *ethpb_alpha.SignedBeaconBlock 553 wantErr bool 554 }{ 555 { 556 name: "slot", 557 blockID: []byte("30"), 558 want: blkContainers[30].Block, 559 }, 560 { 561 name: "bad formatting", 562 blockID: []byte("3bad0"), 563 wantErr: true, 564 }, 565 { 566 name: "head", 567 blockID: []byte("head"), 568 want: headBlock.Block, 569 }, 570 { 571 name: "finalized", 572 blockID: []byte("finalized"), 573 want: blkContainers[64].Block, 574 }, 575 { 576 name: "genesis", 577 blockID: []byte("genesis"), 578 want: genBlk, 579 }, 580 { 581 name: "genesis root", 582 blockID: root[:], 583 want: genBlk, 584 }, 585 { 586 name: "root", 587 blockID: blkContainers[20].BlockRoot, 588 want: blkContainers[20].Block, 589 }, 590 { 591 name: "non-existent root", 592 blockID: bytesutil.PadTo([]byte("hi there"), 32), 593 wantErr: true, 594 }, 595 { 596 name: "slot", 597 blockID: []byte("40"), 598 want: blkContainers[40].Block, 599 }, 600 { 601 name: "no block", 602 blockID: []byte("105"), 603 wantErr: true, 604 }, 605 } 606 for _, tt := range tests { 607 t.Run(tt.name, func(t *testing.T) { 608 block, err := bs.ListBlockAttestations(ctx, ðpb.BlockRequest{ 609 BlockId: tt.blockID, 610 }) 611 if tt.wantErr { 612 require.NotEqual(t, err, nil) 613 return 614 } 615 require.NoError(t, err) 616 617 v1Block, err := migration.V1Alpha1ToV1Block(tt.want) 618 require.NoError(t, err) 619 620 if !reflect.DeepEqual(block.Data, v1Block.Block.Body.Attestations) { 621 t.Error("Expected attestations to equal") 622 } 623 }) 624 } 625 }