github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/blockchain/head_test.go (about) 1 package blockchain 2 3 import ( 4 "bytes" 5 "context" 6 "testing" 7 "time" 8 9 types "github.com/prysmaticlabs/eth2-types" 10 mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 11 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 12 testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 13 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 14 ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1" 15 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 16 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 17 "github.com/prysmaticlabs/prysm/shared/featureconfig" 18 "github.com/prysmaticlabs/prysm/shared/params" 19 "github.com/prysmaticlabs/prysm/shared/testutil" 20 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 21 "github.com/prysmaticlabs/prysm/shared/testutil/require" 22 logTest "github.com/sirupsen/logrus/hooks/test" 23 ) 24 25 func TestSaveHead_Same(t *testing.T) { 26 beaconDB := testDB.SetupDB(t) 27 service := setupBeaconChain(t, beaconDB) 28 29 r := [32]byte{'A'} 30 service.head = &head{slot: 0, root: r} 31 32 require.NoError(t, service.saveHead(context.Background(), r)) 33 assert.Equal(t, types.Slot(0), service.headSlot(), "Head did not stay the same") 34 assert.Equal(t, r, service.headRoot(), "Head did not stay the same") 35 } 36 37 func TestSaveHead_Different(t *testing.T) { 38 ctx := context.Background() 39 beaconDB := testDB.SetupDB(t) 40 service := setupBeaconChain(t, beaconDB) 41 42 testutil.NewBeaconBlock() 43 oldBlock := wrapper.WrappedPhase0SignedBeaconBlock( 44 testutil.NewBeaconBlock(), 45 ) 46 require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), oldBlock)) 47 oldRoot, err := oldBlock.Block().HashTreeRoot() 48 require.NoError(t, err) 49 service.head = &head{ 50 slot: 0, 51 root: oldRoot, 52 block: oldBlock, 53 } 54 55 newHeadSignedBlock := testutil.NewBeaconBlock() 56 newHeadSignedBlock.Block.Slot = 1 57 newHeadBlock := newHeadSignedBlock.Block 58 59 require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(newHeadSignedBlock))) 60 newRoot, err := newHeadBlock.HashTreeRoot() 61 require.NoError(t, err) 62 headState, err := testutil.NewBeaconState() 63 require.NoError(t, err) 64 require.NoError(t, headState.SetSlot(1)) 65 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]})) 66 require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot)) 67 require.NoError(t, service.saveHead(context.Background(), newRoot)) 68 69 assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change") 70 71 cachedRoot, err := service.HeadRoot(context.Background()) 72 require.NoError(t, err) 73 assert.DeepEqual(t, cachedRoot, newRoot[:], "Head did not change") 74 assert.DeepEqual(t, newHeadSignedBlock, service.headBlock().Proto(), "Head did not change") 75 assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change") 76 } 77 78 func TestSaveHead_Different_Reorg(t *testing.T) { 79 ctx := context.Background() 80 hook := logTest.NewGlobal() 81 beaconDB := testDB.SetupDB(t) 82 service := setupBeaconChain(t, beaconDB) 83 84 oldBlock := wrapper.WrappedPhase0SignedBeaconBlock( 85 testutil.NewBeaconBlock(), 86 ) 87 require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), oldBlock)) 88 oldRoot, err := oldBlock.Block().HashTreeRoot() 89 require.NoError(t, err) 90 service.head = &head{ 91 slot: 0, 92 root: oldRoot, 93 block: oldBlock, 94 } 95 96 reorgChainParent := [32]byte{'B'} 97 newHeadSignedBlock := testutil.NewBeaconBlock() 98 newHeadSignedBlock.Block.Slot = 1 99 newHeadSignedBlock.Block.ParentRoot = reorgChainParent[:] 100 newHeadBlock := newHeadSignedBlock.Block 101 102 require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(newHeadSignedBlock))) 103 newRoot, err := newHeadBlock.HashTreeRoot() 104 require.NoError(t, err) 105 headState, err := testutil.NewBeaconState() 106 require.NoError(t, err) 107 require.NoError(t, headState.SetSlot(1)) 108 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]})) 109 require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot)) 110 require.NoError(t, service.saveHead(context.Background(), newRoot)) 111 112 assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change") 113 114 cachedRoot, err := service.HeadRoot(context.Background()) 115 require.NoError(t, err) 116 if !bytes.Equal(cachedRoot, newRoot[:]) { 117 t.Error("Head did not change") 118 } 119 assert.DeepEqual(t, newHeadSignedBlock, service.headBlock().Proto(), "Head did not change") 120 assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change") 121 require.LogsContain(t, hook, "Chain reorg occurred") 122 } 123 124 func TestCacheJustifiedStateBalances_CanCache(t *testing.T) { 125 beaconDB := testDB.SetupDB(t) 126 service := setupBeaconChain(t, beaconDB) 127 128 state, _ := testutil.DeterministicGenesisState(t, 100) 129 r := [32]byte{'a'} 130 require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: r[:]})) 131 require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), state, r)) 132 require.NoError(t, service.cacheJustifiedStateBalances(context.Background(), r)) 133 require.DeepEqual(t, service.getJustifiedBalances(), state.Balances(), "Incorrect justified balances") 134 } 135 136 func TestUpdateHead_MissingJustifiedRoot(t *testing.T) { 137 beaconDB := testDB.SetupDB(t) 138 service := setupBeaconChain(t, beaconDB) 139 140 b := testutil.NewBeaconBlock() 141 require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b))) 142 r, err := b.Block.HashTreeRoot() 143 require.NoError(t, err) 144 145 service.justifiedCheckpt = ðpb.Checkpoint{Root: r[:]} 146 service.finalizedCheckpt = ðpb.Checkpoint{} 147 service.bestJustifiedCheckpt = ðpb.Checkpoint{} 148 149 require.NoError(t, service.updateHead(context.Background(), []uint64{})) 150 } 151 152 func Test_notifyNewHeadEvent(t *testing.T) { 153 t.Run("genesis_state_root", func(t *testing.T) { 154 bState, _ := testutil.DeterministicGenesisState(t, 10) 155 notifier := &mock.MockStateNotifier{RecordEvents: true} 156 srv := &Service{ 157 cfg: &Config{ 158 StateNotifier: notifier, 159 }, 160 genesisRoot: [32]byte{1}, 161 } 162 newHeadStateRoot := [32]byte{2} 163 newHeadRoot := [32]byte{3} 164 err := srv.notifyNewHeadEvent(1, bState, newHeadStateRoot[:], newHeadRoot[:]) 165 require.NoError(t, err) 166 events := notifier.ReceivedEvents() 167 require.Equal(t, 1, len(events)) 168 169 eventHead, ok := events[0].Data.(*ethpbv1.EventHead) 170 require.Equal(t, true, ok) 171 wanted := ðpbv1.EventHead{ 172 Slot: 1, 173 Block: newHeadRoot[:], 174 State: newHeadStateRoot[:], 175 EpochTransition: false, 176 PreviousDutyDependentRoot: srv.genesisRoot[:], 177 CurrentDutyDependentRoot: srv.genesisRoot[:], 178 } 179 require.DeepSSZEqual(t, wanted, eventHead) 180 }) 181 t.Run("non_genesis_values", func(t *testing.T) { 182 bState, _ := testutil.DeterministicGenesisState(t, 10) 183 notifier := &mock.MockStateNotifier{RecordEvents: true} 184 genesisRoot := [32]byte{1} 185 srv := &Service{ 186 cfg: &Config{ 187 StateNotifier: notifier, 188 }, 189 genesisRoot: genesisRoot, 190 } 191 epoch1Start, err := helpers.StartSlot(1) 192 require.NoError(t, err) 193 epoch2Start, err := helpers.StartSlot(1) 194 require.NoError(t, err) 195 require.NoError(t, bState.SetSlot(epoch1Start)) 196 197 newHeadStateRoot := [32]byte{2} 198 newHeadRoot := [32]byte{3} 199 err = srv.notifyNewHeadEvent(epoch2Start, bState, newHeadStateRoot[:], newHeadRoot[:]) 200 require.NoError(t, err) 201 events := notifier.ReceivedEvents() 202 require.Equal(t, 1, len(events)) 203 204 eventHead, ok := events[0].Data.(*ethpbv1.EventHead) 205 require.Equal(t, true, ok) 206 wanted := ðpbv1.EventHead{ 207 Slot: epoch2Start, 208 Block: newHeadRoot[:], 209 State: newHeadStateRoot[:], 210 EpochTransition: false, 211 PreviousDutyDependentRoot: genesisRoot[:], 212 CurrentDutyDependentRoot: make([]byte, 32), 213 } 214 require.DeepSSZEqual(t, wanted, eventHead) 215 }) 216 } 217 218 func TestSaveOrphanedAtts(t *testing.T) { 219 resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{ 220 CorrectlyInsertOrphanedAtts: true, 221 }) 222 defer resetCfg() 223 224 genesis, keys := testutil.DeterministicGenesisState(t, 64) 225 b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1) 226 assert.NoError(t, err) 227 r, err := b.Block.HashTreeRoot() 228 require.NoError(t, err) 229 230 ctx := context.Background() 231 beaconDB := testDB.SetupDB(t) 232 service := setupBeaconChain(t, beaconDB) 233 service.genesisTime = time.Now() 234 235 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) 236 require.NoError(t, service.saveOrphanedAtts(ctx, r)) 237 238 require.Equal(t, len(b.Block.Body.Attestations), service.cfg.AttPool.AggregatedAttestationCount()) 239 savedAtts := service.cfg.AttPool.AggregatedAttestations() 240 atts := b.Block.Body.Attestations 241 require.DeepSSZEqual(t, atts, savedAtts) 242 } 243 244 func TestSaveOrphanedAtts_CanFilter(t *testing.T) { 245 resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{ 246 CorrectlyInsertOrphanedAtts: true, 247 }) 248 defer resetCfg() 249 250 genesis, keys := testutil.DeterministicGenesisState(t, 64) 251 b, err := testutil.GenerateFullBlock(genesis, keys, testutil.DefaultBlockGenConfig(), 1) 252 assert.NoError(t, err) 253 r, err := b.Block.HashTreeRoot() 254 require.NoError(t, err) 255 256 ctx := context.Background() 257 beaconDB := testDB.SetupDB(t) 258 service := setupBeaconChain(t, beaconDB) 259 service.genesisTime = time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SlotsPerEpoch+1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second) 260 261 require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b))) 262 require.NoError(t, service.saveOrphanedAtts(ctx, r)) 263 264 require.Equal(t, 0, service.cfg.AttPool.AggregatedAttestationCount()) 265 savedAtts := service.cfg.AttPool.AggregatedAttestations() 266 atts := b.Block.Body.Attestations 267 require.DeepNotSSZEqual(t, atts, savedAtts) 268 }