mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 21:08:10 -05:00
Integrate state-diff into HasState() (#16045)
**What type of PR is this?** Feature **What does this PR do? Why is it needed?** This PR adds integrates state-diff into `HasState()`. One thing to note: we are assuming that, for a given block root, that has either a state summary or a block in db, and also falls in the state diff tree, then there must exist a state. This function could return true, even when there is no actual state saved due to any error. But this is fine, because we have that assumption throughout the whole state diff feature.
This commit is contained in:
@@ -142,6 +142,7 @@ go_test(
|
||||
"@com_github_golang_snappy//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
"@io_etcd_go_bbolt//:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
|
||||
@@ -427,6 +427,16 @@ func (s *Store) storeValidatorEntriesSeparately(ctx context.Context, tx *bolt.Tx
|
||||
func (s *Store) HasState(ctx context.Context, blockRoot [32]byte) bool {
|
||||
_, span := trace.StartSpan(ctx, "BeaconDB.HasState")
|
||||
defer span.End()
|
||||
|
||||
if features.Get().EnableStateDiff {
|
||||
hasState, err := s.hasStateUsingStateDiff(ctx, blockRoot)
|
||||
if err != nil {
|
||||
log.WithError(err).Error(fmt.Sprintf("error checking state existence using state-diff"))
|
||||
return false
|
||||
}
|
||||
return hasState
|
||||
}
|
||||
|
||||
hasState := false
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(stateBucket)
|
||||
@@ -1053,3 +1063,13 @@ func (s *Store) getStateUsingStateDiff(ctx context.Context, blockRoot [32]byte)
|
||||
|
||||
return st, nil
|
||||
}
|
||||
|
||||
func (s *Store) hasStateUsingStateDiff(ctx context.Context, blockRoot [32]byte) (bool, error) {
|
||||
slot, err := s.SlotByBlockRoot(ctx, blockRoot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
stateLvl := computeLevel(s.getOffset(), slot)
|
||||
return stateLvl != -1, nil
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v7/testing/assert"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/require"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/util"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
@@ -1573,3 +1574,57 @@ func TestStore_CanSaveRetrieveStateUsingStateDiff(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_HasStateUsingStateDiff(t *testing.T) {
|
||||
t.Run("No state summary or block", func(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
db := setupDB(t)
|
||||
featCfg := &features.Flags{}
|
||||
featCfg.EnableStateDiff = true
|
||||
reset := features.InitWithReset(featCfg)
|
||||
defer reset()
|
||||
setDefaultStateDiffExponents()
|
||||
|
||||
err := setOffsetInDB(db, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
hasSt := db.HasState(t.Context(), [32]byte{'A'})
|
||||
require.Equal(t, false, hasSt)
|
||||
require.LogsContain(t, hook, "neither state summary nor block found")
|
||||
})
|
||||
|
||||
t.Run("slot in tree or not", func(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
featCfg := &features.Flags{}
|
||||
featCfg.EnableStateDiff = true
|
||||
reset := features.InitWithReset(featCfg)
|
||||
defer reset()
|
||||
setDefaultStateDiffExponents()
|
||||
|
||||
err := setOffsetInDB(db, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
slot primitives.Slot
|
||||
expected bool
|
||||
}{
|
||||
{slot: 1, expected: false}, // slot 1 not in tree
|
||||
{slot: 32, expected: true}, // slot 32 in tree
|
||||
{slot: 0, expected: true}, // slot 0 in tree
|
||||
{slot: primitives.Slot(math.PowerOf2(21)), expected: true}, // slot in tree
|
||||
{slot: primitives.Slot(math.PowerOf2(21) - 1), expected: false}, // slot not in tree
|
||||
{slot: primitives.Slot(math.PowerOf2(22)), expected: true}, // slot in tree
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
r := bytesutil.ToBytes32([]byte{'A'})
|
||||
ss := ðpb.StateSummary{Slot: tc.slot, Root: r[:]}
|
||||
err = db.SaveStateSummary(t.Context(), ss)
|
||||
require.NoError(t, err)
|
||||
|
||||
hasSt := db.HasState(t.Context(), r)
|
||||
require.Equal(t, tc.expected, hasSt)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
3
changelog/bastin_has-state-using-diff.md
Normal file
3
changelog/bastin_has-state-using-diff.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Integrate state-diff into `HasState()`.
|
||||
Reference in New Issue
Block a user