Skip to content

Commit

Permalink
Update daemon epoch updater to handle 'missed' epochs at startup
Browse files Browse the repository at this point in the history
  • Loading branch information
pbennett committed Apr 26, 2024
1 parent c196c9f commit e93c8ac
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
26 changes: 22 additions & 4 deletions nodemgr/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,9 @@ func (d *Daemon) EpochUpdater(ctx context.Context) {
}
curRound := status.LastRound
epochRoundLength := uint64(App.retiClient.Info().Config.EpochRoundLength)
// let's not worry about each pool and its last payout - just get next immediate block number for epoch
stopAtRound := nextEpoch(curRound, epochRoundLength)
// First we need to see if we MISSED an epoch in ANY of our pools - across all of our pools determine which
// we need to stop at first (could be in past - which will be instant fallthrough in waitUntilBlock)
stopAtRound := d.getFirstEligibleEpochRound(curRound, epochRoundLength)

misc.Infof(d.logger, "at round:%d, with epoch length:%d, first epoch check at %d", curRound, epochRoundLength, stopAtRound)

Expand All @@ -557,7 +558,6 @@ func (d *Daemon) EpochUpdater(ctx context.Context) {
info = App.retiClient.Info()
)
for i, pool := range info.Pools {
appid := pool.PoolAppId
if _, found := info.LocalPools[uint64(i+1)]; !found {
continue
}
Expand All @@ -577,7 +577,7 @@ func (d *Daemon) EpochUpdater(ctx context.Context) {
misc.Infof(d.logger, "already ran epoch update for this epoch on pool:%d, round:%d", i+1, blockWaitResult.atRound)
return nil
}
err = App.retiClient.EpochBalanceUpdate(i+1, appid, signerAddr)
err = App.retiClient.EpochBalanceUpdate(i+1, pool.PoolAppId, signerAddr)
if err != nil {
// Assume epoch update failed because it's just 'slightly' too early?
return repeat.HintTemporary(fmt.Errorf("epoch balance update failed for pool app id:%d, err:%w", i+1, err))
Expand Down Expand Up @@ -650,6 +650,24 @@ func (d *Daemon) waitUntilBlock(ctx context.Context, round uint64) chan BlockOrE
return chReturn
}

func (d *Daemon) getFirstEligibleEpochRound(curRound uint64, epochRoundLength uint64) uint64 {
var (
info = App.retiClient.Info()
curRoundEpochStart = curRound - (curRound % epochRoundLength)
earliestEpochToUse = curRoundEpochStart
)
for i, pool := range info.Pools {
if _, found := info.LocalPools[uint64(i+1)]; !found {
continue
}
lastPayout, err := App.retiClient.GetLastPayout(pool.PoolAppId)
if err == nil {
earliestEpochToUse = min(earliestEpochToUse, nextEpoch(lastPayout, epochRoundLength))
}
}
return earliestEpochToUse
}

// accountHasAtLeast checks if an account has at least a certain amount of microAlgos (spendable)
// Errors are just treated as failures
func accountHasAtLeast(ctx context.Context, algoClient *algod.Client, accountAddr string, microAlgos uint64) bool {
Expand Down
10 changes: 8 additions & 2 deletions nodemgr/internal/lib/reti/stakingpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,14 @@ func (r *Reti) EpochBalanceUpdate(poolID int, poolAppID uint64, caller types.Add
if err != nil {
return fmt.Errorf("failed to get algod status at start: %w", err)
}

misc.Infof(r.Logger, "[EpochBalanceUpdate] pool:%d epoch update at round:%d for app id:%d, avail rewards:%s", poolID, status.LastRound, poolAppID, algo.FormattedAlgoAmount(rewardAvail))
var epochStr string
epochStart := status.LastRound - status.LastRound%uint64(info.Config.EpochRoundLength)
if epochStart != status.LastRound {
epochStr = fmt.Sprintf("round:%d [EpochStart:%d]", status.LastRound, epochStart)
} else {
epochStr = fmt.Sprintf("EpochStart:%d", epochStart)
}
misc.Infof(r.Logger, "[EpochBalanceUpdate] pool:%d epoch update at %s for app id:%d, avail rewards:%s", poolID, epochStr, poolAppID, algo.FormattedAlgoAmount(rewardAvail))

params, err := r.algoClient.SuggestedParams().Do(context.Background())
if err != nil {
Expand Down

0 comments on commit e93c8ac

Please sign in to comment.