mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Clean up old block processing paths (#6311)
* Remove old block processing paths * Go fmt * Go fmt again * Fix tests * Using the wright receiver Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
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"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -78,15 +77,8 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
|
||||
// If the head state is not available, just return nil.
|
||||
// There's nothing to cache
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
if !s.stateGen.StateSummaryExists(ctx, headRoot) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
_, cached := s.initSyncState[headRoot]
|
||||
if !cached && !s.beaconDB.HasState(ctx, headRoot) {
|
||||
return nil
|
||||
}
|
||||
if !s.stateGen.StateSummaryExists(ctx, headRoot) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the new head block from DB.
|
||||
@@ -99,21 +91,9 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
}
|
||||
|
||||
// Get the new head state from cached state or DB.
|
||||
var newHeadState *state.BeaconState
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
newHeadState, err = s.stateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
} else {
|
||||
var exists bool
|
||||
newHeadState, exists = s.initSyncState[headRoot]
|
||||
if !exists {
|
||||
newHeadState, err = s.beaconDB.State(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
}
|
||||
newHeadState, err := s.stateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
if newHeadState == nil {
|
||||
return errors.New("cannot save nil head state")
|
||||
@@ -155,26 +135,9 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock,
|
||||
return errors.New("cannot save nil head block")
|
||||
}
|
||||
|
||||
var headState *state.BeaconState
|
||||
var err error
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
headState, err = s.stateGen.StateByRootInitialSync(ctx, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
} else {
|
||||
headState, err = s.beaconDB.State(ctx, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
if headState == nil {
|
||||
s.initSyncStateLock.RLock()
|
||||
cachedHeadState, ok := s.initSyncState[r]
|
||||
if ok {
|
||||
headState = cachedHeadState
|
||||
}
|
||||
s.initSyncStateLock.RUnlock()
|
||||
}
|
||||
headState, err := s.stateGen.StateByRootInitialSync(ctx, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
if headState == nil {
|
||||
return errors.New("nil head state")
|
||||
@@ -300,20 +263,11 @@ func (s *Service) cacheJustifiedStateBalances(ctx context.Context, justifiedRoot
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
|
||||
var justifiedState *stateTrie.BeaconState
|
||||
var err error
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
justifiedState, err = s.stateGen.StateByRoot(ctx, justifiedRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
justifiedState, err = s.beaconDB.State(ctx, justifiedRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
justifiedState, err := s.stateGen.StateByRoot(ctx, justifiedRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
epoch := helpers.CurrentEpoch(justifiedState)
|
||||
|
||||
@@ -205,10 +205,12 @@ func TestCacheJustifiedStateBalances_CanCache(t *testing.T) {
|
||||
|
||||
state, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
r := [32]byte{'a'}
|
||||
if err := service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: r[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(context.Background(), state, r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := service.cacheJustifiedStateBalances(context.Background(), r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,168 +2,13 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
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"
|
||||
)
|
||||
|
||||
const maxCacheSize = 70
|
||||
const initialSyncCacheSize = 45
|
||||
const minimumCacheSize = initialSyncCacheSize / 3
|
||||
|
||||
func (s *Service) persistCachedStates(ctx context.Context, numOfStates int) error {
|
||||
oldStates := make([]*stateTrie.BeaconState, 0, numOfStates)
|
||||
|
||||
// Add slots to the map and add epoch boundary states to the slice.
|
||||
for _, rt := range s.boundaryRoots[:numOfStates-minimumCacheSize] {
|
||||
oldStates = append(oldStates, s.initSyncState[rt])
|
||||
}
|
||||
|
||||
err := s.beaconDB.SaveStates(ctx, oldStates, s.boundaryRoots[:numOfStates-minimumCacheSize])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, rt := range s.boundaryRoots[:numOfStates-minimumCacheSize] {
|
||||
delete(s.initSyncState, rt)
|
||||
}
|
||||
s.boundaryRoots = s.boundaryRoots[numOfStates-minimumCacheSize:]
|
||||
return nil
|
||||
}
|
||||
|
||||
// filter out boundary candidates from our currently processed batch of states.
|
||||
func (s *Service) filterBoundaryCandidates(ctx context.Context, root [32]byte, postState *stateTrie.BeaconState) {
|
||||
// Only trigger on epoch start.
|
||||
if !helpers.IsEpochStart(postState.Slot()) {
|
||||
return
|
||||
}
|
||||
|
||||
stateSlice := make([][32]byte, 0, len(s.initSyncState))
|
||||
// Add epoch boundary roots to slice.
|
||||
for rt := range s.initSyncState {
|
||||
stateSlice = append(stateSlice, rt)
|
||||
}
|
||||
|
||||
sort.Slice(stateSlice, func(i int, j int) bool {
|
||||
return s.initSyncState[stateSlice[i]].Slot() < s.initSyncState[stateSlice[j]].Slot()
|
||||
})
|
||||
epochLength := params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
if len(s.boundaryRoots) > 0 {
|
||||
// Retrieve previous boundary root.
|
||||
previousBoundaryRoot := s.boundaryRoots[len(s.boundaryRoots)-1]
|
||||
previousState, ok := s.initSyncState[previousBoundaryRoot]
|
||||
if !ok {
|
||||
// Remove the non-existent root and exit filtering.
|
||||
s.boundaryRoots = s.boundaryRoots[:len(s.boundaryRoots)-1]
|
||||
return
|
||||
}
|
||||
previousSlot := previousState.Slot()
|
||||
|
||||
// Round up slot number to account for skipped slots.
|
||||
previousSlot = helpers.RoundUpToNearestEpoch(previousSlot)
|
||||
if postState.Slot()-previousSlot >= epochLength {
|
||||
targetSlot := postState.Slot()
|
||||
tempRoots := s.loopThroughCandidates(stateSlice, previousBoundaryRoot, previousSlot, targetSlot)
|
||||
s.boundaryRoots = append(s.boundaryRoots, tempRoots...)
|
||||
}
|
||||
}
|
||||
s.boundaryRoots = append(s.boundaryRoots, root)
|
||||
s.pruneOldStates()
|
||||
s.pruneNonBoundaryStates()
|
||||
}
|
||||
|
||||
// loop-through the provided candidate roots to filter out which would be appropriate boundary roots.
|
||||
func (s *Service) loopThroughCandidates(stateSlice [][32]byte, previousBoundaryRoot [32]byte,
|
||||
previousSlot uint64, targetSlot uint64) [][32]byte {
|
||||
tempRoots := [][32]byte{}
|
||||
epochLength := params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
// Loop through current states to filter for valid boundary states.
|
||||
for i := len(stateSlice) - 1; stateSlice[i] != previousBoundaryRoot && i >= 0; i-- {
|
||||
currentSlot := s.initSyncState[stateSlice[i]].Slot()
|
||||
// Skip if the current slot is larger than the previous epoch
|
||||
// boundary.
|
||||
if currentSlot > targetSlot-epochLength {
|
||||
continue
|
||||
}
|
||||
tempRoots = append(tempRoots, stateSlice[i])
|
||||
|
||||
// Switch target slot if the current slot is greater than
|
||||
// 1 epoch boundary from the previously saved boundary slot.
|
||||
if currentSlot > previousSlot+epochLength {
|
||||
currentSlot = helpers.RoundUpToNearestEpoch(currentSlot)
|
||||
targetSlot = currentSlot
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
// Reverse to append the roots in ascending order corresponding
|
||||
// to the respective slots.
|
||||
tempRoots = bytesutil.ReverseBytes32Slice(tempRoots)
|
||||
return tempRoots
|
||||
}
|
||||
|
||||
// prune for states past the current finalized checkpoint.
|
||||
func (s *Service) pruneOldStates() {
|
||||
prunedBoundaryRoots := [][32]byte{}
|
||||
for _, rt := range s.boundaryRoots {
|
||||
st, ok := s.initSyncState[rt]
|
||||
// Skip non-existent roots.
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if st.Slot() < helpers.StartSlot(s.FinalizedCheckpt().Epoch) {
|
||||
delete(s.initSyncState, rt)
|
||||
continue
|
||||
}
|
||||
prunedBoundaryRoots = append(prunedBoundaryRoots, rt)
|
||||
}
|
||||
s.boundaryRoots = prunedBoundaryRoots
|
||||
}
|
||||
|
||||
// prune cache for non-boundary states.
|
||||
func (s *Service) pruneNonBoundaryStates() {
|
||||
boundaryMap := make(map[[32]byte]bool)
|
||||
for i := range s.boundaryRoots {
|
||||
boundaryMap[s.boundaryRoots[i]] = true
|
||||
}
|
||||
for rt := range s.initSyncState {
|
||||
if !boundaryMap[rt] {
|
||||
delete(s.initSyncState, rt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) pruneOldNonFinalizedStates() {
|
||||
stateSlice := make([][32]byte, 0, len(s.initSyncState))
|
||||
// Add epoch boundary roots to slice.
|
||||
for rt := range s.initSyncState {
|
||||
stateSlice = append(stateSlice, rt)
|
||||
}
|
||||
|
||||
// Sort by slots.
|
||||
sort.Slice(stateSlice, func(i int, j int) bool {
|
||||
return s.initSyncState[stateSlice[i]].Slot() < s.initSyncState[stateSlice[j]].Slot()
|
||||
})
|
||||
|
||||
boundaryMap := make(map[[32]byte]bool)
|
||||
for i := range s.boundaryRoots {
|
||||
boundaryMap[s.boundaryRoots[i]] = true
|
||||
}
|
||||
for _, rt := range stateSlice[:initialSyncCacheSize] {
|
||||
if boundaryMap[rt] {
|
||||
continue
|
||||
}
|
||||
delete(s.initSyncState, rt)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) generateState(ctx context.Context, startRoot [32]byte, endRoot [32]byte) (*stateTrie.BeaconState, error) {
|
||||
preState, err := s.beaconDB.State(ctx, startRoot)
|
||||
if err != nil {
|
||||
|
||||
@@ -7,231 +7,16 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
)
|
||||
|
||||
func TestFilterBoundaryCandidates_FilterCorrect(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 500; i++ {
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
if helpers.IsEpochStart(i) {
|
||||
service.boundaryRoots = append(service.boundaryRoots, root)
|
||||
}
|
||||
}
|
||||
lastIndex := len(service.boundaryRoots) - 1
|
||||
for i := uint64(500); i < 2000; i++ {
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
}
|
||||
// Set current state.
|
||||
latestSlot := helpers.RoundUpToNearestEpoch(2000)
|
||||
if err := st.SetSlot(latestSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lastRoot := [32]byte{}
|
||||
copy(lastRoot[:], bytesutil.Bytes32(latestSlot))
|
||||
|
||||
service.initSyncState[lastRoot] = st.Copy()
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: []byte{},
|
||||
}
|
||||
service.filterBoundaryCandidates(context.Background(), lastRoot, st)
|
||||
if len(service.boundaryRoots[lastIndex+1:]) == 0 {
|
||||
t.Fatal("Wanted non zero added boundary roots")
|
||||
}
|
||||
for _, rt := range service.boundaryRoots[lastIndex+1:] {
|
||||
st, ok := service.initSyncState[rt]
|
||||
if !ok {
|
||||
t.Error("Root doen't exist in cache map")
|
||||
continue
|
||||
}
|
||||
if !(helpers.IsEpochStart(st.Slot()) || helpers.IsEpochStart(st.Slot()-1) || helpers.IsEpochStart(st.Slot()+1)) {
|
||||
t.Errorf("boundary roots not validly stored. They have slot %d", st.Slot())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterBoundaryCandidates_HandleSkippedSlots(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 500; i++ {
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
if helpers.IsEpochStart(i) {
|
||||
service.boundaryRoots = append(service.boundaryRoots, root)
|
||||
}
|
||||
}
|
||||
lastIndex := len(service.boundaryRoots) - 1
|
||||
for i := uint64(500); i < 2000; i++ {
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
// save only for offsetted slots
|
||||
if helpers.IsEpochStart(i + 10) {
|
||||
service.initSyncState[root] = st.Copy()
|
||||
}
|
||||
}
|
||||
// Set current state.
|
||||
latestSlot := helpers.RoundUpToNearestEpoch(2000)
|
||||
if err := st.SetSlot(latestSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lastRoot := [32]byte{}
|
||||
copy(lastRoot[:], bytesutil.Bytes32(latestSlot))
|
||||
|
||||
service.initSyncState[lastRoot] = st.Copy()
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: []byte{},
|
||||
}
|
||||
service.filterBoundaryCandidates(context.Background(), lastRoot, st)
|
||||
if len(service.boundaryRoots[lastIndex+1:]) == 0 {
|
||||
t.Fatal("Wanted non zero added boundary roots")
|
||||
}
|
||||
for _, rt := range service.boundaryRoots[lastIndex+1:] {
|
||||
st, ok := service.initSyncState[rt]
|
||||
if !ok {
|
||||
t.Error("Root doen't exist in cache map")
|
||||
continue
|
||||
}
|
||||
if st.Slot() >= 500 {
|
||||
// Ignore head boundary root.
|
||||
if st.Slot() == 2016 {
|
||||
continue
|
||||
}
|
||||
if !helpers.IsEpochStart(st.Slot() + 10) {
|
||||
t.Errorf("boundary roots not validly stored. They have slot %d "+
|
||||
"instead of the offset from epoch start", st.Slot())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPruneOldStates_AlreadyFinalized(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(100); i < 200; i++ {
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
service.boundaryRoots = append(service.boundaryRoots, root)
|
||||
}
|
||||
finalizedEpoch := uint64(5)
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Epoch: finalizedEpoch}
|
||||
service.pruneOldStates()
|
||||
for _, rt := range service.boundaryRoots {
|
||||
st, ok := service.initSyncState[rt]
|
||||
if !ok {
|
||||
t.Error("Root doen't exist in cache map")
|
||||
continue
|
||||
}
|
||||
if st.Slot() < helpers.StartSlot(finalizedEpoch) {
|
||||
t.Errorf("State with slot %d still exists and not pruned", st.Slot())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPruneNonBoundary_CanPrune(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 2000; i++ {
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
if helpers.IsEpochStart(i) {
|
||||
service.boundaryRoots = append(service.boundaryRoots, root)
|
||||
}
|
||||
}
|
||||
service.pruneNonBoundaryStates()
|
||||
for _, rt := range service.boundaryRoots {
|
||||
st, ok := service.initSyncState[rt]
|
||||
if !ok {
|
||||
t.Error("Root doesn't exist in cache map")
|
||||
continue
|
||||
}
|
||||
if !helpers.IsEpochStart(st.Slot()) {
|
||||
t.Errorf("Non boundary state with slot %d still exists and not pruned", st.Slot())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateState_CorrectlyGenerated(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
cfg := &Config{BeaconDB: db, StateGen: stategen.New(db, cache.NewStateSummaryCache())}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -31,88 +30,35 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
return cachedState, nil
|
||||
}
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
if !s.stateGen.HasState(ctx, bytesutil.ToBytes32(c.Root)) {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save initial sync blocks")
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
if !s.stateGen.HasState(ctx, bytesutil.ToBytes32(c.Root)) {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save initial sync blocks")
|
||||
}
|
||||
|
||||
baseState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
|
||||
if helpers.StartSlot(c.Epoch) > baseState.Slot() {
|
||||
baseState = baseState.Copy()
|
||||
baseState, err = state.ProcessSlots(ctx, baseState, helpers.StartSlot(c.Epoch))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not process slots up to %d", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.checkpointState.AddCheckpointState(&cache.CheckpointState{
|
||||
Checkpoint: c,
|
||||
State: baseState,
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
|
||||
}
|
||||
|
||||
return baseState, nil
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
|
||||
if featureconfig.Get().CheckHeadState {
|
||||
headRoot, err := s.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get head root")
|
||||
}
|
||||
if bytes.Equal(headRoot, c.Root) {
|
||||
st, err := s.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get head state")
|
||||
}
|
||||
if err := s.checkpointState.AddCheckpointState(&cache.CheckpointState{
|
||||
Checkpoint: c,
|
||||
State: st.Copy(),
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
}
|
||||
|
||||
baseState, err := s.beaconDB.State(ctx, bytesutil.ToBytes32(c.Root))
|
||||
baseState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
if baseState == nil {
|
||||
return nil, fmt.Errorf("pre state of target block %d does not exist", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
|
||||
if helpers.StartSlot(c.Epoch) > baseState.Slot() {
|
||||
savedState := baseState.Copy()
|
||||
savedState, err = state.ProcessSlots(ctx, savedState, helpers.StartSlot(c.Epoch))
|
||||
baseState = baseState.Copy()
|
||||
baseState, err = state.ProcessSlots(ctx, baseState, helpers.StartSlot(c.Epoch))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not process slots up to %d", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
if err := s.checkpointState.AddCheckpointState(&cache.CheckpointState{
|
||||
Checkpoint: c,
|
||||
State: savedState.Copy(),
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
|
||||
}
|
||||
return savedState, nil
|
||||
}
|
||||
|
||||
if err := s.checkpointState.AddCheckpointState(&cache.CheckpointState{
|
||||
Checkpoint: c,
|
||||
State: baseState.Copy(),
|
||||
State: baseState,
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
|
||||
}
|
||||
|
||||
return baseState, nil
|
||||
|
||||
}
|
||||
|
||||
// verifyAttTargetEpoch validates attestation is from the current or previous epoch.
|
||||
@@ -170,25 +116,17 @@ func (s *Service) verifyAttestation(ctx context.Context, baseState *stateTrie.Be
|
||||
if err == helpers.ErrSigFailedToVerify {
|
||||
// When sig fails to verify, check if there's a differences in committees due to
|
||||
// different seeds.
|
||||
var aState *stateTrie.BeaconState
|
||||
var err error
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
if !s.stateGen.HasState(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot)) {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save initial sync blocks")
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
aState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
aState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if !s.stateGen.HasState(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot)) {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save initial sync blocks")
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
aState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if aState == nil {
|
||||
return nil, fmt.Errorf("nil state for block root %#x", a.Data.BeaconBlockRoot)
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
a: ðpb.Attestation{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
|
||||
s: &pb.BeaconState{},
|
||||
wantErr: true,
|
||||
wantErrString: "pre state of target block 0 does not exist",
|
||||
wantErrString: "could not get pre state for slot 0",
|
||||
},
|
||||
{
|
||||
name: "process attestation doesn't match current epoch",
|
||||
|
||||
@@ -89,14 +89,8 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
return nil, errors.Wrapf(err, "could not insert block %d to fork choice store", b.Slot)
|
||||
}
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
if err := s.stateGen.SaveState(ctx, blockRoot, postState); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save state")
|
||||
}
|
||||
} else {
|
||||
if err := s.beaconDB.SaveState(ctx, postState, blockRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save state")
|
||||
}
|
||||
if err := s.stateGen.SaveState(ctx, blockRoot, postState); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save state")
|
||||
}
|
||||
|
||||
// Update justified check point.
|
||||
@@ -119,16 +113,6 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
return nil, errors.Wrap(err, "could not save finalized checkpoint")
|
||||
}
|
||||
|
||||
if !featureconfig.Get().NewStateMgmt {
|
||||
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
|
||||
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
|
||||
if endSlot > startSlot {
|
||||
if err := s.rmStatesOlderThanLastFinalized(ctx, startSlot, endSlot); err != nil {
|
||||
return nil, errors.Wrapf(err, "could not delete states prior to finalized check point, range: %d, %d",
|
||||
startSlot, endSlot)
|
||||
}
|
||||
}
|
||||
}
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
|
||||
// Prune proto array fork choice nodes, all nodes before finalized check point will
|
||||
@@ -144,15 +128,12 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
return nil, errors.Wrap(err, "could not save new justified")
|
||||
}
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
fBlock, err := s.beaconDB.Block(ctx, fRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get finalized block to migrate")
|
||||
}
|
||||
if err := s.stateGen.MigrateToCold(ctx, fBlock.Block.Slot, fRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not migrate to cold")
|
||||
}
|
||||
fBlock, err := s.beaconDB.Block(ctx, fRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get finalized block to migrate")
|
||||
}
|
||||
if err := s.stateGen.MigrateToCold(ctx, fBlock.Block.Slot, fRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not migrate to cold")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,15 +218,8 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
return errors.Wrapf(err, "could not insert block %d to fork choice store", b.Slot)
|
||||
}
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
if err := s.stateGen.SaveState(ctx, blockRoot, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
} else {
|
||||
s.initSyncStateLock.Lock()
|
||||
defer s.initSyncStateLock.Unlock()
|
||||
s.initSyncState[blockRoot] = postState.Copy()
|
||||
s.filterBoundaryCandidates(ctx, blockRoot, postState)
|
||||
if err := s.stateGen.SaveState(ctx, blockRoot, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
|
||||
if flags.Get().EnableArchive {
|
||||
@@ -265,21 +239,6 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
|
||||
// Update finalized check point. Prune the block cache and helper caches on every new finalized epoch.
|
||||
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
|
||||
if !featureconfig.Get().NewStateMgmt {
|
||||
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
|
||||
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
|
||||
if endSlot > startSlot {
|
||||
if err := s.rmStatesOlderThanLastFinalized(ctx, startSlot, endSlot); err != nil {
|
||||
return errors.Wrapf(err, "could not delete states prior to finalized check point, range: %d, %d",
|
||||
startSlot, endSlot)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.saveInitState(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save init sync finalized state")
|
||||
}
|
||||
}
|
||||
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
@@ -294,27 +253,13 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
s.prevFinalizedCheckpt = s.finalizedCheckpt
|
||||
s.finalizedCheckpt = postState.FinalizedCheckpoint()
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
fBlock, err := s.beaconDB.Block(ctx, fRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized block to migrate")
|
||||
}
|
||||
if err := s.stateGen.MigrateToCold(ctx, fBlock.Block.Slot, fRoot); err != nil {
|
||||
return errors.Wrap(err, "could not migrate to cold")
|
||||
}
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
fBlock, err := s.beaconDB.Block(ctx, fRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized block to migrate")
|
||||
}
|
||||
}
|
||||
|
||||
if !featureconfig.Get().NewStateMgmt {
|
||||
numOfStates := len(s.boundaryRoots)
|
||||
if numOfStates > initialSyncCacheSize {
|
||||
if err = s.persistCachedStates(ctx, numOfStates); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(s.initSyncState) > maxCacheSize {
|
||||
s.pruneOldNonFinalizedStates()
|
||||
if err := s.stateGen.MigrateToCold(ctx, fBlock.Block.Slot, fRoot); err != nil {
|
||||
return errors.Wrap(err, "could not migrate to cold")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,12 +275,6 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
if err := helpers.UpdateProposerIndicesInCache(postState, helpers.CurrentEpoch(postState)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !featureconfig.Get().NewStateMgmt && helpers.IsEpochStart(postState.Slot()) {
|
||||
if err := s.beaconDB.SaveState(ctx, postState, blockRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
@@ -43,16 +42,12 @@ func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// For new state management, this ensures the state does not get mutated since initial syncing
|
||||
// uses verifyBlkPreState.
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
preState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(b.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
|
||||
}
|
||||
if preState == nil {
|
||||
return nil, errors.Wrapf(err, "nil pre state for slot %d", b.Slot)
|
||||
}
|
||||
preState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(b.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
|
||||
}
|
||||
if preState == nil {
|
||||
return nil, errors.Wrapf(err, "nil pre state for slot %d", b.Slot)
|
||||
}
|
||||
|
||||
// Verify block slot time is not from the feature.
|
||||
@@ -78,59 +73,28 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b *ethpb.BeaconBlock) (
|
||||
ctx, span := trace.StartSpan(ctx, "chainService.verifyBlkPreState")
|
||||
defer span.End()
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
parentRoot := bytesutil.ToBytes32(b.ParentRoot)
|
||||
// Loosen the check to HasBlock because state summary gets saved in batches
|
||||
// during initial syncing. There's no risk given a state summary object is just a
|
||||
// a subset of the block object.
|
||||
if !s.stateGen.StateSummaryExists(ctx, parentRoot) && !s.beaconDB.HasBlock(ctx, parentRoot) {
|
||||
return nil, errors.New("could not reconstruct parent state")
|
||||
}
|
||||
if !s.stateGen.HasState(ctx, parentRoot) {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save initial sync blocks")
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
preState, err := s.stateGen.StateByRootInitialSync(ctx, parentRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
|
||||
}
|
||||
if preState == nil {
|
||||
return nil, errors.Wrapf(err, "nil pre state for slot %d", b.Slot)
|
||||
}
|
||||
|
||||
return preState, nil // No copy needed from newly hydrated state gen object.
|
||||
parentRoot := bytesutil.ToBytes32(b.ParentRoot)
|
||||
// Loosen the check to HasBlock because state summary gets saved in batches
|
||||
// during initial syncing. There's no risk given a state summary object is just a
|
||||
// a subset of the block object.
|
||||
if !s.stateGen.StateSummaryExists(ctx, parentRoot) && !s.beaconDB.HasBlock(ctx, parentRoot) {
|
||||
return nil, errors.New("could not reconstruct parent state")
|
||||
}
|
||||
if !s.stateGen.HasState(ctx, parentRoot) {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save initial sync blocks")
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
preState, err := s.stateGen.StateByRootInitialSync(ctx, parentRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
|
||||
}
|
||||
|
||||
preState := s.initSyncState[bytesutil.ToBytes32(b.ParentRoot)]
|
||||
var err error
|
||||
if preState == nil {
|
||||
if featureconfig.Get().CheckHeadState {
|
||||
headRoot, err := s.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get head root")
|
||||
}
|
||||
if bytes.Equal(headRoot, b.ParentRoot) {
|
||||
return s.HeadState(ctx)
|
||||
}
|
||||
}
|
||||
preState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(b.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
|
||||
}
|
||||
if preState == nil {
|
||||
if bytes.Equal(s.finalizedCheckpt.Root, b.ParentRoot) {
|
||||
return nil, fmt.Errorf("pre state of slot %d does not exist", b.Slot)
|
||||
}
|
||||
preState, err = s.generateState(ctx, bytesutil.ToBytes32(s.finalizedCheckpt.Root), bytesutil.ToBytes32(b.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return preState, nil // No copy needed from newly hydrated DB object.
|
||||
return nil, errors.Wrapf(err, "nil pre state for slot %d", b.Slot)
|
||||
}
|
||||
return preState.Copy(), nil
|
||||
|
||||
return preState, nil // No copy needed from newly hydrated state gen object.
|
||||
}
|
||||
|
||||
// verifyBlkDescendant validates input block root is a descendant of the
|
||||
@@ -172,64 +136,6 @@ func (s *Service) verifyBlkFinalizedSlot(b *ethpb.BeaconBlock) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rmStatesOlderThanLastFinalized deletes the states in db since last finalized check point.
|
||||
func (s *Service) rmStatesOlderThanLastFinalized(ctx context.Context, startSlot uint64, endSlot uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "forkchoice.rmStatesBySlots")
|
||||
defer span.End()
|
||||
|
||||
// Make sure start slot is not a skipped slot
|
||||
for i := startSlot; i > 0; i-- {
|
||||
filter := filters.NewFilter().SetStartSlot(i).SetEndSlot(i)
|
||||
b, err := s.beaconDB.Blocks(ctx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(b) > 0 {
|
||||
startSlot = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure finalized slot is not a skipped slot.
|
||||
for i := endSlot; i > 0; i-- {
|
||||
filter := filters.NewFilter().SetStartSlot(i).SetEndSlot(i)
|
||||
b, err := s.beaconDB.Blocks(ctx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(b) > 0 {
|
||||
endSlot = i - 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Do not remove genesis state
|
||||
if startSlot == 0 {
|
||||
startSlot++
|
||||
}
|
||||
// If end slot comes less than start slot
|
||||
if endSlot < startSlot {
|
||||
endSlot = startSlot
|
||||
}
|
||||
|
||||
filter := filters.NewFilter().SetStartSlot(startSlot).SetEndSlot(endSlot)
|
||||
roots, err := s.beaconDB.BlockRoots(ctx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
roots, err = s.filterBlockRoots(ctx, roots)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.beaconDB.DeleteStates(ctx, roots); err != nil {
|
||||
log.Warnf("Could not delete states: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// shouldUpdateCurrentJustified prevents bouncing attack, by only update conflicting justified
|
||||
// checkpoints in the fork choice if in the early slots of the epoch.
|
||||
// Otherwise, delay incorporation of new justified checkpoint until next epoch boundary.
|
||||
@@ -300,86 +206,9 @@ func (s *Service) updateJustified(ctx context.Context, state *stateTrie.BeaconSt
|
||||
}
|
||||
}
|
||||
|
||||
if !featureconfig.Get().NewStateMgmt {
|
||||
justifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(cpt.Root))
|
||||
justifiedState := s.initSyncState[justifiedRoot]
|
||||
// If justified state is nil, resume back to normal syncing process and save
|
||||
// justified check point.
|
||||
var err error
|
||||
if justifiedState == nil {
|
||||
if s.beaconDB.HasState(ctx, justifiedRoot) {
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
}
|
||||
justifiedState, err = s.generateState(ctx, bytesutil.ToBytes32(s.finalizedCheckpt.Root), justifiedRoot)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
}
|
||||
}
|
||||
if err := s.beaconDB.SaveState(ctx, justifiedState, justifiedRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save justified state")
|
||||
}
|
||||
}
|
||||
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
}
|
||||
|
||||
// This saves every finalized state in DB during initial sync, needed as part of optimization to
|
||||
// use cache state during initial sync in case of restart.
|
||||
func (s *Service) saveInitState(ctx context.Context, state *stateTrie.BeaconState) error {
|
||||
cpt := state.FinalizedCheckpoint()
|
||||
finalizedRoot := bytesutil.ToBytes32(cpt.Root)
|
||||
fs := s.initSyncState[finalizedRoot]
|
||||
if fs == nil {
|
||||
var err error
|
||||
fs, err = s.beaconDB.State(ctx, finalizedRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if fs == nil {
|
||||
fs, err = s.generateState(ctx, bytesutil.ToBytes32(s.prevFinalizedCheckpt.Root), finalizedRoot)
|
||||
if err != nil {
|
||||
// This might happen if the client was in sync and is now re-syncing for whatever reason.
|
||||
log.Warn("Initial sync cache did not have finalized state root cached")
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.beaconDB.SaveState(ctx, fs, finalizedRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This filters block roots that are not known as head root and finalized root in DB.
|
||||
// It serves as the last line of defence before we prune states.
|
||||
func (s *Service) filterBlockRoots(ctx context.Context, roots [][32]byte) ([][32]byte, error) {
|
||||
f, err := s.beaconDB.FinalizedCheckpoint(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fRoot := f.Root
|
||||
h, err := s.beaconDB.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hRoot, err := stateutil.BlockRoot(h.Block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filtered := make([][32]byte, 0, len(roots))
|
||||
for _, root := range roots {
|
||||
if bytes.Equal(root[:], fRoot[:]) || bytes.Equal(root[:], hRoot[:]) {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, root)
|
||||
}
|
||||
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
// ancestor returns the block root of an ancestry block from the input block root.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
@@ -90,7 +89,7 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
name: "parent block root does not have a state",
|
||||
blk: ðpb.BeaconBlock{},
|
||||
s: st.Copy(),
|
||||
wantErrString: "provided block root does not have block saved in the db",
|
||||
wantErrString: "could not reconstruct parent state",
|
||||
},
|
||||
{
|
||||
name: "block is from the future",
|
||||
@@ -132,85 +131,6 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveStateSinceLastFinalized(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
params.UseMinimalConfig()
|
||||
defer params.UseMainnetConfig()
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Save 100 blocks in DB, each has a state.
|
||||
numBlocks := 100
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, numBlocks)
|
||||
blockRoots := make([][32]byte, 0)
|
||||
for i := 0; i < len(totalBlocks); i++ {
|
||||
totalBlocks[i] = ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: uint64(i),
|
||||
},
|
||||
}
|
||||
r, err := stateutil.BlockRoot(totalBlocks[i].Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetSlot(uint64(i)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, s, r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveBlock(ctx, totalBlocks[i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
blockRoots = append(blockRoots, r)
|
||||
if err := service.beaconDB.SaveHeadBlockRoot(ctx, r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// New finalized epoch: 1
|
||||
finalizedEpoch := uint64(1)
|
||||
finalizedSlot := finalizedEpoch * params.BeaconConfig().SlotsPerEpoch
|
||||
endSlot := helpers.StartSlot(finalizedEpoch+1) - 1 // Inclusive
|
||||
if err := service.rmStatesOlderThanLastFinalized(ctx, 0, endSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, r := range blockRoots {
|
||||
s, err := service.beaconDB.State(ctx, r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Also verifies genesis state didnt get deleted
|
||||
if s != nil && s.Slot() != finalizedSlot && s.Slot() != 0 && s.Slot() < endSlot {
|
||||
t.Errorf("State with slot %d should not be in DB", s.Slot())
|
||||
}
|
||||
}
|
||||
|
||||
// New finalized epoch: 5
|
||||
newFinalizedEpoch := uint64(5)
|
||||
newFinalizedSlot := newFinalizedEpoch * params.BeaconConfig().SlotsPerEpoch
|
||||
endSlot = helpers.StartSlot(newFinalizedEpoch+1) - 1 // Inclusive
|
||||
if err := service.rmStatesOlderThanLastFinalized(ctx, helpers.StartSlot(finalizedEpoch+1)-1, endSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, r := range blockRoots {
|
||||
s, err := service.beaconDB.State(ctx, r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Also verifies genesis state didnt get deleted
|
||||
if s != nil && s.Slot() != newFinalizedSlot && s.Slot() != finalizedSlot && s.Slot() != 0 && s.Slot() < endSlot {
|
||||
t.Errorf("State with slot %d should not be in DB", s.Slot())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
@@ -389,53 +309,6 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveInitState_CanSaveDelete(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 64; i++ {
|
||||
b := ðpb.BeaconBlock{Slot: i}
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := ssz.HashTreeRoot(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
service.initSyncState[r] = s
|
||||
}
|
||||
|
||||
// Set finalized root as slot 32
|
||||
finalizedRoot, err := ssz.HashTreeRoot(ðpb.BeaconBlock{Slot: 32})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: 1, Root: finalizedRoot[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.saveInitState(ctx, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify finalized state is saved in DB
|
||||
finalizedState, err := service.beaconDB.State(ctx, finalizedRoot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if finalizedState == nil {
|
||||
t.Error("finalized state can't be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
@@ -486,100 +359,6 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterBlockRoots_CanFilter(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fBlock := ðpb.BeaconBlock{}
|
||||
fRoot, err := stateutil.BlockRoot(fBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hBlock := ðpb.BeaconBlock{Slot: 1}
|
||||
headRoot, err := stateutil.BlockRoot(hBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
if err := service.beaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: fBlock}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, st.Copy(), fRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: fRoot[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: hBlock}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, st.Copy(), headRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveHeadBlockRoot(ctx, headRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
roots := [][32]byte{{'C'}, {'D'}, headRoot, {'E'}, fRoot, {'F'}}
|
||||
wanted := [][32]byte{{'C'}, {'D'}, {'E'}, {'F'}}
|
||||
|
||||
received, err := service.filterBlockRoots(ctx, roots)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(wanted, received) {
|
||||
t.Error("Did not filter correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPersistCache_CanSave(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
for i := uint64(0); i < initialSyncCacheSize; i++ {
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
service.boundaryRoots = append(service.boundaryRoots, root)
|
||||
}
|
||||
|
||||
if err = service.persistCachedStates(ctx, initialSyncCacheSize); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < initialSyncCacheSize-minimumCacheSize; i++ {
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
state, err := db.State(context.Background(), root)
|
||||
if err != nil {
|
||||
t.Errorf("State with root of %#x , could not be retrieved: %v", root, err)
|
||||
}
|
||||
if state == nil {
|
||||
t.Errorf("State with root of %#x , does not exist", root)
|
||||
}
|
||||
if state.Slot() != i {
|
||||
t.Errorf("Incorrect slot retrieved. Wanted %d but got %d", i, state.Slot())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
@@ -899,11 +678,18 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
|
||||
if err := beaconState.SetCurrentJustifiedCheckpoint(test.args.stateCheckPoint); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
service, err := NewService(ctx, &Config{BeaconDB: db})
|
||||
service, err := NewService(ctx, &Config{BeaconDB: db, StateGen: stategen.New(db, cache.NewStateSummaryCache())})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
service.justifiedCheckpt = test.args.cachedCheckPoint
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
genesisState := testutil.NewBeaconState()
|
||||
if err := service.beaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if test.args.diffFinalizedCheckPoint {
|
||||
b1 := ðpb.BeaconBlock{Slot: 1, ParentRoot: []byte{'a'}}
|
||||
|
||||
@@ -100,13 +100,7 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
|
||||
continue
|
||||
}
|
||||
|
||||
var hasState bool
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
hasState = s.stateGen.StateSummaryExists(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
} else {
|
||||
hasState = s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot)) && s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.Target.Root))
|
||||
}
|
||||
|
||||
hasState := s.stateGen.StateSummaryExists(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
hasBlock := s.hasBlock(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if !(hasState && hasBlock) {
|
||||
continue
|
||||
|
||||
@@ -147,16 +147,9 @@ func (s *Service) Start() {
|
||||
}
|
||||
|
||||
if beaconState == nil {
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
beaconState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state by root: %v", err)
|
||||
}
|
||||
} else {
|
||||
beaconState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state: %v", err)
|
||||
}
|
||||
beaconState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state by root: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,14 +188,6 @@ func (s *Service) Start() {
|
||||
s.prevFinalizedCheckpt = stateTrie.CopyCheckpoint(finalizedCheckpoint)
|
||||
s.resumeForkChoice(justifiedCheckpoint, finalizedCheckpoint)
|
||||
|
||||
if !featureconfig.Get().NewStateMgmt {
|
||||
if finalizedCheckpoint.Epoch > 1 {
|
||||
if err := s.pruneGarbageState(ctx, helpers.StartSlot(finalizedCheckpoint.Epoch)-params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
log.WithError(err).Warn("Could not prune old states")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Initialized,
|
||||
Data: &statefeed.InitializedData{
|
||||
@@ -347,21 +332,16 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.B
|
||||
if err := s.beaconDB.SaveBlock(ctx, genesisBlk); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis block")
|
||||
}
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
if err := s.stateGen.SaveState(ctx, genesisBlkRoot, genesisState); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis state")
|
||||
}
|
||||
if err := s.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{
|
||||
Slot: 0,
|
||||
Root: genesisBlkRoot[:],
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := s.beaconDB.SaveState(ctx, genesisState, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis state")
|
||||
}
|
||||
if err := s.stateGen.SaveState(ctx, genesisBlkRoot, genesisState); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis state")
|
||||
}
|
||||
if err := s.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{
|
||||
Slot: 0,
|
||||
Root: genesisBlkRoot[:],
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.beaconDB.SaveHeadBlockRoot(ctx, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save head block root")
|
||||
}
|
||||
@@ -440,24 +420,18 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
|
||||
var finalizedState *stateTrie.BeaconState
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
finalizedState, err = s.stateGen.Resume(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
if !featureconfig.Get().SkipRegenHistoricalStates {
|
||||
// Since historical states were skipped, the node should start from last finalized check point.
|
||||
finalizedRoot = s.beaconDB.LastArchivedIndexRoot(ctx)
|
||||
if finalizedRoot == params.BeaconConfig().ZeroHash {
|
||||
finalizedRoot = bytesutil.ToBytes32(finalized.Root)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
finalizedState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(finalized.Root))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
finalizedState, err = s.stateGen.Resume(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
if !featureconfig.Get().SkipRegenHistoricalStates {
|
||||
// Since historical states were skipped, the node should start from last finalized check point.
|
||||
finalizedRoot = s.beaconDB.LastArchivedIndexRoot(ctx)
|
||||
if finalizedRoot == params.BeaconConfig().ZeroHash {
|
||||
finalizedRoot = bytesutil.ToBytes32(finalized.Root)
|
||||
}
|
||||
}
|
||||
|
||||
finalizedBlock, err := s.beaconDB.Block(ctx, finalizedRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized block from db")
|
||||
@@ -466,7 +440,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
// To skip the regeneration of historical state, the node has to generate the parent of the last finalized state.
|
||||
// We don't need to do this for genesis.
|
||||
atGenesis := s.CurrentSlot() == 0
|
||||
if featureconfig.Get().NewStateMgmt && featureconfig.Get().SkipRegenHistoricalStates && !atGenesis {
|
||||
if featureconfig.Get().SkipRegenHistoricalStates && !atGenesis {
|
||||
parentRoot := bytesutil.ToBytes32(finalizedBlock.Block.ParentRoot)
|
||||
parentState, err := s.generateState(ctx, finalizedRoot, parentRoot)
|
||||
if err != nil {
|
||||
|
||||
@@ -19,7 +19,6 @@ go_library(
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//proto/beacon/rpc/v1:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//log:go_default_library",
|
||||
"@com_github_gogo_protobuf//types:go_default_library",
|
||||
"@com_github_ipfs_go_log_v2//:go_default_library",
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -16,10 +15,6 @@ func (ds *Server) GetBeaconState(
|
||||
ctx context.Context,
|
||||
req *pbrpc.BeaconStateRequest,
|
||||
) (*pbrpc.SSZResponse, error) {
|
||||
if !featureconfig.Get().NewStateMgmt {
|
||||
return nil, status.Error(codes.FailedPrecondition, "Requires --enable-new-state-mgmt to function")
|
||||
}
|
||||
|
||||
switch q := req.QueryFilter.(type) {
|
||||
case *pbrpc.BeaconStateRequest_Slot:
|
||||
currentSlot := ds.GenesisTimeFetcher.CurrentSlot()
|
||||
|
||||
@@ -90,16 +90,9 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get historical head root: %v", err)
|
||||
}
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
headState, err = vs.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(headRoot))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get historical head state: %v", err)
|
||||
}
|
||||
} else {
|
||||
headState, err = vs.BeaconDB.State(ctx, bytesutil.ToBytes32(headRoot))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get historical head state: %v", err)
|
||||
}
|
||||
headState, err = vs.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(headRoot))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get historical head state: %v", err)
|
||||
}
|
||||
}
|
||||
if headState == nil {
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/trieutil"
|
||||
@@ -236,20 +235,10 @@ func (vs *Server) randomETH1DataVote(ctx context.Context) (*ethpb.Eth1Data, erro
|
||||
// computeStateRoot computes the state root after a block has been processed through a state transition and
|
||||
// returns it to the validator client.
|
||||
func (vs *Server) computeStateRoot(ctx context.Context, block *ethpb.SignedBeaconBlock) ([]byte, error) {
|
||||
var beaconState *stateTrie.BeaconState
|
||||
var err error
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
beaconState, err = vs.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(block.Block.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not retrieve beacon state")
|
||||
}
|
||||
} else {
|
||||
beaconState, err = vs.BeaconDB.State(ctx, bytesutil.ToBytes32(block.Block.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not retrieve beacon state")
|
||||
}
|
||||
beaconState, err := vs.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(block.Block.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not retrieve beacon state")
|
||||
}
|
||||
|
||||
root, err := state.CalculateStateRoot(
|
||||
ctx,
|
||||
beaconState,
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
@@ -111,38 +110,36 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
|
||||
if featureconfig.Get().NewStateMgmt {
|
||||
hasStateSummaryDB := s.db.HasStateSummary(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
hasStateSummaryCache := s.stateSummaryCache.Has(bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if !hasStateSummaryDB && !hasStateSummaryCache {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("No access to parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
parentState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not get parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
hasStateSummaryDB := s.db.HasStateSummary(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
hasStateSummaryCache := s.stateSummaryCache.Has(bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if !hasStateSummaryDB && !hasStateSummaryCache {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("No access to parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
parentState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not get parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
|
||||
if err := blocks.VerifyBlockSignature(parentState, blk); err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not verify block signature")
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
if err := blocks.VerifyBlockSignature(parentState, blk); err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not verify block signature")
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
parentState, err = state.ProcessSlots(context.Background(), parentState, blk.Block.Slot)
|
||||
if err != nil {
|
||||
log.Errorf("Could not advance slot to calculate proposer index: %v", err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
idx, err := helpers.BeaconProposerIndex(parentState)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not get proposer index using parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
if blk.Block.ProposerIndex != idx {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Incorrect proposer index")
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
parentState, err = state.ProcessSlots(context.Background(), parentState, blk.Block.Slot)
|
||||
if err != nil {
|
||||
log.Errorf("Could not advance slot to calculate proposer index: %v", err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
idx, err := helpers.BeaconProposerIndex(parentState)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not get proposer index using parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
if blk.Block.ProposerIndex != idx {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Incorrect proposer index")
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
msg.ValidatorData = blk // Used in downstream subscriber
|
||||
|
||||
Reference in New Issue
Block a user