mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-24 20:37:17 +00:00
Add hot state by slot retrival (#5052)
* Update replay conditions * loadHotStateBySlot * Tests and gaz * Tests
This commit is contained in:
parent
0c3af32274
commit
25c13663d2
@ -14,6 +14,7 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/filters:go_default_library",
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"go.opencensus.io/trace"
|
||||
@ -59,3 +60,45 @@ func (s *State) loadHotStateByRoot(ctx context.Context, blockRoot [32]byte) (*st
|
||||
|
||||
return hotState, nil
|
||||
}
|
||||
|
||||
// This loads a hot state by slot where the slot lies between the epoch boundary points.
|
||||
// This is a slower implementation (versus ByRoot) as slot is the only argument. It require fetching
|
||||
// all the blocks between the epoch boundary points for playback.
|
||||
// Use `loadHotStateByRoot` unless you really don't know the root.
|
||||
func (s *State) loadHotStateBySlot(ctx context.Context, slot uint64) (*state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "stateGen.loadHotStateBySlot")
|
||||
defer span.End()
|
||||
|
||||
// Gather epoch boundary information, that is where node starts to replay the blocks.
|
||||
boundarySlot := helpers.StartSlot(helpers.SlotToEpoch(slot))
|
||||
boundaryRoot, ok := s.epochBoundaryRoot(boundarySlot)
|
||||
if !ok {
|
||||
return nil, errUnknownBoundaryRoot
|
||||
}
|
||||
// Try the cache first then try the DB.
|
||||
boundaryState := s.hotStateCache.Get(boundaryRoot)
|
||||
var err error
|
||||
if boundaryState == nil {
|
||||
boundaryState, err = s.beaconDB.State(ctx, boundaryRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if boundaryState == nil {
|
||||
return nil, errUnknownBoundaryState
|
||||
}
|
||||
}
|
||||
|
||||
// Gather the last saved block root and the slot number.
|
||||
lastValidRoot, lastValidSlot, err := s.lastSavedBlock(ctx, slot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get last valid block for hot state using slot")
|
||||
}
|
||||
|
||||
// Load and replay blocks to get the intermediate state.
|
||||
replayBlks, err := s.LoadBlocks(ctx, boundaryState.Slot()+1, lastValidSlot, lastValidRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.ReplayBlocks(ctx, boundaryState, replayBlks, slot)
|
||||
}
|
||||
|
@ -94,3 +94,45 @@ func TestLoadHoteStateByRoot_FromDBBoundaryCase(t *testing.T) {
|
||||
t.Error("Did not correctly load state")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadHoteStateBySlot_CanAdvanceSlotUsingCache(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
service := New(db)
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
r := [32]byte{'A'}
|
||||
service.hotStateCache.Put(r, beaconState)
|
||||
service.setEpochBoundaryRoot(0, r)
|
||||
|
||||
slot := uint64(10)
|
||||
loadedState, err := service.loadHotStateBySlot(ctx, slot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if loadedState.Slot() != slot {
|
||||
t.Error("Did not correctly load state")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadHoteStateBySlot_CanAdvanceSlotUsingDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
service := New(db)
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
r := [32]byte{'A'}
|
||||
service.setEpochBoundaryRoot(0, r)
|
||||
if err := service.beaconDB.SaveState(ctx, beaconState, r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slot := uint64(10)
|
||||
loadedState, err := service.loadHotStateBySlot(ctx, slot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if loadedState.Slot() != slot {
|
||||
t.Error("Did not correctly load state")
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@ -247,7 +248,8 @@ func (s *State) lastSavedBlock(ctx context.Context, slot uint64) ([32]byte, uint
|
||||
return [32]byte{}, 0, err
|
||||
}
|
||||
if len(rs) == 0 {
|
||||
return [32]byte{}, 0, errors.New("block root has 0 length")
|
||||
// Return zero hash if there hasn't been any block in the DB yet.
|
||||
return params.BeaconChainConfig{}.ZeroHash, 0, nil
|
||||
}
|
||||
lastRoot := rs[len(rs)-1]
|
||||
|
||||
@ -286,7 +288,8 @@ func (s *State) lastSavedState(ctx context.Context, slot uint64) ([32]byte, erro
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if len(rs) == 0 {
|
||||
return [32]byte{}, errors.New("block root has 0 length")
|
||||
// Return zero hash if there hasn't been any block in the DB yet.
|
||||
return params.BeaconChainConfig{}.ZeroHash, nil
|
||||
}
|
||||
for i := len(rs) - 1; i >= 0; i-- {
|
||||
// Stop until a state is saved.
|
||||
|
@ -415,7 +415,7 @@ func TestLastSavedBlock_CanGet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLastSavedBlock_OutOfRange(t *testing.T) {
|
||||
func TestLastSavedBlock_NoSavedBlock(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
ctx := context.Background()
|
||||
@ -429,9 +429,12 @@ func TestLastSavedBlock_OutOfRange(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, _, err := s.lastSavedBlock(ctx, s.lastArchivedSlot+1)
|
||||
if err.Error() != "block root has 0 length" {
|
||||
t.Error("Did not get wanted error")
|
||||
r, slot, err := s.lastSavedBlock(ctx, s.lastArchivedSlot+1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if slot != 0 || r != params.BeaconConfig().ZeroHash {
|
||||
t.Error("Did not get no saved block info")
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,7 +507,7 @@ func TestLastSavedState_CanGet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLastSavedState_OutOfRange(t *testing.T) {
|
||||
func TestLastSavedState_NoSavedBlockState(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
ctx := context.Background()
|
||||
@ -518,9 +521,12 @@ func TestLastSavedState_OutOfRange(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err := s.lastSavedState(ctx, s.lastArchivedSlot+1)
|
||||
if err.Error() != "block root has 0 length" {
|
||||
t.Error("Did not get wanted error")
|
||||
r, err := s.lastSavedState(ctx, s.lastArchivedSlot+1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if r != params.BeaconConfig().ZeroHash {
|
||||
t.Error("Did not get no saved block info")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user