github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/blockchain/chain_info_test.go (about) 1 package blockchain 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 types "github.com/prysmaticlabs/eth2-types" 9 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 10 testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 11 "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray" 12 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" 13 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 14 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 15 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 16 "github.com/prysmaticlabs/prysm/shared/bytesutil" 17 "github.com/prysmaticlabs/prysm/shared/params" 18 "github.com/prysmaticlabs/prysm/shared/testutil" 19 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 20 "github.com/prysmaticlabs/prysm/shared/testutil/require" 21 "google.golang.org/protobuf/proto" 22 ) 23 24 // Ensure Service implements chain info interface. 25 var _ ChainInfoFetcher = (*Service)(nil) 26 var _ TimeFetcher = (*Service)(nil) 27 var _ ForkFetcher = (*Service)(nil) 28 29 func TestFinalizedCheckpt_Nil(t *testing.T) { 30 beaconDB := testDB.SetupDB(t) 31 c := setupBeaconChain(t, beaconDB) 32 assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], c.FinalizedCheckpt().Root, "Incorrect pre chain start value") 33 } 34 35 func TestHeadRoot_Nil(t *testing.T) { 36 beaconDB := testDB.SetupDB(t) 37 c := setupBeaconChain(t, beaconDB) 38 headRoot, err := c.HeadRoot(context.Background()) 39 require.NoError(t, err) 40 assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], headRoot, "Incorrect pre chain start value") 41 } 42 43 func TestFinalizedCheckpt_CanRetrieve(t *testing.T) { 44 beaconDB := testDB.SetupDB(t) 45 46 cp := ðpb.Checkpoint{Epoch: 5, Root: bytesutil.PadTo([]byte("foo"), 32)} 47 c := setupBeaconChain(t, beaconDB) 48 c.finalizedCheckpt = cp 49 50 assert.Equal(t, cp.Epoch, c.FinalizedCheckpt().Epoch, "Unexpected finalized epoch") 51 } 52 53 func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) { 54 beaconDB := testDB.SetupDB(t) 55 56 genesisRoot := [32]byte{'A'} 57 cp := ðpb.Checkpoint{Root: genesisRoot[:]} 58 c := setupBeaconChain(t, beaconDB) 59 c.finalizedCheckpt = cp 60 c.genesisRoot = genesisRoot 61 assert.DeepEqual(t, c.genesisRoot[:], c.FinalizedCheckpt().Root) 62 } 63 64 func TestCurrentJustifiedCheckpt_CanRetrieve(t *testing.T) { 65 beaconDB := testDB.SetupDB(t) 66 67 c := setupBeaconChain(t, beaconDB) 68 assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch") 69 cp := ðpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)} 70 c.justifiedCheckpt = cp 71 assert.Equal(t, cp.Epoch, c.CurrentJustifiedCheckpt().Epoch, "Unexpected justified epoch") 72 } 73 74 func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) { 75 beaconDB := testDB.SetupDB(t) 76 77 c := setupBeaconChain(t, beaconDB) 78 genesisRoot := [32]byte{'B'} 79 cp := ðpb.Checkpoint{Root: genesisRoot[:]} 80 c.justifiedCheckpt = cp 81 c.genesisRoot = genesisRoot 82 assert.DeepEqual(t, c.genesisRoot[:], c.CurrentJustifiedCheckpt().Root) 83 } 84 85 func TestPreviousJustifiedCheckpt_CanRetrieve(t *testing.T) { 86 beaconDB := testDB.SetupDB(t) 87 88 cp := ðpb.Checkpoint{Epoch: 7, Root: bytesutil.PadTo([]byte("foo"), 32)} 89 c := setupBeaconChain(t, beaconDB) 90 assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch") 91 c.prevJustifiedCheckpt = cp 92 assert.Equal(t, cp.Epoch, c.PreviousJustifiedCheckpt().Epoch, "Unexpected previous justified epoch") 93 } 94 95 func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) { 96 beaconDB := testDB.SetupDB(t) 97 98 genesisRoot := [32]byte{'C'} 99 cp := ðpb.Checkpoint{Root: genesisRoot[:]} 100 c := setupBeaconChain(t, beaconDB) 101 c.prevJustifiedCheckpt = cp 102 c.genesisRoot = genesisRoot 103 assert.DeepEqual(t, c.genesisRoot[:], c.PreviousJustifiedCheckpt().Root) 104 } 105 106 func TestHeadSlot_CanRetrieve(t *testing.T) { 107 c := &Service{} 108 s, err := v1.InitializeFromProto(&pb.BeaconState{}) 109 require.NoError(t, err) 110 c.head = &head{slot: 100, state: s} 111 assert.Equal(t, types.Slot(100), c.HeadSlot()) 112 } 113 114 func TestHeadRoot_CanRetrieve(t *testing.T) { 115 c := &Service{} 116 c.head = &head{root: [32]byte{'A'}} 117 r, err := c.HeadRoot(context.Background()) 118 require.NoError(t, err) 119 assert.Equal(t, [32]byte{'A'}, bytesutil.ToBytes32(r)) 120 } 121 122 func TestHeadRoot_UseDB(t *testing.T) { 123 beaconDB := testDB.SetupDB(t) 124 c := &Service{cfg: &Config{BeaconDB: beaconDB}} 125 c.head = &head{root: params.BeaconConfig().ZeroHash} 126 b := testutil.NewBeaconBlock() 127 br, err := b.Block.HashTreeRoot() 128 require.NoError(t, err) 129 require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b))) 130 require.NoError(t, beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: br[:]})) 131 require.NoError(t, beaconDB.SaveHeadBlockRoot(context.Background(), br)) 132 r, err := c.HeadRoot(context.Background()) 133 require.NoError(t, err) 134 assert.Equal(t, br, bytesutil.ToBytes32(r)) 135 } 136 137 func TestHeadBlock_CanRetrieve(t *testing.T) { 138 b := testutil.NewBeaconBlock() 139 b.Block.Slot = 1 140 s, err := v1.InitializeFromProto(&pb.BeaconState{}) 141 require.NoError(t, err) 142 c := &Service{} 143 c.head = &head{block: wrapper.WrappedPhase0SignedBeaconBlock(b), state: s} 144 145 recevied, err := c.HeadBlock(context.Background()) 146 require.NoError(t, err) 147 assert.DeepEqual(t, b, recevied.Proto(), "Incorrect head block received") 148 } 149 150 func TestHeadState_CanRetrieve(t *testing.T) { 151 s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 2, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]}) 152 require.NoError(t, err) 153 c := &Service{} 154 c.head = &head{state: s} 155 headState, err := c.HeadState(context.Background()) 156 require.NoError(t, err) 157 assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Incorrect head state received") 158 } 159 160 func TestGenesisTime_CanRetrieve(t *testing.T) { 161 c := &Service{genesisTime: time.Unix(999, 0)} 162 wanted := time.Unix(999, 0) 163 assert.Equal(t, wanted, c.GenesisTime(), "Did not get wanted genesis time") 164 } 165 166 func TestCurrentFork_CanRetrieve(t *testing.T) { 167 f := &pb.Fork{Epoch: 999} 168 s, err := v1.InitializeFromProto(&pb.BeaconState{Fork: f}) 169 require.NoError(t, err) 170 c := &Service{} 171 c.head = &head{state: s} 172 if !proto.Equal(c.CurrentFork(), f) { 173 t.Error("Received incorrect fork version") 174 } 175 } 176 177 func TestCurrentFork_NilHeadSTate(t *testing.T) { 178 f := &pb.Fork{ 179 PreviousVersion: params.BeaconConfig().GenesisForkVersion, 180 CurrentVersion: params.BeaconConfig().GenesisForkVersion, 181 } 182 c := &Service{} 183 if !proto.Equal(c.CurrentFork(), f) { 184 t.Error("Received incorrect fork version") 185 } 186 } 187 188 func TestGenesisValidatorRoot_CanRetrieve(t *testing.T) { 189 // Should not panic if head state is nil. 190 c := &Service{} 191 assert.Equal(t, [32]byte{}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root") 192 193 s, err := v1.InitializeFromProto(&pb.BeaconState{GenesisValidatorsRoot: []byte{'a'}}) 194 require.NoError(t, err) 195 c.head = &head{state: s} 196 assert.Equal(t, [32]byte{'a'}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root") 197 } 198 199 func TestHeadETH1Data_Nil(t *testing.T) { 200 beaconDB := testDB.SetupDB(t) 201 c := setupBeaconChain(t, beaconDB) 202 assert.DeepEqual(t, ðpb.Eth1Data{}, c.HeadETH1Data(), "Incorrect pre chain start value") 203 } 204 205 func TestHeadETH1Data_CanRetrieve(t *testing.T) { 206 d := ðpb.Eth1Data{DepositCount: 999} 207 s, err := v1.InitializeFromProto(&pb.BeaconState{Eth1Data: d}) 208 require.NoError(t, err) 209 c := &Service{} 210 c.head = &head{state: s} 211 if !proto.Equal(c.HeadETH1Data(), d) { 212 t.Error("Received incorrect eth1 data") 213 } 214 } 215 216 func TestIsCanonical_Ok(t *testing.T) { 217 ctx := context.Background() 218 beaconDB := testDB.SetupDB(t) 219 c := setupBeaconChain(t, beaconDB) 220 221 blk := testutil.NewBeaconBlock() 222 blk.Block.Slot = 0 223 root, err := blk.Block.HashTreeRoot() 224 require.NoError(t, err) 225 require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(blk))) 226 require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, root)) 227 can, err := c.IsCanonical(ctx, root) 228 require.NoError(t, err) 229 assert.Equal(t, true, can) 230 231 can, err = c.IsCanonical(ctx, [32]byte{'a'}) 232 require.NoError(t, err) 233 assert.Equal(t, false, can) 234 } 235 236 func TestService_HeadValidatorsIndices(t *testing.T) { 237 s, _ := testutil.DeterministicGenesisState(t, 10) 238 c := &Service{} 239 240 c.head = &head{} 241 indices, err := c.HeadValidatorsIndices(context.Background(), 0) 242 require.NoError(t, err) 243 require.Equal(t, 0, len(indices)) 244 245 c.head = &head{state: s} 246 indices, err = c.HeadValidatorsIndices(context.Background(), 0) 247 require.NoError(t, err) 248 require.Equal(t, 10, len(indices)) 249 } 250 251 func TestService_HeadSeed(t *testing.T) { 252 s, _ := testutil.DeterministicGenesisState(t, 1) 253 c := &Service{} 254 seed, err := helpers.Seed(s, 0, params.BeaconConfig().DomainBeaconAttester) 255 require.NoError(t, err) 256 257 c.head = &head{} 258 root, err := c.HeadSeed(context.Background(), 0) 259 require.NoError(t, err) 260 require.Equal(t, [32]byte{}, root) 261 262 c.head = &head{state: s} 263 root, err = c.HeadSeed(context.Background(), 0) 264 require.NoError(t, err) 265 require.DeepEqual(t, seed, root) 266 } 267 268 func TestService_HeadGenesisValidatorRoot(t *testing.T) { 269 s, _ := testutil.DeterministicGenesisState(t, 1) 270 c := &Service{} 271 272 c.head = &head{} 273 root := c.HeadGenesisValidatorRoot() 274 require.Equal(t, [32]byte{}, root) 275 276 c.head = &head{state: s} 277 root = c.HeadGenesisValidatorRoot() 278 require.DeepEqual(t, root[:], s.GenesisValidatorRoot()) 279 } 280 281 func TestService_ProtoArrayStore(t *testing.T) { 282 c := &Service{cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}} 283 p := c.ProtoArrayStore() 284 require.Equal(t, 0, int(p.FinalizedEpoch())) 285 } 286 287 func TestService_ChainHeads(t *testing.T) { 288 ctx := context.Background() 289 c := &Service{cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}} 290 require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 100, [32]byte{'a'}, [32]byte{}, [32]byte{}, 0, 0)) 291 require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{}, 0, 0)) 292 require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{}, 0, 0)) 293 require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 103, [32]byte{'d'}, [32]byte{}, [32]byte{}, 0, 0)) 294 require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 104, [32]byte{'e'}, [32]byte{'b'}, [32]byte{}, 0, 0)) 295 296 roots, slots := c.ChainHeads() 297 require.DeepEqual(t, [][32]byte{{'c'}, {'d'}, {'e'}}, roots) 298 require.DeepEqual(t, []types.Slot{102, 103, 104}, slots) 299 }