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 := &ethpb.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 := &ethpb.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 := &ethpb.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 := &ethpb.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 := &ethpb.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 := &ethpb.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, &ethpb.Eth1Data{}, c.HeadETH1Data(), "Incorrect pre chain start value")
   203  }
   204  
   205  func TestHeadETH1Data_CanRetrieve(t *testing.T) {
   206  	d := &ethpb.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  }