mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 07:28:06 -05:00
Save LC Bootstrap DB Space Optimization (#14775)
* add db optimization altair * add db optimization * add tests * fix tests * fix changelog * remove debug code * remove unused code * fix comment * remove unused code
This commit is contained in:
@@ -18,6 +18,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
|
|||||||
- Add field param placeholder for Electra blob target and max to pass spec tests.
|
- Add field param placeholder for Electra blob target and max to pass spec tests.
|
||||||
- Add EIP-7691: Blob throughput increase.
|
- Add EIP-7691: Blob throughput increase.
|
||||||
- SSZ files generation: Remove the `// Hash: ...` header.
|
- SSZ files generation: Remove the `// Hash: ...` header.
|
||||||
|
- DB optimization for saving light client bootstraps (save unique sync committees only).
|
||||||
- Trace IDONTWANT Messages in Pubsub.
|
- Trace IDONTWANT Messages in Pubsub.
|
||||||
- Add Fulu fork boilerplate.
|
- Add Fulu fork boilerplate.
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ go_library(
|
|||||||
"//beacon-chain/state/genesis:go_default_library",
|
"//beacon-chain/state/genesis:go_default_library",
|
||||||
"//beacon-chain/state/state-native:go_default_library",
|
"//beacon-chain/state/state-native:go_default_library",
|
||||||
"//config/features:go_default_library",
|
"//config/features:go_default_library",
|
||||||
|
"//config/fieldparams:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
"//consensus-types/blocks:go_default_library",
|
"//consensus-types/blocks:go_default_library",
|
||||||
"//consensus-types/interfaces:go_default_library",
|
"//consensus-types/interfaces:go_default_library",
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ var Buckets = [][]byte{
|
|||||||
stateValidatorsBucket,
|
stateValidatorsBucket,
|
||||||
lightClientUpdatesBucket,
|
lightClientUpdatesBucket,
|
||||||
lightClientBootstrapBucket,
|
lightClientBootstrapBucket,
|
||||||
|
lightClientSyncCommitteeBucket,
|
||||||
// Indices buckets.
|
// Indices buckets.
|
||||||
blockSlotIndicesBucket,
|
blockSlotIndicesBucket,
|
||||||
stateSlotIndicesBucket,
|
stateSlotIndicesBucket,
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
|
|
||||||
"github.com/golang/snappy"
|
"github.com/golang/snappy"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||||
light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client"
|
light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client"
|
||||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||||
@@ -35,9 +37,35 @@ func (s *Store) SaveLightClientBootstrap(ctx context.Context, blockRoot []byte,
|
|||||||
_, span := trace.StartSpan(ctx, "BeaconDB.SaveLightClientBootstrap")
|
_, span := trace.StartSpan(ctx, "BeaconDB.SaveLightClientBootstrap")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
|
bootstrapCopy, err := light_client.NewWrappedBootstrap(proto.Clone(bootstrap.Proto()))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not clone light client bootstrap")
|
||||||
|
}
|
||||||
|
syncCommitteeHash, err := bootstrapCopy.CurrentSyncCommittee().HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not hash current sync committee")
|
||||||
|
}
|
||||||
|
|
||||||
return s.db.Update(func(tx *bolt.Tx) error {
|
return s.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
syncCommitteeBucket := tx.Bucket(lightClientSyncCommitteeBucket)
|
||||||
|
syncCommitteeAlreadyExists := syncCommitteeBucket.Get(syncCommitteeHash[:]) != nil
|
||||||
|
if !syncCommitteeAlreadyExists {
|
||||||
|
enc, err := bootstrapCopy.CurrentSyncCommittee().MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not marshal current sync committee")
|
||||||
|
}
|
||||||
|
if err := syncCommitteeBucket.Put(syncCommitteeHash[:], enc); err != nil {
|
||||||
|
return errors.Wrap(err, "could not save current sync committee")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bootstrapCopy.SetCurrentSyncCommittee(createEmptySyncCommittee())
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not set current sync committee to zero while saving")
|
||||||
|
}
|
||||||
|
|
||||||
bkt := tx.Bucket(lightClientBootstrapBucket)
|
bkt := tx.Bucket(lightClientBootstrapBucket)
|
||||||
enc, err := encodeLightClientBootstrap(bootstrap)
|
enc, err := encodeLightClientBootstrap(bootstrapCopy, syncCommitteeHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -50,20 +78,49 @@ func (s *Store) LightClientBootstrap(ctx context.Context, blockRoot []byte) (int
|
|||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
var bootstrap interfaces.LightClientBootstrap
|
var bootstrap interfaces.LightClientBootstrap
|
||||||
|
var syncCommitteeHash []byte
|
||||||
err := s.db.View(func(tx *bolt.Tx) error {
|
err := s.db.View(func(tx *bolt.Tx) error {
|
||||||
bkt := tx.Bucket(lightClientBootstrapBucket)
|
bkt := tx.Bucket(lightClientBootstrapBucket)
|
||||||
|
syncCommitteeBucket := tx.Bucket(lightClientSyncCommitteeBucket)
|
||||||
enc := bkt.Get(blockRoot)
|
enc := bkt.Get(blockRoot)
|
||||||
if enc == nil {
|
if enc == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
bootstrap, err = decodeLightClientBootstrap(enc)
|
bootstrap, syncCommitteeHash, err = decodeLightClientBootstrap(enc)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not decode light client bootstrap")
|
||||||
|
}
|
||||||
|
var syncCommitteeBytes = syncCommitteeBucket.Get(syncCommitteeHash)
|
||||||
|
if syncCommitteeBytes == nil {
|
||||||
|
return errors.New("sync committee not found")
|
||||||
|
}
|
||||||
|
syncCommittee := ðpb.SyncCommittee{}
|
||||||
|
if err := syncCommittee.UnmarshalSSZ(syncCommitteeBytes); err != nil {
|
||||||
|
return errors.Wrap(err, "could not unmarshal sync committee")
|
||||||
|
}
|
||||||
|
err = bootstrap.SetCurrentSyncCommittee(syncCommittee)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not set current sync committee while retrieving")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
return bootstrap, err
|
return bootstrap, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeLightClientBootstrap(bootstrap interfaces.LightClientBootstrap) ([]byte, error) {
|
func createEmptySyncCommittee() *ethpb.SyncCommittee {
|
||||||
|
syncCom := make([][]byte, params.BeaconConfig().SyncCommitteeSize)
|
||||||
|
for i := 0; uint64(i) < params.BeaconConfig().SyncCommitteeSize; i++ {
|
||||||
|
syncCom[i] = make([]byte, fieldparams.BLSPubkeyLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ðpb.SyncCommittee{
|
||||||
|
Pubkeys: syncCom,
|
||||||
|
AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeLightClientBootstrap(bootstrap interfaces.LightClientBootstrap, syncCommitteeHash [32]byte) ([]byte, error) {
|
||||||
key, err := keyForLightClientUpdate(bootstrap.Version())
|
key, err := keyForLightClientUpdate(bootstrap.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -72,48 +129,56 @@ func encodeLightClientBootstrap(bootstrap interfaces.LightClientBootstrap) ([]by
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not marshal light client bootstrap")
|
return nil, errors.Wrap(err, "could not marshal light client bootstrap")
|
||||||
}
|
}
|
||||||
fullEnc := make([]byte, len(key)+len(enc))
|
fullEnc := make([]byte, len(key)+32+len(enc))
|
||||||
copy(fullEnc, key)
|
copy(fullEnc, key)
|
||||||
copy(fullEnc[len(key):], enc)
|
copy(fullEnc[len(key):len(key)+32], syncCommitteeHash[:])
|
||||||
return snappy.Encode(nil, fullEnc), nil
|
copy(fullEnc[len(key)+32:], enc)
|
||||||
|
compressedEnc := snappy.Encode(nil, fullEnc)
|
||||||
|
return compressedEnc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeLightClientBootstrap(enc []byte) (interfaces.LightClientBootstrap, error) {
|
func decodeLightClientBootstrap(enc []byte) (interfaces.LightClientBootstrap, []byte, error) {
|
||||||
var err error
|
var err error
|
||||||
enc, err = snappy.Decode(nil, enc)
|
enc, err = snappy.Decode(nil, enc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not snappy decode light client bootstrap")
|
return nil, nil, errors.Wrap(err, "could not snappy decode light client bootstrap")
|
||||||
}
|
}
|
||||||
var m proto.Message
|
var m proto.Message
|
||||||
|
var syncCommitteeHash []byte
|
||||||
switch {
|
switch {
|
||||||
case hasAltairKey(enc):
|
case hasAltairKey(enc):
|
||||||
bootstrap := ðpb.LightClientBootstrapAltair{}
|
bootstrap := ðpb.LightClientBootstrapAltair{}
|
||||||
if err := bootstrap.UnmarshalSSZ(enc[len(altairKey):]); err != nil {
|
if err := bootstrap.UnmarshalSSZ(enc[len(altairKey)+32:]); err != nil {
|
||||||
return nil, errors.Wrap(err, "could not unmarshal Altair light client bootstrap")
|
return nil, nil, errors.Wrap(err, "could not unmarshal Altair light client bootstrap")
|
||||||
}
|
}
|
||||||
m = bootstrap
|
m = bootstrap
|
||||||
|
syncCommitteeHash = enc[len(altairKey) : len(altairKey)+32]
|
||||||
case hasCapellaKey(enc):
|
case hasCapellaKey(enc):
|
||||||
bootstrap := ðpb.LightClientBootstrapCapella{}
|
bootstrap := ðpb.LightClientBootstrapCapella{}
|
||||||
if err := bootstrap.UnmarshalSSZ(enc[len(capellaKey):]); err != nil {
|
if err := bootstrap.UnmarshalSSZ(enc[len(capellaKey)+32:]); err != nil {
|
||||||
return nil, errors.Wrap(err, "could not unmarshal Capella light client bootstrap")
|
return nil, nil, errors.Wrap(err, "could not unmarshal Capella light client bootstrap")
|
||||||
}
|
}
|
||||||
m = bootstrap
|
m = bootstrap
|
||||||
|
syncCommitteeHash = enc[len(capellaKey) : len(capellaKey)+32]
|
||||||
case hasDenebKey(enc):
|
case hasDenebKey(enc):
|
||||||
bootstrap := ðpb.LightClientBootstrapDeneb{}
|
bootstrap := ðpb.LightClientBootstrapDeneb{}
|
||||||
if err := bootstrap.UnmarshalSSZ(enc[len(denebKey):]); err != nil {
|
if err := bootstrap.UnmarshalSSZ(enc[len(denebKey)+32:]); err != nil {
|
||||||
return nil, errors.Wrap(err, "could not unmarshal Deneb light client bootstrap")
|
return nil, nil, errors.Wrap(err, "could not unmarshal Deneb light client bootstrap")
|
||||||
}
|
}
|
||||||
m = bootstrap
|
m = bootstrap
|
||||||
|
syncCommitteeHash = enc[len(denebKey) : len(denebKey)+32]
|
||||||
case hasElectraKey(enc):
|
case hasElectraKey(enc):
|
||||||
bootstrap := ðpb.LightClientBootstrapElectra{}
|
bootstrap := ðpb.LightClientBootstrapElectra{}
|
||||||
if err := bootstrap.UnmarshalSSZ(enc[len(electraKey):]); err != nil {
|
if err := bootstrap.UnmarshalSSZ(enc[len(electraKey)+32:]); err != nil {
|
||||||
return nil, errors.Wrap(err, "could not unmarshal Electra light client bootstrap")
|
return nil, nil, errors.Wrap(err, "could not unmarshal Electra light client bootstrap")
|
||||||
}
|
}
|
||||||
m = bootstrap
|
m = bootstrap
|
||||||
|
syncCommitteeHash = enc[len(electraKey) : len(electraKey)+32]
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("decoding of saved light client bootstrap is unsupported")
|
return nil, nil, errors.New("decoding of saved light client bootstrap is unsupported")
|
||||||
}
|
}
|
||||||
return light_client.NewWrappedBootstrap(m)
|
bootstrap, err := light_client.NewWrappedBootstrap(m)
|
||||||
|
return bootstrap, syncCommitteeHash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) LightClientUpdates(ctx context.Context, startPeriod, endPeriod uint64) (map[uint64]interfaces.LightClientUpdate, error) {
|
func (s *Store) LightClientUpdates(ctx context.Context, startPeriod, endPeriod uint64) (map[uint64]interfaces.LightClientUpdate, error) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -611,7 +612,13 @@ func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) {
|
|||||||
|
|
||||||
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair"))
|
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.DeepEqual(t, bootstrap, retrievedBootstrap, "retrieved bootstrap does not match saved bootstrap")
|
require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header")
|
||||||
|
require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee")
|
||||||
|
savedBranch, err := bootstrap.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Capella", func(t *testing.T) {
|
t.Run("Capella", func(t *testing.T) {
|
||||||
@@ -626,7 +633,13 @@ func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) {
|
|||||||
|
|
||||||
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootCapella"))
|
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootCapella"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.DeepEqual(t, bootstrap, retrievedBootstrap, "retrieved bootstrap does not match saved bootstrap")
|
require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header")
|
||||||
|
require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee")
|
||||||
|
savedBranch, err := bootstrap.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Deneb", func(t *testing.T) {
|
t.Run("Deneb", func(t *testing.T) {
|
||||||
@@ -641,7 +654,13 @@ func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) {
|
|||||||
|
|
||||||
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootDeneb"))
|
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootDeneb"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.DeepEqual(t, bootstrap, retrievedBootstrap, "retrieved bootstrap does not match saved bootstrap")
|
require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header")
|
||||||
|
require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee")
|
||||||
|
savedBranch, err := bootstrap.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Electra", func(t *testing.T) {
|
t.Run("Electra", func(t *testing.T) {
|
||||||
@@ -656,10 +675,138 @@ func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) {
|
|||||||
|
|
||||||
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootElectra"))
|
retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootElectra"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.DeepEqual(t, bootstrap, retrievedBootstrap, "retrieved bootstrap does not match saved bootstrap")
|
require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header")
|
||||||
|
require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee")
|
||||||
|
savedBranch, err := bootstrap.CurrentSyncCommitteeBranchElectra()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranchElectra()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStore_LightClientBootstrap_MultipleBootstrapsWithSameSyncCommittee(t *testing.T) {
|
||||||
|
params.SetupTestConfigCleanup(t)
|
||||||
|
cfg := params.BeaconConfig()
|
||||||
|
cfg.AltairForkEpoch = 0
|
||||||
|
cfg.CapellaForkEpoch = 1
|
||||||
|
cfg.DenebForkEpoch = 2
|
||||||
|
cfg.ElectraForkEpoch = 3
|
||||||
|
cfg.EpochsPerSyncCommitteePeriod = 1
|
||||||
|
params.OverrideBeaconConfig(cfg)
|
||||||
|
|
||||||
|
db := setupDB(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
bootstrap1, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
bootstrap2, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
randomSyncCommittee := createRandomSyncCommittee()
|
||||||
|
|
||||||
|
err = bootstrap1.SetCurrentSyncCommittee(randomSyncCommittee)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = bootstrap2.SetCurrentSyncCommittee(randomSyncCommittee)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair1"), bootstrap1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair2"), bootstrap2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
retrievedBootstrap1, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair1"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBootstrap2, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair2"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.DeepEqual(t, bootstrap1.Header(), retrievedBootstrap1.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header")
|
||||||
|
require.DeepEqual(t, randomSyncCommittee, retrievedBootstrap1.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee")
|
||||||
|
savedBranch, err := bootstrap1.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch, err := retrievedBootstrap1.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch")
|
||||||
|
|
||||||
|
require.DeepEqual(t, bootstrap2.Header(), retrievedBootstrap2.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header")
|
||||||
|
require.DeepEqual(t, randomSyncCommittee, retrievedBootstrap2.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee")
|
||||||
|
savedBranch2, err := bootstrap2.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch2, err := retrievedBootstrap2.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch2, retrievedBranch2, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch")
|
||||||
|
|
||||||
|
// Ensure that the sync committee is only stored once
|
||||||
|
err = db.db.View(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket(lightClientSyncCommitteeBucket)
|
||||||
|
require.NotNil(t, bucket)
|
||||||
|
count := bucket.Stats().KeyN
|
||||||
|
require.Equal(t, 1, count)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStore_LightClientBootstrap_MultipleBootstrapsWithDifferentSyncCommittees(t *testing.T) {
|
||||||
|
params.SetupTestConfigCleanup(t)
|
||||||
|
cfg := params.BeaconConfig()
|
||||||
|
cfg.AltairForkEpoch = 0
|
||||||
|
cfg.CapellaForkEpoch = 1
|
||||||
|
cfg.DenebForkEpoch = 2
|
||||||
|
cfg.ElectraForkEpoch = 3
|
||||||
|
cfg.EpochsPerSyncCommitteePeriod = 1
|
||||||
|
params.OverrideBeaconConfig(cfg)
|
||||||
|
|
||||||
|
db := setupDB(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
bootstrap1, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
bootstrap2, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = bootstrap1.SetCurrentSyncCommittee(createRandomSyncCommittee())
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = bootstrap2.SetCurrentSyncCommittee(createRandomSyncCommittee())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair1"), bootstrap1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair2"), bootstrap2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
retrievedBootstrap1, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair1"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBootstrap2, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair2"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.DeepEqual(t, bootstrap1.Header(), retrievedBootstrap1.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header")
|
||||||
|
require.DeepEqual(t, bootstrap1.CurrentSyncCommittee(), retrievedBootstrap1.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee")
|
||||||
|
savedBranch, err := bootstrap1.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch, err := retrievedBootstrap1.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch")
|
||||||
|
|
||||||
|
require.DeepEqual(t, bootstrap2.Header(), retrievedBootstrap2.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header")
|
||||||
|
require.DeepEqual(t, bootstrap2.CurrentSyncCommittee(), retrievedBootstrap2.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee")
|
||||||
|
savedBranch2, err := bootstrap2.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
retrievedBranch2, err := retrievedBootstrap2.CurrentSyncCommitteeBranch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.DeepEqual(t, savedBranch2, retrievedBranch2, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch")
|
||||||
|
|
||||||
|
// Ensure that the sync committee is stored twice
|
||||||
|
err = db.db.View(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket(lightClientSyncCommitteeBucket)
|
||||||
|
require.NotNil(t, bucket)
|
||||||
|
count := bucket.Stats().KeyN
|
||||||
|
require.Equal(t, 2, count)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces.LightClientBootstrap, error) {
|
func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces.LightClientBootstrap, error) {
|
||||||
currentEpoch := slots.ToEpoch(currentSlot)
|
currentEpoch := slots.ToEpoch(currentSlot)
|
||||||
syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize
|
syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ var (
|
|||||||
registrationBucket = []byte("registration")
|
registrationBucket = []byte("registration")
|
||||||
|
|
||||||
// Light Client Updates Bucket
|
// Light Client Updates Bucket
|
||||||
lightClientUpdatesBucket = []byte("light-client-updates")
|
lightClientUpdatesBucket = []byte("light-client-updates")
|
||||||
lightClientBootstrapBucket = []byte("light-client-bootstrap")
|
lightClientBootstrapBucket = []byte("light-client-bootstrap")
|
||||||
|
lightClientSyncCommitteeBucket = []byte("light-client-sync-committee")
|
||||||
|
|
||||||
// Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations.
|
// Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations.
|
||||||
slotsHasObjectBucket = []byte("slots-has-objects")
|
slotsHasObjectBucket = []byte("slots-has-objects")
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type LightClientHeader interface {
|
|||||||
type LightClientBootstrap interface {
|
type LightClientBootstrap interface {
|
||||||
ssz.Marshaler
|
ssz.Marshaler
|
||||||
Version() int
|
Version() int
|
||||||
|
Proto() proto.Message
|
||||||
Header() LightClientHeader
|
Header() LightClientHeader
|
||||||
SetHeader(header LightClientHeader) error
|
SetHeader(header LightClientHeader) error
|
||||||
CurrentSyncCommittee() *pb.SyncCommittee
|
CurrentSyncCommittee() *pb.SyncCommittee
|
||||||
|
|||||||
@@ -86,6 +86,10 @@ func (h *bootstrapAltair) Version() int {
|
|||||||
return version.Altair
|
return version.Altair
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *bootstrapAltair) Proto() proto.Message {
|
||||||
|
return h.p
|
||||||
|
}
|
||||||
|
|
||||||
func (h *bootstrapAltair) Header() interfaces.LightClientHeader {
|
func (h *bootstrapAltair) Header() interfaces.LightClientHeader {
|
||||||
return h.header
|
return h.header
|
||||||
}
|
}
|
||||||
@@ -187,6 +191,10 @@ func (h *bootstrapCapella) Version() int {
|
|||||||
return version.Capella
|
return version.Capella
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *bootstrapCapella) Proto() proto.Message {
|
||||||
|
return h.p
|
||||||
|
}
|
||||||
|
|
||||||
func (h *bootstrapCapella) Header() interfaces.LightClientHeader {
|
func (h *bootstrapCapella) Header() interfaces.LightClientHeader {
|
||||||
return h.header
|
return h.header
|
||||||
}
|
}
|
||||||
@@ -288,6 +296,10 @@ func (h *bootstrapDeneb) Version() int {
|
|||||||
return version.Deneb
|
return version.Deneb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *bootstrapDeneb) Proto() proto.Message {
|
||||||
|
return h.p
|
||||||
|
}
|
||||||
|
|
||||||
func (h *bootstrapDeneb) Header() interfaces.LightClientHeader {
|
func (h *bootstrapDeneb) Header() interfaces.LightClientHeader {
|
||||||
return h.header
|
return h.header
|
||||||
}
|
}
|
||||||
@@ -389,6 +401,10 @@ func (h *bootstrapElectra) Version() int {
|
|||||||
return version.Electra
|
return version.Electra
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *bootstrapElectra) Proto() proto.Message {
|
||||||
|
return h.p
|
||||||
|
}
|
||||||
|
|
||||||
func (h *bootstrapElectra) Header() interfaces.LightClientHeader {
|
func (h *bootstrapElectra) Header() interfaces.LightClientHeader {
|
||||||
return h.header
|
return h.header
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user