Reorganize processing of light client updates (#15383)

* Reorganize processing of light client updates

* changelog <3
This commit is contained in:
Radosław Kapka
2025-06-09 19:08:23 +02:00
committed by GitHub
parent 4095da8568
commit f5a9394c77
4 changed files with 49 additions and 52 deletions

View File

@@ -72,8 +72,6 @@ func (s *Service) postBlockProcess(cfg *postBlockProcessConfig) error {
} }
if features.Get().EnableLightClient && slots.ToEpoch(s.CurrentSlot()) >= params.BeaconConfig().AltairForkEpoch { if features.Get().EnableLightClient && slots.ToEpoch(s.CurrentSlot()) >= params.BeaconConfig().AltairForkEpoch {
defer s.processLightClientUpdates(cfg) defer s.processLightClientUpdates(cfg)
defer s.saveLightClientUpdate(cfg)
defer s.saveLightClientBootstrap(cfg)
} }
defer s.sendStateFeedOnBlock(cfg) defer s.sendStateFeedOnBlock(cfg)
defer reportProcessingTime(startTime) defer reportProcessingTime(startTime)

View File

@@ -131,6 +131,12 @@ func (s *Service) sendStateFeedOnBlock(cfg *postBlockProcessConfig) {
} }
func (s *Service) processLightClientUpdates(cfg *postBlockProcessConfig) { func (s *Service) processLightClientUpdates(cfg *postBlockProcessConfig) {
if err := s.processLightClientUpdate(cfg); err != nil {
log.WithError(err).Error("Failed to process light client update")
}
if err := s.processLightClientBootstrap(cfg); err != nil {
log.WithError(err).Error("Failed to process light client bootstrap")
}
if err := s.processLightClientOptimisticUpdate(cfg.ctx, cfg.roblock, cfg.postState); err != nil { if err := s.processLightClientOptimisticUpdate(cfg.ctx, cfg.roblock, cfg.postState); err != nil {
log.WithError(err).Error("Failed to process light client optimistic update") log.WithError(err).Error("Failed to process light client optimistic update")
} }
@@ -139,38 +145,33 @@ func (s *Service) processLightClientUpdates(cfg *postBlockProcessConfig) {
} }
} }
// saveLightClientUpdate saves the light client update for this block // processLightClientUpdate saves the light client update for this block
// if it's better than the already saved one, when feature flag is enabled. // if it's better than the already saved one, when feature flag is enabled.
func (s *Service) saveLightClientUpdate(cfg *postBlockProcessConfig) { func (s *Service) processLightClientUpdate(cfg *postBlockProcessConfig) error {
attestedRoot := cfg.roblock.Block().ParentRoot() attestedRoot := cfg.roblock.Block().ParentRoot()
attestedBlock, err := s.getBlock(cfg.ctx, attestedRoot) attestedBlock, err := s.getBlock(cfg.ctx, attestedRoot)
if err != nil { if err != nil {
log.WithError(err).Errorf("Saving light client update failed: Could not get attested block for root %#x", attestedRoot) return errors.Wrapf(err, "could not get attested block for root %#x", attestedRoot)
return
} }
if attestedBlock == nil || attestedBlock.IsNil() { if attestedBlock == nil || attestedBlock.IsNil() {
log.Error("Saving light client update failed: Attested block is nil") return errors.New("attested block is nil")
return
} }
attestedState, err := s.cfg.StateGen.StateByRoot(cfg.ctx, attestedRoot) attestedState, err := s.cfg.StateGen.StateByRoot(cfg.ctx, attestedRoot)
if err != nil { if err != nil {
log.WithError(err).Errorf("Saving light client update failed: Could not get attested state for root %#x", attestedRoot) return errors.Wrapf(err, "could not get attested state for root %#x", attestedRoot)
return
} }
if attestedState == nil || attestedState.IsNil() { if attestedState == nil || attestedState.IsNil() {
log.Error("Saving light client update failed: Attested state is nil") return errors.New("attested state is nil")
return
} }
finalizedRoot := attestedState.FinalizedCheckpoint().Root finalizedRoot := attestedState.FinalizedCheckpoint().Root
finalizedBlock, err := s.getBlock(cfg.ctx, [32]byte(finalizedRoot)) finalizedBlock, err := s.getBlock(cfg.ctx, [32]byte(finalizedRoot))
if err != nil { if err != nil {
if errors.Is(err, errBlockNotFoundInCacheOrDB) { if errors.Is(err, errBlockNotFoundInCacheOrDB) {
log.Debugf("Skipping saving light client update: Finalized block is nil for root %#x", finalizedRoot) log.Debugf("Skipping saving light client update because finalized block is nil for root %#x", finalizedRoot)
} else { return nil
log.WithError(err).Errorf("Saving light client update failed: Could not get finalized block for root %#x", finalizedRoot)
} }
return return errors.Wrapf(err, "could not get finalized block for root %#x", finalizedRoot)
} }
update, err := lightclient.NewLightClientUpdateFromBeaconState( update, err := lightclient.NewLightClientUpdateFromBeaconState(
@@ -183,57 +184,52 @@ func (s *Service) saveLightClientUpdate(cfg *postBlockProcessConfig) {
finalizedBlock, finalizedBlock,
) )
if err != nil { if err != nil {
log.WithError(err).Error("Saving light client update failed: Could not create light client update") return errors.Wrapf(err, "could not create light client update")
return
} }
period := slots.SyncCommitteePeriod(slots.ToEpoch(attestedState.Slot())) period := slots.SyncCommitteePeriod(slots.ToEpoch(attestedState.Slot()))
oldUpdate, err := s.cfg.BeaconDB.LightClientUpdate(cfg.ctx, period) oldUpdate, err := s.cfg.BeaconDB.LightClientUpdate(cfg.ctx, period)
if err != nil { if err != nil {
log.WithError(err).Error("Saving light client update failed: Could not get current light client update") return errors.Wrapf(err, "could not get current light client update")
return
} }
if oldUpdate == nil { if oldUpdate == nil {
if err := s.cfg.BeaconDB.SaveLightClientUpdate(cfg.ctx, period, update); err != nil { if err := s.cfg.BeaconDB.SaveLightClientUpdate(cfg.ctx, period, update); err != nil {
log.WithError(err).Error("Saving light client update failed: Could not save light client update") return errors.Wrapf(err, "could not save light client update")
} else {
log.WithField("period", period).Debug("Saving light client update: Saved new update")
} }
return log.WithField("period", period).Debug("Saved new light client update")
return nil
} }
isNewUpdateBetter, err := lightclient.IsBetterUpdate(update, oldUpdate) isNewUpdateBetter, err := lightclient.IsBetterUpdate(update, oldUpdate)
if err != nil { if err != nil {
log.WithError(err).Error("Saving light client update failed: Could not compare light client updates") return errors.Wrapf(err, "could not compare light client updates")
return
} }
if isNewUpdateBetter { if isNewUpdateBetter {
if err := s.cfg.BeaconDB.SaveLightClientUpdate(cfg.ctx, period, update); err != nil { if err := s.cfg.BeaconDB.SaveLightClientUpdate(cfg.ctx, period, update); err != nil {
log.WithError(err).Error("Saving light client update failed: Could not save light client update") return errors.Wrapf(err, "could not save light client update")
} else {
log.WithField("period", period).Debug("Saving light client update: Saved new update")
} }
} else { log.WithField("period", period).Debug("Saved new light client update")
log.WithField("period", period).Debug("Saving light client update: New update is not better than the current one. Skipping save.") return nil
} }
log.WithField("period", period).Debug("New light client update is not better than the current one, skipping save")
return nil
} }
// saveLightClientBootstrap saves a light client bootstrap for this block // processLightClientBootstrap saves a light client bootstrap for this block
// when feature flag is enabled. // when feature flag is enabled.
func (s *Service) saveLightClientBootstrap(cfg *postBlockProcessConfig) { func (s *Service) processLightClientBootstrap(cfg *postBlockProcessConfig) error {
blockRoot := cfg.roblock.Root() blockRoot := cfg.roblock.Root()
bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(cfg.ctx, s.CurrentSlot(), cfg.postState, cfg.roblock) bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(cfg.ctx, s.CurrentSlot(), cfg.postState, cfg.roblock)
if err != nil { if err != nil {
log.WithError(err).Error("Saving light client bootstrap failed: Could not create light client bootstrap") return errors.Wrapf(err, "could not create light client bootstrap")
return
} }
err = s.cfg.BeaconDB.SaveLightClientBootstrap(cfg.ctx, blockRoot[:], bootstrap) if err := s.cfg.BeaconDB.SaveLightClientBootstrap(cfg.ctx, blockRoot[:], bootstrap); err != nil {
if err != nil { return errors.Wrapf(err, "could not save light client bootstrap")
log.WithError(err).Error("Saving light client bootstrap failed: Could not save light client bootstrap in DB")
} }
return nil
} }
func (s *Service) processLightClientFinalityUpdate( func (s *Service) processLightClientFinalityUpdate(

View File

@@ -2706,7 +2706,7 @@ func fakeResult(missing []uint64) map[uint64]struct{} {
return r return r
} }
func TestSaveLightClientUpdate(t *testing.T) { func TestProcessLightClientUpdate(t *testing.T) {
featCfg := &features.Flags{} featCfg := &features.Flags{}
featCfg.EnableLightClient = true featCfg.EnableLightClient = true
reset := features.InitWithReset(featCfg) reset := features.InitWithReset(featCfg)
@@ -2747,7 +2747,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
isValidPayload: true, isValidPayload: true,
} }
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
// Check that the light client update is saved // Check that the light client update is saved
period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot()))
@@ -2802,7 +2802,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate)
require.NoError(t, err) require.NoError(t, err)
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period)
require.NoError(t, err) require.NoError(t, err)
@@ -2863,7 +2863,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate)
require.NoError(t, err) require.NoError(t, err)
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period)
require.NoError(t, err) require.NoError(t, err)
@@ -2906,7 +2906,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
isValidPayload: true, isValidPayload: true,
} }
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
// Check that the light client update is saved // Check that the light client update is saved
period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot()))
@@ -2960,7 +2960,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate)
require.NoError(t, err) require.NoError(t, err)
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period)
require.NoError(t, err) require.NoError(t, err)
@@ -3021,7 +3021,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate)
require.NoError(t, err) require.NoError(t, err)
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period)
require.NoError(t, err) require.NoError(t, err)
@@ -3064,7 +3064,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
isValidPayload: true, isValidPayload: true,
} }
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
// Check that the light client update is saved // Check that the light client update is saved
period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot()))
@@ -3118,7 +3118,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate)
require.NoError(t, err) require.NoError(t, err)
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period)
require.NoError(t, err) require.NoError(t, err)
@@ -3179,7 +3179,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate)
require.NoError(t, err) require.NoError(t, err)
s.saveLightClientUpdate(cfg) require.NoError(t, s.processLightClientUpdate(cfg))
u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period)
require.NoError(t, err) require.NoError(t, err)
@@ -3192,7 +3192,7 @@ func TestSaveLightClientUpdate(t *testing.T) {
reset() reset()
} }
func TestSaveLightClientBootstrap(t *testing.T) { func TestProcessLightClientBootstrap(t *testing.T) {
featCfg := &features.Flags{} featCfg := &features.Flags{}
featCfg.EnableLightClient = true featCfg.EnableLightClient = true
reset := features.InitWithReset(featCfg) reset := features.InitWithReset(featCfg)
@@ -3222,7 +3222,7 @@ func TestSaveLightClientBootstrap(t *testing.T) {
isValidPayload: true, isValidPayload: true,
} }
s.saveLightClientBootstrap(cfg) require.NoError(t, s.processLightClientBootstrap(cfg))
// Check that the light client bootstrap is saved // Check that the light client bootstrap is saved
b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:]) b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:])
@@ -3257,7 +3257,7 @@ func TestSaveLightClientBootstrap(t *testing.T) {
isValidPayload: true, isValidPayload: true,
} }
s.saveLightClientBootstrap(cfg) require.NoError(t, s.processLightClientBootstrap(cfg))
// Check that the light client bootstrap is saved // Check that the light client bootstrap is saved
b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:]) b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:])
@@ -3292,7 +3292,7 @@ func TestSaveLightClientBootstrap(t *testing.T) {
isValidPayload: true, isValidPayload: true,
} }
s.saveLightClientBootstrap(cfg) require.NoError(t, s.processLightClientBootstrap(cfg))
// Check that the light client bootstrap is saved // Check that the light client bootstrap is saved
b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:]) b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:])

View File

@@ -0,0 +1,3 @@
### Ignored
- Reorganize processing of light client updates.