mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-02-11 13:35:06 -05:00
hdiff restart-support: persist and validate exponents metadata
This commit is contained in:
@@ -7,9 +7,11 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/db/iface"
|
||||
"github.com/OffchainLabs/prysm/v7/cmd/beacon-chain/flags"
|
||||
"github.com/OffchainLabs/prysm/v7/config/features"
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
||||
@@ -223,6 +225,22 @@ func (kv *Store) startStateDiff(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if hasOffset {
|
||||
storedExponents, err := kv.loadStateDiffExponents()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "state-diff metadata missing or invalid; re-sync required")
|
||||
}
|
||||
currentExponents := flags.Get().StateDiffExponents
|
||||
if !slices.Equal(storedExponents, currentExponents) {
|
||||
return fmt.Errorf(
|
||||
"state-diff exponents changed; database incompatible. "+
|
||||
"Database was initialized with: %v. "+
|
||||
"Current configuration: %v. "+
|
||||
"Options: use original exponents (--state-diff-exponents=%s) or delete database and re-sync from genesis/checkpoint.",
|
||||
storedExponents,
|
||||
currentExponents,
|
||||
formatStateDiffExponents(storedExponents),
|
||||
)
|
||||
}
|
||||
// Existing state-diff database - restarts not yet supported.
|
||||
return errors.New("restarting with existing state-diff database not yet supported")
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
||||
statenative "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
|
||||
@@ -61,6 +62,38 @@ func decodeStateDiffExponents(encoded []byte) ([]int, error) {
|
||||
return exponents, nil
|
||||
}
|
||||
|
||||
func formatStateDiffExponents(exponents []int) string {
|
||||
if len(exponents) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(exponents))
|
||||
for i, exp := range exponents {
|
||||
parts[i] = fmt.Sprintf("%d", exp)
|
||||
}
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func (s *Store) loadStateDiffExponents() ([]int, error) {
|
||||
var encoded []byte
|
||||
err := s.db.View(func(tx *bbolt.Tx) error {
|
||||
bucket := tx.Bucket(stateDiffBucket)
|
||||
if bucket == nil {
|
||||
return bbolt.ErrBucketNotFound
|
||||
}
|
||||
value := bucket.Get(exponentsKey)
|
||||
if value == nil {
|
||||
return errors.New("state diff exponents not found")
|
||||
}
|
||||
encoded = make([]byte, len(value))
|
||||
copy(encoded, value)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return decodeStateDiffExponents(encoded)
|
||||
}
|
||||
|
||||
func makeKeyForStateDiffTree(level int, slot uint64) []byte {
|
||||
buf := make([]byte, 16)
|
||||
buf[0] = byte(level)
|
||||
@@ -190,8 +223,13 @@ func (s *Store) initializeStateDiff(slot primitives.Slot, initialState state.Rea
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// Write offset directly to the database (without using cache which doesn't exist yet).
|
||||
err := s.db.Update(func(tx *bbolt.Tx) error {
|
||||
exponentsBytes, err := encodeStateDiffExponents(flags.Get().StateDiffExponents)
|
||||
if err != nil {
|
||||
return pkgerrors.Wrap(err, "failed to encode state diff exponents")
|
||||
}
|
||||
|
||||
// Write metadata directly to the database (without using cache which doesn't exist yet).
|
||||
err = s.db.Update(func(tx *bbolt.Tx) error {
|
||||
bucket := tx.Bucket(stateDiffBucket)
|
||||
if bucket == nil {
|
||||
return bbolt.ErrBucketNotFound
|
||||
@@ -199,7 +237,10 @@ func (s *Store) initializeStateDiff(slot primitives.Slot, initialState state.Rea
|
||||
|
||||
offsetBytes := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(offsetBytes, uint64(slot))
|
||||
return bucket.Put(offsetKey, offsetBytes)
|
||||
if err := bucket.Put(offsetKey, offsetBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
return bucket.Put(exponentsKey, exponentsBytes)
|
||||
})
|
||||
if err != nil {
|
||||
return pkgerrors.Wrap(err, "failed to set offset")
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
||||
"github.com/OffchainLabs/prysm/v7/cmd/beacon-chain/flags"
|
||||
"github.com/OffchainLabs/prysm/v7/config/features"
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v7/math"
|
||||
@@ -75,6 +76,26 @@ func TestStateDiff_EncodeDecodeExponents(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestStateDiff_InitializeStoresExponents(t *testing.T) {
|
||||
setDefaultStateDiffExponents()
|
||||
resetCfg := features.InitWithReset(&features.Flags{EnableStateDiff: true})
|
||||
defer resetCfg()
|
||||
|
||||
db := setupDB(t)
|
||||
st, _ := createState(t, 0, version.Phase0)
|
||||
require.NoError(t, db.initializeStateDiff(0, st))
|
||||
|
||||
stored, err := db.loadStateDiffExponents()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, flags.Get().StateDiffExponents, stored)
|
||||
}
|
||||
|
||||
func TestStateDiff_LoadExponentsMissing(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
_, err := db.loadStateDiffExponents()
|
||||
require.ErrorContains(t, "exponents not found", err)
|
||||
}
|
||||
|
||||
func TestStateDiff_ComputeLevel(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
setDefaultStateDiffExponents()
|
||||
|
||||
Reference in New Issue
Block a user