github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/db/kv/blocks_test.go (about) 1 package kv 2 3 import ( 4 "context" 5 "sort" 6 "testing" 7 8 types "github.com/prysmaticlabs/eth2-types" 9 "github.com/prysmaticlabs/prysm/beacon-chain/db/filters" 10 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 11 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 12 "github.com/prysmaticlabs/prysm/proto/interfaces" 13 "github.com/prysmaticlabs/prysm/shared/bytesutil" 14 "github.com/prysmaticlabs/prysm/shared/params" 15 "github.com/prysmaticlabs/prysm/shared/testutil" 16 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 17 "github.com/prysmaticlabs/prysm/shared/testutil/require" 18 "google.golang.org/protobuf/proto" 19 ) 20 21 func TestStore_SaveBlock_NoDuplicates(t *testing.T) { 22 BlockCacheSize = 1 23 db := setupDB(t) 24 slot := types.Slot(20) 25 ctx := context.Background() 26 // First we save a previous block to ensure the cache max size is reached. 27 prevBlock := testutil.NewBeaconBlock() 28 prevBlock.Block.Slot = slot - 1 29 prevBlock.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) 30 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(prevBlock))) 31 32 block := testutil.NewBeaconBlock() 33 block.Block.Slot = slot 34 block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) 35 // Even with a full cache, saving new blocks should not cause 36 // duplicated blocks in the DB. 37 for i := 0; i < 100; i++ { 38 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block))) 39 } 40 f := filters.NewFilter().SetStartSlot(slot).SetEndSlot(slot) 41 retrieved, _, err := db.Blocks(ctx, f) 42 require.NoError(t, err) 43 assert.Equal(t, 1, len(retrieved)) 44 // We reset the block cache size. 45 BlockCacheSize = 256 46 } 47 48 func TestStore_BlocksCRUD(t *testing.T) { 49 db := setupDB(t) 50 ctx := context.Background() 51 52 block := testutil.NewBeaconBlock() 53 block.Block.Slot = 20 54 block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) 55 56 blockRoot, err := block.Block.HashTreeRoot() 57 require.NoError(t, err) 58 retrievedBlock, err := db.Block(ctx, blockRoot) 59 require.NoError(t, err) 60 assert.DeepEqual(t, (*ethpb.SignedBeaconBlock)(nil), retrievedBlock.Proto(), "Expected nil block") 61 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block))) 62 assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db") 63 retrievedBlock, err = db.Block(ctx, blockRoot) 64 require.NoError(t, err) 65 assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock) 66 require.NoError(t, db.deleteBlock(ctx, blockRoot)) 67 assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db") 68 } 69 70 func TestStore_BlocksBatchDelete(t *testing.T) { 71 db := setupDB(t) 72 ctx := context.Background() 73 numBlocks := 10 74 totalBlocks := make([]interfaces.SignedBeaconBlock, numBlocks) 75 blockRoots := make([][32]byte, 0) 76 oddBlocks := make([]interfaces.SignedBeaconBlock, 0) 77 for i := 0; i < len(totalBlocks); i++ { 78 b := testutil.NewBeaconBlock() 79 b.Block.Slot = types.Slot(i) 80 b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 81 totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) 82 if i%2 == 0 { 83 r, err := totalBlocks[i].Block().HashTreeRoot() 84 require.NoError(t, err) 85 blockRoots = append(blockRoots, r) 86 } else { 87 oddBlocks = append(oddBlocks, totalBlocks[i]) 88 } 89 } 90 require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) 91 retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32))) 92 require.NoError(t, err) 93 assert.Equal(t, numBlocks, len(retrieved), "Unexpected number of blocks received") 94 // We delete all even indexed blocks. 95 require.NoError(t, db.deleteBlocks(ctx, blockRoots)) 96 // When we retrieve the data, only the odd indexed blocks should remain. 97 retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32))) 98 require.NoError(t, err) 99 sort.Slice(retrieved, func(i, j int) bool { 100 return retrieved[i].Block().Slot() < retrieved[j].Block().Slot() 101 }) 102 for i, block := range retrieved { 103 assert.Equal(t, true, proto.Equal(block.Proto(), oddBlocks[i].Proto()), "Wanted: %v, received: %v", block, oddBlocks[i]) 104 } 105 } 106 107 func TestStore_BlocksHandleZeroCase(t *testing.T) { 108 db := setupDB(t) 109 ctx := context.Background() 110 numBlocks := 10 111 totalBlocks := make([]interfaces.SignedBeaconBlock, numBlocks) 112 for i := 0; i < len(totalBlocks); i++ { 113 b := testutil.NewBeaconBlock() 114 b.Block.Slot = types.Slot(i) 115 b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 116 totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) 117 _, err := totalBlocks[i].Block().HashTreeRoot() 118 require.NoError(t, err) 119 } 120 require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) 121 zeroFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(0) 122 retrieved, _, err := db.Blocks(ctx, zeroFilter) 123 require.NoError(t, err) 124 assert.Equal(t, 1, len(retrieved), "Unexpected number of blocks received, expected one") 125 } 126 127 func TestStore_BlocksHandleInvalidEndSlot(t *testing.T) { 128 db := setupDB(t) 129 ctx := context.Background() 130 numBlocks := 10 131 totalBlocks := make([]interfaces.SignedBeaconBlock, numBlocks) 132 // Save blocks from slot 1 onwards. 133 for i := 0; i < len(totalBlocks); i++ { 134 b := testutil.NewBeaconBlock() 135 b.Block.Slot = types.Slot(i) + 1 136 b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 137 totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) 138 _, err := totalBlocks[i].Block().HashTreeRoot() 139 require.NoError(t, err) 140 } 141 require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) 142 badFilter := filters.NewFilter().SetStartSlot(5).SetEndSlot(1) 143 _, _, err := db.Blocks(ctx, badFilter) 144 require.ErrorContains(t, errInvalidSlotRange.Error(), err) 145 146 goodFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(1) 147 requested, _, err := db.Blocks(ctx, goodFilter) 148 require.NoError(t, err) 149 assert.Equal(t, 1, len(requested), "Unexpected number of blocks received, only expected two") 150 } 151 152 func TestStore_GenesisBlock(t *testing.T) { 153 db := setupDB(t) 154 ctx := context.Background() 155 genesisBlock := testutil.NewBeaconBlock() 156 genesisBlock.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) 157 blockRoot, err := genesisBlock.Block.HashTreeRoot() 158 require.NoError(t, err) 159 require.NoError(t, db.SaveGenesisBlockRoot(ctx, blockRoot)) 160 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlock))) 161 retrievedBlock, err := db.GenesisBlock(ctx) 162 require.NoError(t, err) 163 assert.Equal(t, true, proto.Equal(genesisBlock, retrievedBlock.Proto()), "Wanted: %v, received: %v", genesisBlock, retrievedBlock) 164 } 165 166 func TestStore_BlocksCRUD_NoCache(t *testing.T) { 167 db := setupDB(t) 168 ctx := context.Background() 169 block := testutil.NewBeaconBlock() 170 block.Block.Slot = 20 171 block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) 172 blockRoot, err := block.Block.HashTreeRoot() 173 require.NoError(t, err) 174 retrievedBlock, err := db.Block(ctx, blockRoot) 175 require.NoError(t, err) 176 require.DeepEqual(t, (*ethpb.SignedBeaconBlock)(nil), retrievedBlock.Proto(), "Expected nil block") 177 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block))) 178 db.blockCache.Del(string(blockRoot[:])) 179 assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db") 180 retrievedBlock, err = db.Block(ctx, blockRoot) 181 require.NoError(t, err) 182 assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock) 183 require.NoError(t, db.deleteBlock(ctx, blockRoot)) 184 assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db") 185 } 186 187 func TestStore_Blocks_FiltersCorrectly(t *testing.T) { 188 db := setupDB(t) 189 b4 := testutil.NewBeaconBlock() 190 b4.Block.Slot = 4 191 b4.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 192 b5 := testutil.NewBeaconBlock() 193 b5.Block.Slot = 5 194 b5.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32) 195 b6 := testutil.NewBeaconBlock() 196 b6.Block.Slot = 6 197 b6.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32) 198 b7 := testutil.NewBeaconBlock() 199 b7.Block.Slot = 7 200 b7.Block.ParentRoot = bytesutil.PadTo([]byte("parent3"), 32) 201 b8 := testutil.NewBeaconBlock() 202 b8.Block.Slot = 8 203 b8.Block.ParentRoot = bytesutil.PadTo([]byte("parent4"), 32) 204 blocks := []interfaces.SignedBeaconBlock{ 205 wrapper.WrappedPhase0SignedBeaconBlock(b4), 206 wrapper.WrappedPhase0SignedBeaconBlock(b5), 207 wrapper.WrappedPhase0SignedBeaconBlock(b6), 208 wrapper.WrappedPhase0SignedBeaconBlock(b7), 209 wrapper.WrappedPhase0SignedBeaconBlock(b8), 210 } 211 ctx := context.Background() 212 require.NoError(t, db.SaveBlocks(ctx, blocks)) 213 214 tests := []struct { 215 filter *filters.QueryFilter 216 expectedNumBlocks int 217 }{ 218 { 219 filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)), 220 expectedNumBlocks: 2, 221 }, 222 { 223 // No block meets the criteria below. 224 filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte{3, 4, 5}, 32)), 225 expectedNumBlocks: 0, 226 }, 227 { 228 // Block slot range filter criteria. 229 filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(7), 230 expectedNumBlocks: 3, 231 }, 232 { 233 filter: filters.NewFilter().SetStartSlot(7).SetEndSlot(7), 234 expectedNumBlocks: 1, 235 }, 236 { 237 filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(8), 238 expectedNumBlocks: 5, 239 }, 240 { 241 filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(5), 242 expectedNumBlocks: 2, 243 }, 244 { 245 filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(9), 246 expectedNumBlocks: 4, 247 }, 248 { 249 filter: filters.NewFilter().SetEndSlot(7), 250 expectedNumBlocks: 4, 251 }, 252 { 253 filter: filters.NewFilter().SetEndSlot(8), 254 expectedNumBlocks: 5, 255 }, 256 { 257 filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(10), 258 expectedNumBlocks: 4, 259 }, 260 { 261 // Composite filter criteria. 262 filter: filters.NewFilter(). 263 SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)). 264 SetStartSlot(6). 265 SetEndSlot(8), 266 expectedNumBlocks: 1, 267 }, 268 } 269 for _, tt := range tests { 270 retrievedBlocks, _, err := db.Blocks(ctx, tt.filter) 271 require.NoError(t, err) 272 assert.Equal(t, tt.expectedNumBlocks, len(retrievedBlocks), "Unexpected number of blocks") 273 } 274 } 275 276 func TestStore_Blocks_VerifyBlockRoots(t *testing.T) { 277 ctx := context.Background() 278 db := setupDB(t) 279 b1 := testutil.NewBeaconBlock() 280 b1.Block.Slot = 1 281 r1, err := b1.Block.HashTreeRoot() 282 require.NoError(t, err) 283 b2 := testutil.NewBeaconBlock() 284 b2.Block.Slot = 2 285 r2, err := b2.Block.HashTreeRoot() 286 require.NoError(t, err) 287 288 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) 289 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) 290 291 filter := filters.NewFilter().SetStartSlot(b1.Block.Slot).SetEndSlot(b2.Block.Slot) 292 roots, err := db.BlockRoots(ctx, filter) 293 require.NoError(t, err) 294 295 assert.DeepEqual(t, [][32]byte{r1, r2}, roots) 296 } 297 298 func TestStore_Blocks_Retrieve_SlotRange(t *testing.T) { 299 db := setupDB(t) 300 totalBlocks := make([]interfaces.SignedBeaconBlock, 500) 301 for i := 0; i < 500; i++ { 302 b := testutil.NewBeaconBlock() 303 b.Block.Slot = types.Slot(i) 304 b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 305 totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) 306 } 307 ctx := context.Background() 308 require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) 309 retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399)) 310 require.NoError(t, err) 311 assert.Equal(t, 300, len(retrieved)) 312 } 313 314 func TestStore_Blocks_Retrieve_Epoch(t *testing.T) { 315 db := setupDB(t) 316 slots := params.BeaconConfig().SlotsPerEpoch.Mul(7) 317 totalBlocks := make([]interfaces.SignedBeaconBlock, slots) 318 for i := types.Slot(0); i < slots; i++ { 319 b := testutil.NewBeaconBlock() 320 b.Block.Slot = i 321 b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 322 totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) 323 } 324 ctx := context.Background() 325 require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) 326 retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartEpoch(5).SetEndEpoch(6)) 327 require.NoError(t, err) 328 want := params.BeaconConfig().SlotsPerEpoch.Mul(2) 329 assert.Equal(t, uint64(want), uint64(len(retrieved))) 330 retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetStartEpoch(0).SetEndEpoch(0)) 331 require.NoError(t, err) 332 want = params.BeaconConfig().SlotsPerEpoch 333 assert.Equal(t, uint64(want), uint64(len(retrieved))) 334 } 335 336 func TestStore_Blocks_Retrieve_SlotRangeWithStep(t *testing.T) { 337 db := setupDB(t) 338 totalBlocks := make([]interfaces.SignedBeaconBlock, 500) 339 for i := 0; i < 500; i++ { 340 b := testutil.NewBeaconBlock() 341 b.Block.Slot = types.Slot(i) 342 b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 343 totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) 344 } 345 const step = 2 346 ctx := context.Background() 347 require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) 348 retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399).SetSlotStep(step)) 349 require.NoError(t, err) 350 assert.Equal(t, 150, len(retrieved)) 351 for _, b := range retrieved { 352 assert.Equal(t, types.Slot(0), (b.Block().Slot()-100)%step, "Unexpect block slot %d", b.Block().Slot()) 353 } 354 } 355 356 func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) { 357 db := setupDB(t) 358 ctx := context.Background() 359 360 block1 := testutil.NewBeaconBlock() 361 block1.Block.Slot = 1 362 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block1))) 363 block2 := testutil.NewBeaconBlock() 364 block2.Block.Slot = 10 365 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block2))) 366 block3 := testutil.NewBeaconBlock() 367 block3.Block.Slot = 100 368 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block3))) 369 370 highestAt, err := db.HighestSlotBlocksBelow(ctx, 2) 371 require.NoError(t, err) 372 assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice") 373 assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0]) 374 highestAt, err = db.HighestSlotBlocksBelow(ctx, 11) 375 require.NoError(t, err) 376 assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice") 377 assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0]) 378 highestAt, err = db.HighestSlotBlocksBelow(ctx, 101) 379 require.NoError(t, err) 380 assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice") 381 assert.Equal(t, true, proto.Equal(block3, highestAt[0].Proto()), "Wanted: %v, received: %v", block3, highestAt[0]) 382 383 r3, err := block3.Block.HashTreeRoot() 384 require.NoError(t, err) 385 require.NoError(t, db.deleteBlock(ctx, r3)) 386 387 highestAt, err = db.HighestSlotBlocksBelow(ctx, 101) 388 require.NoError(t, err) 389 assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0]) 390 } 391 392 func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) { 393 db := setupDB(t) 394 ctx := context.Background() 395 396 genesisBlock := testutil.NewBeaconBlock() 397 genesisRoot, err := genesisBlock.Block.HashTreeRoot() 398 require.NoError(t, err) 399 require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot)) 400 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlock))) 401 block1 := testutil.NewBeaconBlock() 402 block1.Block.Slot = 1 403 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block1))) 404 405 highestAt, err := db.HighestSlotBlocksBelow(ctx, 2) 406 require.NoError(t, err) 407 assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0]) 408 highestAt, err = db.HighestSlotBlocksBelow(ctx, 1) 409 require.NoError(t, err) 410 assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0]) 411 highestAt, err = db.HighestSlotBlocksBelow(ctx, 0) 412 require.NoError(t, err) 413 assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0]) 414 } 415 416 func TestStore_SaveBlocks_HasCachedBlocks(t *testing.T) { 417 db := setupDB(t) 418 ctx := context.Background() 419 420 b := make([]interfaces.SignedBeaconBlock, 500) 421 for i := 0; i < 500; i++ { 422 blk := testutil.NewBeaconBlock() 423 blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 424 blk.Block.Slot = types.Slot(i) 425 b[i] = wrapper.WrappedPhase0SignedBeaconBlock(blk) 426 } 427 428 require.NoError(t, db.SaveBlock(ctx, b[0])) 429 require.NoError(t, db.SaveBlocks(ctx, b)) 430 f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500) 431 432 blks, _, err := db.Blocks(ctx, f) 433 require.NoError(t, err) 434 assert.Equal(t, 500, len(blks), "Did not get wanted blocks") 435 } 436 437 func TestStore_SaveBlocks_HasRootsMatched(t *testing.T) { 438 db := setupDB(t) 439 ctx := context.Background() 440 441 b := make([]interfaces.SignedBeaconBlock, 500) 442 for i := 0; i < 500; i++ { 443 blk := testutil.NewBeaconBlock() 444 blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) 445 blk.Block.Slot = types.Slot(i) 446 b[i] = wrapper.WrappedPhase0SignedBeaconBlock(blk) 447 } 448 449 require.NoError(t, db.SaveBlocks(ctx, b)) 450 f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500) 451 452 blks, roots, err := db.Blocks(ctx, f) 453 require.NoError(t, err) 454 assert.Equal(t, 500, len(blks), "Did not get wanted blocks") 455 456 for i, blk := range blks { 457 rt, err := blk.Block().HashTreeRoot() 458 require.NoError(t, err) 459 assert.Equal(t, roots[i], rt, "mismatch of block roots") 460 } 461 } 462 463 func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) { 464 db := setupDB(t) 465 ctx := context.Background() 466 467 b1 := testutil.NewBeaconBlock() 468 b1.Block.Slot = 20 469 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) 470 b2 := testutil.NewBeaconBlock() 471 b2.Block.Slot = 100 472 b2.Block.ParentRoot = bytesutil.PadTo([]byte("parent1"), 32) 473 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) 474 b3 := testutil.NewBeaconBlock() 475 b3.Block.Slot = 100 476 b3.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32) 477 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3))) 478 479 r1, err := b1.Block.HashTreeRoot() 480 require.NoError(t, err) 481 r2, err := b2.Block.HashTreeRoot() 482 require.NoError(t, err) 483 r3, err := b3.Block.HashTreeRoot() 484 require.NoError(t, err) 485 486 hasBlocks, retrievedBlocks, err := db.BlocksBySlot(ctx, 1) 487 require.NoError(t, err) 488 assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none") 489 assert.Equal(t, false, hasBlocks, "Expected no blocks") 490 hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 20) 491 require.NoError(t, err) 492 assert.Equal(t, true, proto.Equal(b1, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b1, retrievedBlocks[0]) 493 assert.Equal(t, true, hasBlocks, "Expected to have blocks") 494 hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 100) 495 require.NoError(t, err) 496 assert.Equal(t, true, proto.Equal(b2, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b2, retrievedBlocks[0]) 497 assert.Equal(t, true, proto.Equal(b3, retrievedBlocks[1].Proto()), "Wanted: %v, received: %v", b3, retrievedBlocks[1]) 498 assert.Equal(t, true, hasBlocks, "Expected to have blocks") 499 500 hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1) 501 require.NoError(t, err) 502 assert.DeepEqual(t, [][32]byte{}, retrievedBlockRoots) 503 assert.Equal(t, false, hasBlockRoots, "Expected no block roots") 504 hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 20) 505 require.NoError(t, err) 506 assert.DeepEqual(t, [][32]byte{r1}, retrievedBlockRoots) 507 assert.Equal(t, true, hasBlockRoots, "Expected no block roots") 508 hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 100) 509 require.NoError(t, err) 510 assert.DeepEqual(t, [][32]byte{r2, r3}, retrievedBlockRoots) 511 assert.Equal(t, true, hasBlockRoots, "Expected no block roots") 512 }