github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/blockchain/process_block_test.go (about) 1 package blockchain 2 3 import ( 4 "context" 5 "fmt" 6 "math/big" 7 "strconv" 8 "testing" 9 "time" 10 11 "github.com/pkg/errors" 12 types "github.com/prysmaticlabs/eth2-types" 13 mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 14 "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" 15 "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" 16 "github.com/prysmaticlabs/prysm/beacon-chain/core/state" 17 "github.com/prysmaticlabs/prysm/beacon-chain/db" 18 testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 19 "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" 20 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 21 "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" 22 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" 23 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 24 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 25 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 26 "github.com/prysmaticlabs/prysm/proto/interfaces" 27 "github.com/prysmaticlabs/prysm/shared/attestationutil" 28 "github.com/prysmaticlabs/prysm/shared/bytesutil" 29 "github.com/prysmaticlabs/prysm/shared/featureconfig" 30 "github.com/prysmaticlabs/prysm/shared/params" 31 "github.com/prysmaticlabs/prysm/shared/testutil" 32 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 33 "github.com/prysmaticlabs/prysm/shared/testutil/require" 34 "github.com/prysmaticlabs/prysm/shared/timeutils" 35 ) 36 37 func TestStore_OnBlock(t *testing.T) { 38 ctx := context.Background() 39 beaconDB := testDB.SetupDB(t) 40 41 cfg := &Config{ 42 BeaconDB: beaconDB, 43 StateGen: stategen.New(beaconDB), 44 ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), 45 } 46 service, err := NewService(ctx, cfg) 47 require.NoError(t, err) 48 genesisStateRoot := [32]byte{} 49 genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) 50 assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) 51 validGenesisRoot, err := genesis.Block.HashTreeRoot() 52 require.NoError(t, err) 53 st, err := testutil.NewBeaconState() 54 require.NoError(t, err) 55 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot)) 56 roots, err := blockTree1(t, beaconDB, validGenesisRoot[:]) 57 require.NoError(t, err) 58 random := testutil.NewBeaconBlock() 59 random.Block.Slot = 1 60 random.Block.ParentRoot = validGenesisRoot[:] 61 assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(random))) 62 randomParentRoot, err := random.Block.HashTreeRoot() 63 assert.NoError(t, err) 64 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]})) 65 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), randomParentRoot)) 66 randomParentRoot2 := roots[1] 67 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2})) 68 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2))) 69 70 tests := []struct { 71 name string 72 blk *ethpb.SignedBeaconBlock 73 s iface.BeaconState 74 time uint64 75 wantErrString string 76 }{ 77 { 78 name: "parent block root does not have a state", 79 blk: testutil.NewBeaconBlock(), 80 s: st.Copy(), 81 wantErrString: "could not reconstruct parent state", 82 }, 83 { 84 name: "block is from the future", 85 blk: func() *ethpb.SignedBeaconBlock { 86 b := testutil.NewBeaconBlock() 87 b.Block.ParentRoot = randomParentRoot2 88 b.Block.Slot = params.BeaconConfig().FarFutureSlot 89 return b 90 }(), 91 s: st.Copy(), 92 wantErrString: "is in the far distant future", 93 }, 94 { 95 name: "could not get finalized block", 96 blk: func() *ethpb.SignedBeaconBlock { 97 b := testutil.NewBeaconBlock() 98 b.Block.ParentRoot = randomParentRoot[:] 99 return b 100 }(), 101 s: st.Copy(), 102 wantErrString: "is not a descendent of the current finalized block", 103 }, 104 { 105 name: "same slot as finalized block", 106 blk: func() *ethpb.SignedBeaconBlock { 107 b := testutil.NewBeaconBlock() 108 b.Block.Slot = 0 109 b.Block.ParentRoot = randomParentRoot2 110 return b 111 }(), 112 s: st.Copy(), 113 wantErrString: "block is equal or earlier than finalized block, slot 0 < slot 0", 114 }, 115 } 116 117 for _, tt := range tests { 118 t.Run(tt.name, func(t *testing.T) { 119 service.justifiedCheckpt = ðpb.Checkpoint{Root: validGenesisRoot[:]} 120 service.bestJustifiedCheckpt = ðpb.Checkpoint{Root: validGenesisRoot[:]} 121 service.finalizedCheckpt = ðpb.Checkpoint{Root: validGenesisRoot[:]} 122 service.prevFinalizedCheckpt = ðpb.Checkpoint{Root: validGenesisRoot[:]} 123 service.finalizedCheckpt.Root = roots[0] 124 125 root, err := tt.blk.Block.HashTreeRoot() 126 assert.NoError(t, err) 127 err = service.onBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(tt.blk), root) 128 assert.ErrorContains(t, tt.wantErrString, err) 129 }) 130 } 131 } 132 133 func TestStore_OnBlockBatch(t *testing.T) { 134 ctx := context.Background() 135 beaconDB := testDB.SetupDB(t) 136 137 cfg := &Config{ 138 BeaconDB: beaconDB, 139 StateGen: stategen.New(beaconDB), 140 } 141 service, err := NewService(ctx, cfg) 142 require.NoError(t, err) 143 144 genesisStateRoot := [32]byte{} 145 genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) 146 assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) 147 gRoot, err := genesis.Block.HashTreeRoot() 148 require.NoError(t, err) 149 service.finalizedCheckpt = ðpb.Checkpoint{ 150 Root: gRoot[:], 151 } 152 service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{}) 153 service.saveInitSyncBlock(gRoot, wrapper.WrappedPhase0SignedBeaconBlock(genesis)) 154 155 st, keys := testutil.DeterministicGenesisState(t, 64) 156 157 bState := st.Copy() 158 159 var blks []interfaces.SignedBeaconBlock 160 var blkRoots [][32]byte 161 var firstState iface.BeaconState 162 for i := 1; i < 10; i++ { 163 b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), types.Slot(i)) 164 require.NoError(t, err) 165 bState, err = state.ExecuteStateTransition(ctx, bState, wrapper.WrappedPhase0SignedBeaconBlock(b)) 166 require.NoError(t, err) 167 if i == 1 { 168 firstState = bState.Copy() 169 } 170 root, err := b.Block.HashTreeRoot() 171 require.NoError(t, err) 172 service.saveInitSyncBlock(root, wrapper.WrappedPhase0SignedBeaconBlock(b)) 173 blks = append(blks, wrapper.WrappedPhase0SignedBeaconBlock(b)) 174 blkRoots = append(blkRoots, root) 175 } 176 177 rBlock, err := blks[0].PbPhase0Block() 178 assert.NoError(t, err) 179 rBlock.Block.ParentRoot = gRoot[:] 180 require.NoError(t, beaconDB.SaveBlock(context.Background(), blks[0])) 181 require.NoError(t, service.cfg.StateGen.SaveState(ctx, blkRoots[0], firstState)) 182 _, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:]) 183 require.NoError(t, err) 184 } 185 186 func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) { 187 ctx := context.Background() 188 beaconDB := testDB.SetupDB(t) 189 params.UseMinimalConfig() 190 defer params.UseMainnetConfig() 191 192 cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})} 193 service, err := NewService(ctx, cfg) 194 require.NoError(t, err) 195 service.genesisTime = time.Now() 196 197 update, err := service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: make([]byte, 32)}) 198 require.NoError(t, err) 199 assert.Equal(t, true, update, "Should be able to update justified") 200 lastJustifiedBlk := testutil.NewBeaconBlock() 201 lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32) 202 lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot() 203 require.NoError(t, err) 204 newJustifiedBlk := testutil.NewBeaconBlock() 205 newJustifiedBlk.Block.Slot = 1 206 newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32) 207 newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot() 208 require.NoError(t, err) 209 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(newJustifiedBlk))) 210 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(lastJustifiedBlk))) 211 212 diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot) 213 service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0) 214 service.justifiedCheckpt = ðpb.Checkpoint{Root: lastJustifiedRoot[:]} 215 update, err = service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]}) 216 require.NoError(t, err) 217 assert.Equal(t, true, update, "Should be able to update justified") 218 } 219 220 func TestShouldUpdateJustified_ReturnFalse(t *testing.T) { 221 ctx := context.Background() 222 beaconDB := testDB.SetupDB(t) 223 params.UseMinimalConfig() 224 defer params.UseMainnetConfig() 225 226 cfg := &Config{BeaconDB: beaconDB} 227 service, err := NewService(ctx, cfg) 228 require.NoError(t, err) 229 lastJustifiedBlk := testutil.NewBeaconBlock() 230 lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32) 231 lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot() 232 require.NoError(t, err) 233 newJustifiedBlk := testutil.NewBeaconBlock() 234 newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32) 235 newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot() 236 require.NoError(t, err) 237 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(newJustifiedBlk))) 238 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(lastJustifiedBlk))) 239 240 diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot) 241 service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0) 242 service.justifiedCheckpt = ðpb.Checkpoint{Root: lastJustifiedRoot[:]} 243 244 update, err := service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]}) 245 require.NoError(t, err) 246 assert.Equal(t, false, update, "Should not be able to update justified, received true") 247 } 248 249 func TestCachedPreState_CanGetFromStateSummary(t *testing.T) { 250 ctx := context.Background() 251 beaconDB := testDB.SetupDB(t) 252 253 cfg := &Config{ 254 BeaconDB: beaconDB, 255 StateGen: stategen.New(beaconDB), 256 } 257 service, err := NewService(ctx, cfg) 258 require.NoError(t, err) 259 260 s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]}) 261 require.NoError(t, err) 262 263 genesisStateRoot := [32]byte{} 264 genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) 265 assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) 266 gRoot, err := genesis.Block.HashTreeRoot() 267 require.NoError(t, err) 268 service.finalizedCheckpt = ðpb.Checkpoint{ 269 Root: gRoot[:], 270 } 271 service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{}) 272 service.saveInitSyncBlock(gRoot, wrapper.WrappedPhase0SignedBeaconBlock(genesis)) 273 274 b := testutil.NewBeaconBlock() 275 b.Block.Slot = 1 276 b.Block.ParentRoot = gRoot[:] 277 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]})) 278 require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s)) 279 require.NoError(t, service.verifyBlkPreState(ctx, wrapper.WrappedPhase0BeaconBlock(b.Block))) 280 } 281 282 func TestCachedPreState_CanGetFromDB(t *testing.T) { 283 ctx := context.Background() 284 beaconDB := testDB.SetupDB(t) 285 286 cfg := &Config{ 287 BeaconDB: beaconDB, 288 StateGen: stategen.New(beaconDB), 289 } 290 service, err := NewService(ctx, cfg) 291 require.NoError(t, err) 292 293 genesisStateRoot := [32]byte{} 294 genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) 295 assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) 296 gRoot, err := genesis.Block.HashTreeRoot() 297 require.NoError(t, err) 298 service.finalizedCheckpt = ðpb.Checkpoint{ 299 Root: gRoot[:], 300 } 301 service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{}) 302 service.saveInitSyncBlock(gRoot, wrapper.WrappedPhase0SignedBeaconBlock(genesis)) 303 304 b := testutil.NewBeaconBlock() 305 b.Block.Slot = 1 306 service.finalizedCheckpt = ðpb.Checkpoint{Root: gRoot[:]} 307 err = service.verifyBlkPreState(ctx, wrapper.WrappedPhase0BeaconBlock(b.Block)) 308 wanted := "could not reconstruct parent state" 309 assert.ErrorContains(t, wanted, err) 310 311 b.Block.ParentRoot = gRoot[:] 312 s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 1}) 313 require.NoError(t, err) 314 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]})) 315 require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s)) 316 require.NoError(t, service.verifyBlkPreState(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b).Block())) 317 } 318 319 func TestUpdateJustified_CouldUpdateBest(t *testing.T) { 320 ctx := context.Background() 321 beaconDB := testDB.SetupDB(t) 322 323 cfg := &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)} 324 service, err := NewService(ctx, cfg) 325 require.NoError(t, err) 326 327 signedBlock := testutil.NewBeaconBlock() 328 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(signedBlock))) 329 r, err := signedBlock.Block.HashTreeRoot() 330 require.NoError(t, err) 331 service.justifiedCheckpt = ðpb.Checkpoint{Root: []byte{'A'}} 332 service.bestJustifiedCheckpt = ðpb.Checkpoint{Root: []byte{'A'}} 333 st, err := testutil.NewBeaconState() 334 require.NoError(t, err) 335 require.NoError(t, beaconDB.SaveState(ctx, st.Copy(), r)) 336 337 // Could update 338 s, err := testutil.NewBeaconState() 339 require.NoError(t, err) 340 require.NoError(t, s.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: r[:]})) 341 require.NoError(t, service.updateJustified(context.Background(), s)) 342 343 assert.Equal(t, s.CurrentJustifiedCheckpoint().Epoch, service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service") 344 345 // Could not update 346 service.bestJustifiedCheckpt.Epoch = 2 347 require.NoError(t, service.updateJustified(context.Background(), s)) 348 349 assert.Equal(t, types.Epoch(2), service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service") 350 } 351 352 func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) { 353 ctx := context.Background() 354 beaconDB := testDB.SetupDB(t) 355 356 cfg := &Config{BeaconDB: beaconDB} 357 service, err := NewService(ctx, cfg) 358 require.NoError(t, err) 359 service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'}) 360 service.finalizedCheckpt = ðpb.Checkpoint{Root: make([]byte, 32)} 361 362 genesisStateRoot := [32]byte{} 363 genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) 364 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) 365 validGenesisRoot, err := genesis.Block.HashTreeRoot() 366 require.NoError(t, err) 367 st, err := testutil.NewBeaconState() 368 require.NoError(t, err) 369 370 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot)) 371 roots, err := blockTree1(t, beaconDB, validGenesisRoot[:]) 372 require.NoError(t, err) 373 374 beaconState, _ := testutil.DeterministicGenesisState(t, 32) 375 block := testutil.NewBeaconBlock() 376 block.Block.Slot = 9 377 block.Block.ParentRoot = roots[8] 378 379 err = service.fillInForkChoiceMissingBlocks( 380 context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(block).Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) 381 require.NoError(t, err) 382 383 // 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8 384 assert.Equal(t, 5, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes") 385 assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[4])), "Didn't save node") 386 assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[6])), "Didn't save node") 387 assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[8])), "Didn't save node") 388 } 389 390 func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) { 391 ctx := context.Background() 392 beaconDB := testDB.SetupDB(t) 393 394 cfg := &Config{BeaconDB: beaconDB} 395 service, err := NewService(ctx, cfg) 396 require.NoError(t, err) 397 service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'}) 398 service.finalizedCheckpt = ðpb.Checkpoint{Root: make([]byte, 32)} 399 400 genesisStateRoot := [32]byte{} 401 genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) 402 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) 403 validGenesisRoot, err := genesis.Block.HashTreeRoot() 404 require.NoError(t, err) 405 st, err := testutil.NewBeaconState() 406 require.NoError(t, err) 407 408 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot)) 409 roots, err := blockTree1(t, beaconDB, validGenesisRoot[:]) 410 require.NoError(t, err) 411 412 beaconState, _ := testutil.DeterministicGenesisState(t, 32) 413 block := testutil.NewBeaconBlock() 414 block.Block.Slot = 9 415 block.Block.ParentRoot = roots[8] 416 417 err = service.fillInForkChoiceMissingBlocks( 418 context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(block).Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) 419 require.NoError(t, err) 420 421 // 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8 422 assert.Equal(t, 5, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes") 423 // Ensure all roots and their respective blocks exist. 424 wantedRoots := [][]byte{roots[0], roots[3], roots[4], roots[6], roots[8]} 425 for i, rt := range wantedRoots { 426 assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(rt)), fmt.Sprintf("Didn't save node: %d", i)) 427 assert.Equal(t, true, service.cfg.BeaconDB.HasBlock(context.Background(), bytesutil.ToBytes32(rt))) 428 } 429 } 430 431 func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) { 432 ctx := context.Background() 433 beaconDB := testDB.SetupDB(t) 434 435 cfg := &Config{BeaconDB: beaconDB} 436 service, err := NewService(ctx, cfg) 437 require.NoError(t, err) 438 service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'}) 439 // Set finalized epoch to 1. 440 service.finalizedCheckpt = ðpb.Checkpoint{Epoch: 1} 441 442 genesisStateRoot := [32]byte{} 443 genesis := blocks.NewGenesisBlock(genesisStateRoot[:]) 444 assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis))) 445 validGenesisRoot, err := genesis.Block.HashTreeRoot() 446 assert.NoError(t, err) 447 st, err := testutil.NewBeaconState() 448 require.NoError(t, err) 449 450 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot)) 451 452 // Define a tree branch, slot 63 <- 64 <- 65 453 b63 := testutil.NewBeaconBlock() 454 b63.Block.Slot = 63 455 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b63))) 456 r63, err := b63.Block.HashTreeRoot() 457 require.NoError(t, err) 458 b64 := testutil.NewBeaconBlock() 459 b64.Block.Slot = 64 460 b64.Block.ParentRoot = r63[:] 461 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b64))) 462 r64, err := b64.Block.HashTreeRoot() 463 require.NoError(t, err) 464 b65 := testutil.NewBeaconBlock() 465 b65.Block.Slot = 65 466 b65.Block.ParentRoot = r64[:] 467 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b65))) 468 469 beaconState, _ := testutil.DeterministicGenesisState(t, 32) 470 err = service.fillInForkChoiceMissingBlocks( 471 context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b65).Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) 472 require.NoError(t, err) 473 474 // There should be 2 nodes, block 65 and block 64. 475 assert.Equal(t, 2, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes") 476 477 // Block with slot 63 should be in fork choice because it's less than finalized epoch 1. 478 assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(r63), "Didn't save node") 479 } 480 481 // blockTree1 constructs the following tree: 482 // /- B1 483 // B0 /- B5 - B7 484 // \- B3 - B4 - B6 - B8 485 // (B1, and B3 are all from the same slots) 486 func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byte, error) { 487 genesisRoot = bytesutil.PadTo(genesisRoot, 32) 488 b0 := testutil.NewBeaconBlock() 489 b0.Block.Slot = 0 490 b0.Block.ParentRoot = genesisRoot 491 r0, err := b0.Block.HashTreeRoot() 492 if err != nil { 493 return nil, err 494 } 495 b1 := testutil.NewBeaconBlock() 496 b1.Block.Slot = 1 497 b1.Block.ParentRoot = r0[:] 498 r1, err := b1.Block.HashTreeRoot() 499 if err != nil { 500 return nil, err 501 } 502 b3 := testutil.NewBeaconBlock() 503 b3.Block.Slot = 3 504 b3.Block.ParentRoot = r0[:] 505 r3, err := b3.Block.HashTreeRoot() 506 if err != nil { 507 return nil, err 508 } 509 b4 := testutil.NewBeaconBlock() 510 b4.Block.Slot = 4 511 b4.Block.ParentRoot = r3[:] 512 r4, err := b4.Block.HashTreeRoot() 513 if err != nil { 514 return nil, err 515 } 516 b5 := testutil.NewBeaconBlock() 517 b5.Block.Slot = 5 518 b5.Block.ParentRoot = r4[:] 519 r5, err := b5.Block.HashTreeRoot() 520 if err != nil { 521 return nil, err 522 } 523 b6 := testutil.NewBeaconBlock() 524 b6.Block.Slot = 6 525 b6.Block.ParentRoot = r4[:] 526 r6, err := b6.Block.HashTreeRoot() 527 if err != nil { 528 return nil, err 529 } 530 b7 := testutil.NewBeaconBlock() 531 b7.Block.Slot = 7 532 b7.Block.ParentRoot = r5[:] 533 r7, err := b7.Block.HashTreeRoot() 534 if err != nil { 535 return nil, err 536 } 537 b8 := testutil.NewBeaconBlock() 538 b8.Block.Slot = 8 539 b8.Block.ParentRoot = r6[:] 540 r8, err := b8.Block.HashTreeRoot() 541 if err != nil { 542 return nil, err 543 } 544 st, err := testutil.NewBeaconState() 545 require.NoError(t, err) 546 547 for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} { 548 beaconBlock := testutil.NewBeaconBlock() 549 beaconBlock.Block.Slot = b.Block.Slot 550 beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) 551 if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil { 552 return nil, err 553 } 554 if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil { 555 return nil, errors.Wrap(err, "could not save state") 556 } 557 } 558 if err := beaconDB.SaveState(context.Background(), st.Copy(), r1); err != nil { 559 return nil, err 560 } 561 if err := beaconDB.SaveState(context.Background(), st.Copy(), r7); err != nil { 562 return nil, err 563 } 564 if err := beaconDB.SaveState(context.Background(), st.Copy(), r8); err != nil { 565 return nil, err 566 } 567 return [][]byte{r0[:], r1[:], nil, r3[:], r4[:], r5[:], r6[:], r7[:], r8[:]}, nil 568 } 569 570 func TestCurrentSlot_HandlesOverflow(t *testing.T) { 571 svc := Service{genesisTime: timeutils.Now().Add(1 * time.Hour)} 572 573 slot := svc.CurrentSlot() 574 require.Equal(t, types.Slot(0), slot, "Unexpected slot") 575 } 576 func TestAncestorByDB_CtxErr(t *testing.T) { 577 ctx, cancel := context.WithCancel(context.Background()) 578 service, err := NewService(ctx, &Config{}) 579 require.NoError(t, err) 580 581 cancel() 582 _, err = service.ancestorByDB(ctx, [32]byte{}, 0) 583 require.ErrorContains(t, "context canceled", err) 584 } 585 586 func TestAncestor_HandleSkipSlot(t *testing.T) { 587 ctx := context.Background() 588 beaconDB := testDB.SetupDB(t) 589 590 cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})} 591 service, err := NewService(ctx, cfg) 592 require.NoError(t, err) 593 594 b1 := testutil.NewBeaconBlock() 595 b1.Block.Slot = 1 596 b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32) 597 r1, err := b1.Block.HashTreeRoot() 598 require.NoError(t, err) 599 b100 := testutil.NewBeaconBlock() 600 b100.Block.Slot = 100 601 b100.Block.ParentRoot = r1[:] 602 r100, err := b100.Block.HashTreeRoot() 603 require.NoError(t, err) 604 b200 := testutil.NewBeaconBlock() 605 b200.Block.Slot = 200 606 b200.Block.ParentRoot = r100[:] 607 r200, err := b200.Block.HashTreeRoot() 608 require.NoError(t, err) 609 for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} { 610 beaconBlock := testutil.NewBeaconBlock() 611 beaconBlock.Block.Slot = b.Block.Slot 612 beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) 613 require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock))) 614 } 615 616 // Slots 100 to 200 are skip slots. Requesting root at 150 will yield root at 100. The last physical block. 617 r, err := service.ancestor(context.Background(), r200[:], 150) 618 require.NoError(t, err) 619 if bytesutil.ToBytes32(r) != r100 { 620 t.Error("Did not get correct root") 621 } 622 623 // Slots 1 to 100 are skip slots. Requesting root at 50 will yield root at 1. The last physical block. 624 r, err = service.ancestor(context.Background(), r200[:], 50) 625 require.NoError(t, err) 626 if bytesutil.ToBytes32(r) != r1 { 627 t.Error("Did not get correct root") 628 } 629 } 630 631 func TestAncestor_CanUseForkchoice(t *testing.T) { 632 ctx := context.Background() 633 cfg := &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})} 634 service, err := NewService(ctx, cfg) 635 require.NoError(t, err) 636 637 b1 := testutil.NewBeaconBlock() 638 b1.Block.Slot = 1 639 b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32) 640 r1, err := b1.Block.HashTreeRoot() 641 require.NoError(t, err) 642 b100 := testutil.NewBeaconBlock() 643 b100.Block.Slot = 100 644 b100.Block.ParentRoot = r1[:] 645 r100, err := b100.Block.HashTreeRoot() 646 require.NoError(t, err) 647 b200 := testutil.NewBeaconBlock() 648 b200.Block.Slot = 200 649 b200.Block.ParentRoot = r100[:] 650 r200, err := b200.Block.HashTreeRoot() 651 require.NoError(t, err) 652 for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} { 653 beaconBlock := testutil.NewBeaconBlock() 654 beaconBlock.Block.Slot = b.Block.Slot 655 beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) 656 r, err := b.Block.HashTreeRoot() 657 require.NoError(t, err) 658 require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(context.Background(), b.Block.Slot, r, bytesutil.ToBytes32(b.Block.ParentRoot), [32]byte{}, 0, 0)) // Saves blocks to fork choice store. 659 } 660 661 r, err := service.ancestor(context.Background(), r200[:], 150) 662 require.NoError(t, err) 663 if bytesutil.ToBytes32(r) != r100 { 664 t.Error("Did not get correct root") 665 } 666 } 667 668 func TestAncestor_CanUseDB(t *testing.T) { 669 ctx := context.Background() 670 beaconDB := testDB.SetupDB(t) 671 672 cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})} 673 service, err := NewService(ctx, cfg) 674 require.NoError(t, err) 675 676 b1 := testutil.NewBeaconBlock() 677 b1.Block.Slot = 1 678 b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32) 679 r1, err := b1.Block.HashTreeRoot() 680 require.NoError(t, err) 681 b100 := testutil.NewBeaconBlock() 682 b100.Block.Slot = 100 683 b100.Block.ParentRoot = r1[:] 684 r100, err := b100.Block.HashTreeRoot() 685 require.NoError(t, err) 686 b200 := testutil.NewBeaconBlock() 687 b200.Block.Slot = 200 688 b200.Block.ParentRoot = r100[:] 689 r200, err := b200.Block.HashTreeRoot() 690 require.NoError(t, err) 691 for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} { 692 beaconBlock := testutil.NewBeaconBlock() 693 beaconBlock.Block.Slot = b.Block.Slot 694 beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) 695 require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock))) // Saves blocks to DB. 696 } 697 698 require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(context.Background(), 200, r200, r200, [32]byte{}, 0, 0)) 699 700 r, err := service.ancestor(context.Background(), r200[:], 150) 701 require.NoError(t, err) 702 if bytesutil.ToBytes32(r) != r100 { 703 t.Error("Did not get correct root") 704 } 705 } 706 707 func TestEnsureRootNotZeroHashes(t *testing.T) { 708 ctx := context.Background() 709 cfg := &Config{} 710 service, err := NewService(ctx, cfg) 711 require.NoError(t, err) 712 service.genesisRoot = [32]byte{'a'} 713 714 r := service.ensureRootNotZeros(params.BeaconConfig().ZeroHash) 715 assert.Equal(t, service.genesisRoot, r, "Did not get wanted justified root") 716 root := [32]byte{'b'} 717 r = service.ensureRootNotZeros(root) 718 assert.Equal(t, root, r, "Did not get wanted justified root") 719 } 720 721 func TestFinalizedImpliesNewJustified(t *testing.T) { 722 beaconDB := testDB.SetupDB(t) 723 ctx := context.Background() 724 type args struct { 725 cachedCheckPoint *ethpb.Checkpoint 726 stateCheckPoint *ethpb.Checkpoint 727 diffFinalizedCheckPoint bool 728 } 729 tests := []struct { 730 name string 731 args args 732 want *ethpb.Checkpoint 733 }{ 734 { 735 name: "Same justified, do nothing", 736 args: args{ 737 cachedCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}, 738 stateCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}, 739 }, 740 want: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}, 741 }, 742 { 743 name: "Different justified, higher epoch, cache new justified", 744 args: args{ 745 cachedCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}, 746 stateCheckPoint: ðpb.Checkpoint{Epoch: 2, Root: []byte{'b'}}, 747 }, 748 want: ðpb.Checkpoint{Epoch: 2, Root: []byte{'b'}}, 749 }, 750 { 751 name: "finalized has different justified, cache new justified", 752 args: args{ 753 cachedCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}, 754 stateCheckPoint: ðpb.Checkpoint{Epoch: 1, Root: []byte{'b'}}, 755 diffFinalizedCheckPoint: true, 756 }, 757 want: ðpb.Checkpoint{Epoch: 1, Root: []byte{'b'}}, 758 }, 759 } 760 for _, test := range tests { 761 beaconState, err := testutil.NewBeaconState() 762 require.NoError(t, err) 763 require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(test.args.stateCheckPoint)) 764 service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}) 765 require.NoError(t, err) 766 service.justifiedCheckpt = test.args.cachedCheckPoint 767 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)})) 768 genesisState, err := testutil.NewBeaconState() 769 require.NoError(t, err) 770 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root))) 771 772 if test.args.diffFinalizedCheckPoint { 773 b1 := testutil.NewBeaconBlock() 774 b1.Block.Slot = 1 775 b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32) 776 r1, err := b1.Block.HashTreeRoot() 777 require.NoError(t, err) 778 b100 := testutil.NewBeaconBlock() 779 b100.Block.Slot = 100 780 b100.Block.ParentRoot = r1[:] 781 r100, err := b100.Block.HashTreeRoot() 782 require.NoError(t, err) 783 for _, b := range []*ethpb.SignedBeaconBlock{b1, b100} { 784 beaconBlock := testutil.NewBeaconBlock() 785 beaconBlock.Block.Slot = b.Block.Slot 786 beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32) 787 require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock))) 788 } 789 service.finalizedCheckpt = ðpb.Checkpoint{Root: []byte{'c'}, Epoch: 1} 790 service.justifiedCheckpt.Root = r100[:] 791 } 792 793 require.NoError(t, service.finalizedImpliesNewJustified(ctx, beaconState)) 794 assert.Equal(t, true, attestationutil.CheckPointIsEqual(test.want, service.justifiedCheckpt), "Did not get wanted check point") 795 } 796 } 797 798 func TestVerifyBlkDescendant(t *testing.T) { 799 beaconDB := testDB.SetupDB(t) 800 ctx := context.Background() 801 802 b := testutil.NewBeaconBlock() 803 b.Block.Slot = 1 804 r, err := b.Block.HashTreeRoot() 805 require.NoError(t, err) 806 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) 807 808 b1 := testutil.NewBeaconBlock() 809 b1.Block.Slot = 1 810 b1.Block.Body.Graffiti = bytesutil.PadTo([]byte{'a'}, 32) 811 r1, err := b1.Block.HashTreeRoot() 812 require.NoError(t, err) 813 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) 814 815 type args struct { 816 parentRoot [32]byte 817 finalizedRoot [32]byte 818 } 819 tests := []struct { 820 name string 821 args args 822 wantedErr string 823 }{ 824 { 825 name: "could not get finalized block in block service cache", 826 args: args{ 827 finalizedRoot: [32]byte{'a'}, 828 }, 829 wantedErr: "nil finalized block", 830 }, 831 { 832 name: "could not get finalized block root in DB", 833 args: args{ 834 finalizedRoot: r, 835 parentRoot: [32]byte{'a'}, 836 }, 837 wantedErr: "could not get finalized block root", 838 }, 839 { 840 name: "is not descendant", 841 args: args{ 842 finalizedRoot: r1, 843 parentRoot: r, 844 }, 845 wantedErr: "is not a descendent of the current finalized block slot", 846 }, 847 { 848 name: "is descendant", 849 args: args{ 850 finalizedRoot: r, 851 parentRoot: r, 852 }, 853 }, 854 } 855 for _, tt := range tests { 856 service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}) 857 require.NoError(t, err) 858 service.finalizedCheckpt = ðpb.Checkpoint{ 859 Root: tt.args.finalizedRoot[:], 860 } 861 err = service.VerifyBlkDescendant(ctx, tt.args.parentRoot) 862 if tt.wantedErr != "" { 863 assert.ErrorContains(t, tt.wantedErr, err) 864 } else if err != nil { 865 assert.NoError(t, err) 866 } 867 } 868 } 869 870 func TestUpdateJustifiedInitSync(t *testing.T) { 871 beaconDB := testDB.SetupDB(t) 872 ctx := context.Background() 873 cfg := &Config{BeaconDB: beaconDB} 874 service, err := NewService(ctx, cfg) 875 require.NoError(t, err) 876 877 gBlk := testutil.NewBeaconBlock() 878 gRoot, err := gBlk.Block.HashTreeRoot() 879 require.NoError(t, err) 880 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk))) 881 require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, gRoot)) 882 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: gRoot[:]})) 883 beaconState, _ := testutil.DeterministicGenesisState(t, 32) 884 require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, beaconState, gRoot)) 885 service.genesisRoot = gRoot 886 currentCp := ðpb.Checkpoint{Epoch: 1} 887 service.justifiedCheckpt = currentCp 888 newCp := ðpb.Checkpoint{Epoch: 2, Root: gRoot[:]} 889 890 require.NoError(t, service.updateJustifiedInitSync(ctx, newCp)) 891 892 assert.DeepSSZEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint") 893 assert.DeepSSZEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache") 894 cp, err := service.cfg.BeaconDB.JustifiedCheckpoint(ctx) 895 require.NoError(t, err) 896 assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in db") 897 } 898 899 func TestHandleEpochBoundary_BadMetrics(t *testing.T) { 900 ctx := context.Background() 901 cfg := &Config{} 902 service, err := NewService(ctx, cfg) 903 require.NoError(t, err) 904 905 s, err := testutil.NewBeaconState() 906 require.NoError(t, err) 907 require.NoError(t, s.SetSlot(1)) 908 service.head = &head{state: (*v1.BeaconState)(nil)} 909 910 require.ErrorContains(t, "failed to initialize precompute: nil inner state", service.handleEpochBoundary(ctx, s)) 911 } 912 913 func TestHandleEpochBoundary_UpdateFirstSlot(t *testing.T) { 914 ctx := context.Background() 915 cfg := &Config{} 916 service, err := NewService(ctx, cfg) 917 require.NoError(t, err) 918 919 s, _ := testutil.DeterministicGenesisState(t, 1024) 920 service.head = &head{state: s} 921 require.NoError(t, s.SetSlot(2*params.BeaconConfig().SlotsPerEpoch)) 922 require.NoError(t, service.handleEpochBoundary(ctx, s)) 923 require.Equal(t, 3*params.BeaconConfig().SlotsPerEpoch, service.nextEpochBoundarySlot) 924 } 925 926 func TestOnBlock_CanFinalize(t *testing.T) { 927 ctx := context.Background() 928 beaconDB := testDB.SetupDB(t) 929 depositCache, err := depositcache.New() 930 require.NoError(t, err) 931 cfg := &Config{ 932 BeaconDB: beaconDB, 933 StateGen: stategen.New(beaconDB), 934 ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), 935 DepositCache: depositCache, 936 StateNotifier: &mock.MockStateNotifier{}, 937 } 938 service, err := NewService(ctx, cfg) 939 require.NoError(t, err) 940 941 gs, keys := testutil.DeterministicGenesisState(t, 32) 942 require.NoError(t, service.saveGenesisData(ctx, gs)) 943 gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx) 944 require.NoError(t, err) 945 gRoot, err := gBlk.Block().HashTreeRoot() 946 require.NoError(t, err) 947 service.finalizedCheckpt = ðpb.Checkpoint{Root: gRoot[:]} 948 949 testState := gs.Copy() 950 for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ { 951 blk, err := testutil.GenerateFullBlock(testState, keys, testutil.DefaultBlockGenConfig(), i) 952 require.NoError(t, err) 953 r, err := blk.Block.HashTreeRoot() 954 require.NoError(t, err) 955 require.NoError(t, service.onBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(blk), r)) 956 testState, err = service.cfg.StateGen.StateByRoot(ctx, r) 957 require.NoError(t, err) 958 } 959 require.Equal(t, types.Epoch(3), service.CurrentJustifiedCheckpt().Epoch) 960 require.Equal(t, types.Epoch(2), service.FinalizedCheckpt().Epoch) 961 } 962 963 func TestInsertFinalizedDeposits(t *testing.T) { 964 ctx := context.Background() 965 beaconDB := testDB.SetupDB(t) 966 depositCache, err := depositcache.New() 967 require.NoError(t, err) 968 cfg := &Config{ 969 BeaconDB: beaconDB, 970 StateGen: stategen.New(beaconDB), 971 ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), 972 DepositCache: depositCache, 973 } 974 service, err := NewService(ctx, cfg) 975 require.NoError(t, err) 976 977 gs, _ := testutil.DeterministicGenesisState(t, 32) 978 require.NoError(t, service.saveGenesisData(ctx, gs)) 979 gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx) 980 require.NoError(t, err) 981 gRoot, err := gBlk.Block().HashTreeRoot() 982 require.NoError(t, err) 983 service.finalizedCheckpt = ðpb.Checkpoint{Root: gRoot[:]} 984 gs = gs.Copy() 985 assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10})) 986 assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs)) 987 zeroSig := [96]byte{} 988 for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ { 989 root := []byte(strconv.Itoa(int(i))) 990 assert.NoError(t, depositCache.InsertDeposit(ctx, ðpb.Deposit{Data: ðpb.Deposit_Data{ 991 PublicKey: bytesutil.FromBytes48([48]byte{}), 992 WithdrawalCredentials: params.BeaconConfig().ZeroHash[:], 993 Amount: 0, 994 Signature: zeroSig[:], 995 }, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root))) 996 } 997 assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'})) 998 fDeposits := depositCache.FinalizedDeposits(ctx) 999 assert.Equal(t, 9, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly") 1000 deps := depositCache.AllDeposits(ctx, big.NewInt(109)) 1001 for _, d := range deps { 1002 assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty") 1003 } 1004 } 1005 1006 func TestRemoveBlockAttestationsInPool_Canonical(t *testing.T) { 1007 resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{ 1008 CorrectlyPruneCanonicalAtts: true, 1009 }) 1010 defer resetCfg() 1011 1012 genesis, keys := testutil.DeterministicGenesisState(t, 64) 1013 b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1) 1014 assert.NoError(t, err) 1015 r, err := b.Block.HashTreeRoot() 1016 require.NoError(t, err) 1017 1018 ctx := context.Background() 1019 beaconDB := testDB.SetupDB(t) 1020 service := setupBeaconChain(t, beaconDB) 1021 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: r[:]})) 1022 require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, r)) 1023 1024 atts := b.Block.Body.Attestations 1025 require.NoError(t, service.cfg.AttPool.SaveAggregatedAttestations(atts)) 1026 require.NoError(t, service.pruneCanonicalAttsFromPool(ctx, r, wrapper.WrappedPhase0SignedBeaconBlock(b))) 1027 require.Equal(t, 0, service.cfg.AttPool.AggregatedAttestationCount()) 1028 } 1029 1030 func TestRemoveBlockAttestationsInPool_NonCanonical(t *testing.T) { 1031 resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{ 1032 CorrectlyPruneCanonicalAtts: true, 1033 }) 1034 defer resetCfg() 1035 1036 genesis, keys := testutil.DeterministicGenesisState(t, 64) 1037 b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1) 1038 assert.NoError(t, err) 1039 r, err := b.Block.HashTreeRoot() 1040 require.NoError(t, err) 1041 1042 ctx := context.Background() 1043 beaconDB := testDB.SetupDB(t) 1044 service := setupBeaconChain(t, beaconDB) 1045 1046 atts := b.Block.Body.Attestations 1047 require.NoError(t, service.cfg.AttPool.SaveAggregatedAttestations(atts)) 1048 require.NoError(t, service.pruneCanonicalAttsFromPool(ctx, r, wrapper.WrappedPhase0SignedBeaconBlock(b))) 1049 require.Equal(t, 1, service.cfg.AttPool.AggregatedAttestationCount()) 1050 }