Handle missing archived index (#5899)

* Make `archivedRoot` handle missing root case
* Regression tests
* Fixed existing tests
* Removed debug log
* Merge refs/heads/master into handle-missing-archived-index
* Merge refs/heads/master into handle-missing-archived-index
* More comments on the look back
* Merge branch 'handle-missing-archived-index' of github.com:prysmaticlabs/prysm into handle-missing-archived-index
* Merge refs/heads/master into handle-missing-archived-index
This commit is contained in:
terence tsao
2020-05-18 12:46:06 -07:00
committed by GitHub
parent ca26745720
commit 678347e64b
5 changed files with 96 additions and 11 deletions

View File

@@ -63,7 +63,10 @@ func (s *State) loadColdStateBySlot(ctx context.Context, slot uint64) (*state.Be
return nil, err
}
if archivedState == nil {
archivedRoot := s.archivedRoot(ctx, slot)
archivedRoot, err := s.archivedRoot(ctx, slot)
if err != nil {
return nil, err
}
archivedState, err = s.recoverStateByRoot(ctx, archivedRoot)
if err != nil {
return nil, err

View File

@@ -83,6 +83,9 @@ func TestLoadColdStateByRoot_CanGet(t *testing.T) {
if err := service.beaconDB.SaveGenesisBlockRoot(ctx, blkRoot); err != nil {
t.Fatal(err)
}
if service.beaconDB.SaveBlock(ctx, blk) != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveState(ctx, beaconState, blkRoot); err != nil {
t.Fatal(err)
}
@@ -121,6 +124,9 @@ func TestLoadColdStateBySlot_CanGet(t *testing.T) {
if err := service.beaconDB.SaveGenesisBlockRoot(ctx, blkRoot); err != nil {
t.Fatal(err)
}
if service.beaconDB.SaveBlock(ctx, blk) != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveState(ctx, beaconState, blkRoot); err != nil {
t.Fatal(err)
}

View File

@@ -41,6 +41,12 @@ func TestStateByRoot_ColdState(t *testing.T) {
if err := service.beaconDB.SaveState(ctx, beaconState, bRoot); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveBlock(ctx, b); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveGenesisBlockRoot(ctx, bRoot); err != nil {
t.Fatal(err)
}
r := [32]byte{'a'}
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{
Root: r[:],

View File

@@ -308,18 +308,38 @@ func (s *State) genesisRoot(ctx context.Context) ([32]byte, error) {
return stateutil.BlockRoot(b.Block)
}
// This retrieves the archived root in the DB.
func (s *State) archivedRoot(ctx context.Context, slot uint64) [32]byte {
// This returns the highest archived root based on input slot in the DB.
// If the archived root is not available at that exact input slot due to an event of skip block,
// this will look back and return the last available archived root (ie. the one with the highest slot below input slot).
func (s *State) archivedRoot(ctx context.Context, slot uint64) ([32]byte, error) {
archivedIndex := uint64(0)
if slot/params.BeaconConfig().SlotsPerArchivedPoint > 1 {
archivedIndex = slot/params.BeaconConfig().SlotsPerArchivedPoint - 1
}
return s.beaconDB.ArchivedPointRoot(ctx, archivedIndex)
for archivedIndex > 0 {
if ctx.Err() != nil {
return [32]byte{}, ctx.Err()
}
if s.beaconDB.HasArchivedPoint(ctx, archivedIndex) {
return s.beaconDB.ArchivedPointRoot(ctx, archivedIndex), nil
}
archivedIndex--
}
if archivedIndex == 0 {
return s.genesisRoot(ctx)
}
return [32]byte{}, errUnknownArchivedState
}
// This retrieves the archived state in the DB.
func (s *State) archivedState(ctx context.Context, slot uint64) (*state.BeaconState, error) {
archivedRoot := s.archivedRoot(ctx, slot)
archivedRoot, err := s.archivedRoot(ctx, slot)
if err != nil {
return nil, err
}
return s.beaconDB.State(ctx, archivedRoot)
}

View File

@@ -534,35 +534,85 @@ func TestLastSavedState_NoSavedBlockState(t *testing.T) {
}
}
func TestArchivedRoot_CanGet(t *testing.T) {
func TestArchivedRoot_CanGetSpecificIndex(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
service := New(db, cache.NewStateSummaryCache())
r := [32]byte{'a'}
if err := db.SaveArchivedPointRoot(ctx, r, 0); err != nil {
if err := db.SaveArchivedPointRoot(ctx, r, 1); err != nil {
t.Fatal(err)
}
got, err := service.archivedRoot(ctx, params.BeaconConfig().SlotsPerArchivedPoint*2)
if err != nil {
t.Fatal(err)
}
got := service.archivedRoot(ctx, params.BeaconConfig().SlotsPerArchivedPoint)
if r != got {
t.Error("Did not get wanted root")
}
}
func TestArchivedState_CanGet(t *testing.T) {
func TestArchivedRoot_CanGetOlderOlder(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
service := New(db, cache.NewStateSummaryCache())
r := [32]byte{'a'}
if err := db.SaveArchivedPointRoot(ctx, r, 0); err != nil {
if err := db.SaveArchivedPointRoot(ctx, r, 10); err != nil {
t.Fatal(err)
}
r = [32]byte{'b'}
if err := db.SaveArchivedPointRoot(ctx, r, 11); err != nil {
t.Fatal(err)
}
got, err := service.archivedRoot(ctx, 100000)
if err != nil {
t.Fatal(err)
}
if r != got {
t.Error("Did not get wanted root")
}
}
func TestArchivedRoot_CanGetGenesisIndex(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
service := New(db, cache.NewStateSummaryCache())
gBlock := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{}}
gRoot, err := stateutil.BlockRoot(gBlock.Block)
if err != nil {
t.Fatal(err)
}
if err := db.SaveBlock(ctx, gBlock); err != nil {
t.Fatal(err)
}
if err := db.SaveGenesisBlockRoot(ctx, gRoot); err != nil {
t.Fatal(err)
}
got, err := service.archivedRoot(ctx, 100000)
if err != nil {
t.Fatal(err)
}
if gRoot != got {
t.Error("Did not get wanted root")
}
}
func TestArchivedState_CanGetSpecificIndex(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
service := New(db, cache.NewStateSummaryCache())
r := [32]byte{'a'}
if err := db.SaveArchivedPointRoot(ctx, r, 1); err != nil {
t.Fatal(err)
}
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
if err := db.SaveState(ctx, beaconState, r); err != nil {
t.Fatal(err)
}
got, err := service.archivedState(ctx, params.BeaconConfig().SlotsPerArchivedPoint)
got, err := service.archivedState(ctx, params.BeaconConfig().SlotsPerArchivedPoint*2)
if err != nil {
t.Fatal(err)
}