Skip to content

Commit dd9a5fb

Browse files
authored
Force duties update on received blocks. (#15251)
* Force duties update on received blocks. - Change the context on UpdateDuties to be passed by the calling function. - Change the context passed to UpdateDuties to not be dependent on a slot context. - Change the deadlines to be forced to be an entire epoch. - Force duties to be initialized when receiving a HeadEvent if they aren't already. - Adds a read lock on the event handling * review * Add deadlines at start and healthyagain * cancel once
1 parent 7da7019 commit dd9a5fb

File tree

3 files changed

+58
-26
lines changed

3 files changed

+58
-26
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Added
2+
3+
- Force duties start on received blocks.

validator/client/runner.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,17 @@ func run(ctx context.Context, v iface.Validator) {
4343
if err != nil {
4444
return // Exit if context is canceled.
4545
}
46-
if err := v.UpdateDuties(ctx); err != nil {
46+
ss, err := slots.EpochStart(slots.ToEpoch(headSlot + 1))
47+
if err != nil {
48+
log.WithError(err).Error("Failed to get epoch start")
49+
ss = headSlot
50+
}
51+
startDeadline := v.SlotDeadline(ss + params.BeaconConfig().SlotsPerEpoch - 1)
52+
startCtx, startCancel := context.WithDeadline(ctx, startDeadline)
53+
if err := v.UpdateDuties(startCtx); err != nil {
4754
handleAssignmentError(err, headSlot)
4855
}
56+
startCancel()
4957
eventsChan := make(chan *event.Event, 1)
5058
healthTracker := v.HealthTracker()
5159
runHealthCheckRoutine(ctx, v, eventsChan)
@@ -90,12 +98,16 @@ func run(ctx context.Context, v iface.Validator) {
9098
// Keep trying to update assignments if they are nil or if we are past an
9199
// epoch transition in the beacon node's state.
92100
if slots.IsEpochStart(slot) {
93-
if err := v.UpdateDuties(slotCtx); err != nil {
101+
deadline = v.SlotDeadline(slot + params.BeaconConfig().SlotsPerEpoch - 1)
102+
dutiesCtx, dutiesCancel := context.WithDeadline(ctx, deadline)
103+
if err := v.UpdateDuties(dutiesCtx); err != nil {
94104
handleAssignmentError(err, slot)
105+
dutiesCancel()
95106
span.End()
96107
cancel()
97108
continue
98109
}
110+
dutiesCancel()
99111
}
100112

101113
// call push proposer settings often to account for the following edge cases:
@@ -127,10 +139,19 @@ func run(ctx context.Context, v iface.Validator) {
127139
log.WithError(err).Error("Failed to re initialize validator and get head slot")
128140
continue
129141
}
130-
if err := v.UpdateDuties(ctx); err != nil {
142+
ss, err := slots.EpochStart(slots.ToEpoch(headSlot + 1))
143+
if err != nil {
144+
log.WithError(err).Error("Failed to get epoch start")
145+
continue
146+
}
147+
deadline := v.SlotDeadline(ss + params.BeaconConfig().SlotsPerEpoch - 1)
148+
dutiesCtx, dutiesCancel := context.WithDeadline(ctx, deadline)
149+
if err := v.UpdateDuties(dutiesCtx); err != nil {
131150
handleAssignmentError(err, headSlot)
151+
dutiesCancel()
132152
continue
133153
}
154+
dutiesCancel()
134155
}
135156
case e := <-eventsChan:
136157
v.ProcessEvent(ctx, e)

validator/client/validator.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -515,15 +515,6 @@ func retrieveLatestRecord(recs []*dbCommon.AttestationRecord) *dbCommon.Attestat
515515
// list of upcoming assignments needs to be updated. For example, at the
516516
// beginning of a new epoch.
517517
func (v *validator) UpdateDuties(ctx context.Context) error {
518-
// Set deadline to end of epoch.
519-
epoch := slots.ToEpoch(slots.CurrentSlot(v.genesisTime) + 1)
520-
521-
ss, err := slots.EpochStart(epoch + 1)
522-
if err != nil {
523-
return err
524-
}
525-
ctx, cancel := context.WithDeadline(ctx, v.SlotDeadline(ss))
526-
defer cancel()
527518
ctx, span := trace.StartSpan(ctx, "validator.UpdateDuties")
528519
defer span.End()
529520

@@ -546,7 +537,7 @@ func (v *validator) UpdateDuties(ctx context.Context) error {
546537
}
547538
}
548539
v.blacklistedPubkeysLock.RUnlock()
549-
540+
epoch := slots.ToEpoch(slots.CurrentSlot(v.genesisTime) + 1)
550541
req := &ethpb.DutiesRequest{
551542
Epoch: epoch,
552543
PublicKeys: bytesutil.FromBytes48Array(filteredKeys),
@@ -562,9 +553,13 @@ func (v *validator) UpdateDuties(ctx context.Context) error {
562553
return err
563554
}
564555

556+
ss, err := slots.EpochStart(epoch)
557+
if err != nil {
558+
return err
559+
}
565560
v.dutiesLock.Lock()
566561
v.duties = resp
567-
v.logDuties(ss-params.BeaconConfig().SlotsPerEpoch, v.duties.CurrentEpochDuties, v.duties.NextEpochDuties)
562+
v.logDuties(ss, v.duties.CurrentEpochDuties, v.duties.NextEpochDuties)
568563
v.dutiesLock.Unlock()
569564

570565
allExitedCounter := 0
@@ -1146,18 +1141,28 @@ func (v *validator) checkDependentRoots(ctx context.Context, head *structs.HeadE
11461141
if head == nil {
11471142
return errors.New("received empty head event")
11481143
}
1149-
if v.duties == nil {
1150-
return errors.New("duties are not initialized")
1151-
}
1152-
prevDepedentRoot, err := bytesutil.DecodeHexWithLength(head.PreviousDutyDependentRoot, fieldparams.RootLength)
1144+
prevDependentRoot, err := bytesutil.DecodeHexWithLength(head.PreviousDutyDependentRoot, fieldparams.RootLength)
11531145
if err != nil {
11541146
return errors.Wrap(err, "failed to decode previous duty dependent root")
11551147
}
1156-
if bytes.Equal(prevDepedentRoot, params.BeaconConfig().ZeroHash[:]) {
1148+
if bytes.Equal(prevDependentRoot, params.BeaconConfig().ZeroHash[:]) {
11571149
return nil
11581150
}
1159-
if !bytes.Equal(prevDepedentRoot, v.duties.PrevDependentRoot) {
1160-
if err := v.UpdateDuties(ctx); err != nil {
1151+
epoch := slots.ToEpoch(slots.CurrentSlot(v.genesisTime) + 1)
1152+
ss, err := slots.EpochStart(epoch + 1)
1153+
if err != nil {
1154+
return errors.Wrap(err, "failed to get epoch start")
1155+
}
1156+
deadline := v.SlotDeadline(ss - 1)
1157+
dutiesCtx, cancel := context.WithDeadline(ctx, deadline)
1158+
defer cancel()
1159+
v.dutiesLock.RLock()
1160+
needsPrevDependentRootUpdate := v.duties == nil || !bytes.Equal(prevDependentRoot, v.duties.PrevDependentRoot)
1161+
v.dutiesLock.RUnlock()
1162+
if needsPrevDependentRootUpdate {
1163+
// There's an edge case when the initial duties are not set yet
1164+
// This routine will lock and recompute them right after the initial duties finishes.
1165+
if err := v.UpdateDuties(dutiesCtx); err != nil {
11611166
return errors.Wrap(err, "failed to update duties")
11621167
}
11631168
log.Info("Updated duties due to previous dependent root change")
@@ -1170,13 +1175,16 @@ func (v *validator) checkDependentRoots(ctx context.Context, head *structs.HeadE
11701175
if bytes.Equal(currDepedentRoot, params.BeaconConfig().ZeroHash[:]) {
11711176
return nil
11721177
}
1173-
if !bytes.Equal(currDepedentRoot, v.duties.CurrDependentRoot) {
1174-
if err := v.UpdateDuties(ctx); err != nil {
1175-
return errors.Wrap(err, "failed to update duties")
1176-
}
1177-
log.Info("Updated duties due to current dependent root change")
1178+
v.dutiesLock.RLock()
1179+
needsCurrDependentRootUpdate := v.duties == nil || !bytes.Equal(currDepedentRoot, v.duties.CurrDependentRoot)
1180+
v.dutiesLock.RUnlock()
1181+
if !needsCurrDependentRootUpdate {
11781182
return nil
11791183
}
1184+
if err := v.UpdateDuties(dutiesCtx); err != nil {
1185+
return errors.Wrap(err, "failed to update duties")
1186+
}
1187+
log.Info("Updated duties due to current dependent root change")
11801188
return nil
11811189
}
11821190

0 commit comments

Comments
 (0)