44 "context"
55 "errors"
66 "fmt"
7+ "slices"
78 "sort"
89 "time"
910
@@ -322,10 +323,16 @@ func (k *keeper) EndBlocker(ctx context.Context) error {
322323 panic (fmt .Sprintf ("failed to walk latest prices: %v" , err ))
323324 }
324325
326+ cutoffHeight := sctx .BlockHeight () - params .MaxPriceStalenessBlocks
327+
325328 for id , rid := range rIDs {
326329 latestData := make ([]types.PriceData , 0 , len (rid ))
327330
328331 for _ , id := range rid {
332+ if id .Height < cutoffHeight {
333+ continue
334+ }
335+
329336 state , _ := k .prices .Get (sctx , id )
330337
331338 latestData = append (latestData , types.PriceData {
@@ -496,18 +503,28 @@ func (k *keeper) calculateAggregatedPrices(ctx sdk.Context, id types.DataID, lat
496503 Denom : id .Denom ,
497504 }
498505
506+ params , err := k .GetParams (ctx )
507+ if err != nil {
508+ return aggregated , err
509+ }
510+
511+ // filter out stale sources by time
512+ // todo block time is a variable, it should not be hardcoded
513+ cutoffTimestamp := ctx .BlockTime ().Add (- time .Duration (params .MaxPriceStalenessBlocks ) * (time .Second * 6 ))
514+
515+ for i := len (latestData ) - 1 ; i >= 0 ; i -- {
516+ if latestData [i ].State .Timestamp .Before (cutoffTimestamp ) {
517+ latestData = slices .Delete (latestData , i , i + 1 )
518+ }
519+ }
520+
499521 if len (latestData ) == 0 {
500522 return aggregated , errorsmod .Wrap (
501523 types .ErrPriceStalled ,
502524 "all price sources are stale" ,
503525 )
504526 }
505527
506- params , err := k .GetParams (ctx )
507- if err != nil {
508- return aggregated , err
509- }
510-
511528 // Calculate TWAP for each source
512529 var twaps []sdkmath.LegacyDec //nolint:prealloc
513530 for _ , source := range latestData {
@@ -624,7 +641,9 @@ func (k *keeper) getAggregatedPrice(ctx sdk.Context, denom string) (types.Aggreg
624641// CheckPriceHealth checks if the aggregated price meets health requirements
625642func (k * keeper ) setPriceHealth (ctx sdk.Context , params types.Params , dataIDs []types.PriceDataRecordID , aggregatedPrice types.AggregatedPrice ) types.PriceHealth {
626643 health := types.PriceHealth {
627- Denom : aggregatedPrice .Denom ,
644+ Denom : aggregatedPrice .Denom ,
645+ TotalSources : uint32 (len (dataIDs )),
646+ TotalHealthySources : aggregatedPrice .NumSources ,
628647 }
629648
630649 // Check 1: Minimum number of sources
@@ -647,41 +666,7 @@ func (k *keeper) setPriceHealth(ctx sdk.Context, params types.Params, dataIDs []
647666 ))
648667 }
649668
650- // Check 3: All sources are fresh
651- allFresh := true
652- foundSource := false
653- cutoffHeight := ctx .BlockHeight () - params .MaxPriceStalenessBlocks
654-
655- for _ , did := range dataIDs {
656- foundSource = true
657- allFresh = allFresh && did .Height >= cutoffHeight
658- //return !allFresh, nil
659- }
660-
661- //err := k.latestPrices.Walk(ctx, nil, func(key types.PriceDataID, value int64) (bool, error) {
662- // if key.Denom != aggregatedPrice.Denom || key.BaseDenom != sdkutil.DenomUSD {
663- // return false, nil
664- // }
665- //
666- // foundSource = true
667- // allFresh = allFresh && value >= cutoffHeight
668- // return !allFresh, nil
669- //})
670-
671- //if err != nil {
672- // allFresh = false
673- //}
674-
675- if ! foundSource {
676- allFresh = false
677- }
678-
679- if ! allFresh {
680- health .FailureReason = append (health .FailureReason , "one or more price sources are stale" )
681- }
682-
683- health .AllSourcesFresh = allFresh
684- health .IsHealthy = health .HasMinSources && health .DeviationOk && health .AllSourcesFresh
669+ health .IsHealthy = health .HasMinSources && health .DeviationOk
685670
686671 err := k .pricesHealth .Set (ctx , types.DataID {Denom : health .Denom , BaseDenom : sdkutil .DenomUSD }, health )
687672 // if there is an error when storing price health, something went horribly wrong
0 commit comments