diff --git a/x/oracle/keeper/common/expected_keepers.go b/x/oracle/keeper/common/expected_keepers.go index 49e7098b6..0e83e37ed 100644 --- a/x/oracle/keeper/common/expected_keepers.go +++ b/x/oracle/keeper/common/expected_keepers.go @@ -29,7 +29,7 @@ type KeeperOracle interface { InitValidatorReportInfo(ctx sdk.Context, validator string, height int64) ClearAllValidatorReportInfo(ctx sdk.Context) ClearAllValidatorMissedRoundBitArray(ctx sdk.Context) - GrowRoundID(ctx sdk.Context, tokenID uint64) (price string, roundID uint64) + GrowRoundID(ctx sdk.Context, tokenID, nextRoundID uint64) (price string, roundID uint64) AppendPriceTR(ctx sdk.Context, tokenID uint64, priceTR types.PriceTimeRound, detID string) bool GetValidatorReportInfo(ctx sdk.Context, validator string) (info types.ValidatorReportInfo, found bool) GetMaliciousJailDuration(ctx sdk.Context) (res time.Duration) diff --git a/x/oracle/keeper/feedermanagement/feedermanager.go b/x/oracle/keeper/feedermanagement/feedermanager.go index 636501b21..8c0cfeecb 100644 --- a/x/oracle/keeper/feedermanagement/feedermanager.go +++ b/x/oracle/keeper/feedermanagement/feedermanager.go @@ -275,15 +275,17 @@ func (f *FeederManager) commitRounds(ctx sdk.Context) { if !ok { logger.Info("commit round with price from previous", "feederID", r.feederID, "roundID", r.roundID, "baseBlock", r.roundBaseBlock, "height", height) // #nosec G115 // tokenID is index of slice - f.k.GrowRoundID(ctx, uint64(r.tokenID)) + f.k.GrowRoundID(ctx, uint64(r.tokenID), uint64(r.roundID)) } else { if f.cs.IsRuleV1(r.feederID) { priceCommit := finalPrice.ProtoPriceTimeRound(r.roundID, ctx.BlockTime().Format(oracletypes.TimeLayout)) logger.Info("commit round with aggregated price", "feederID", r.feederID, "roundID", r.roundID, "baseBlock", r.roundBaseBlock, "price", priceCommit, "height", height) // #nosec G115 // tokenID is index of slice - f.k.AppendPriceTR(ctx, uint64(r.tokenID), *priceCommit, finalPrice.DetID) - // f.k.AppendPriceTR(ctx, uint64(r.tokenID), *priceCommit) + if updated := f.k.AppendPriceTR(ctx, uint64(r.tokenID), *priceCommit, finalPrice.DetID); !updated { + // failed to append price due to roundID gap, and this is a 'should-not-happen' case + f.k.GrowRoundID(ctx, uint64(r.tokenID), uint64(r.roundID)) + } fstr := strconv.FormatInt(feederID, 10) successFeederIDs = append(successFeederIDs, fstr) // there's no valid price for any round yet diff --git a/x/oracle/keeper/msg_server_create_price.go b/x/oracle/keeper/msg_server_price_feed.go similarity index 100% rename from x/oracle/keeper/msg_server_create_price.go rename to x/oracle/keeper/msg_server_price_feed.go diff --git a/x/oracle/keeper/prices.go b/x/oracle/keeper/prices.go index 6866bd236..0fdd1ccaf 100644 --- a/x/oracle/keeper/prices.go +++ b/x/oracle/keeper/prices.go @@ -210,10 +210,16 @@ func (k Keeper) AppendPriceTR(ctx sdk.Context, tokenID uint64, priceTR types.Pri store.Delete(types.PricesRoundKey(expiredRoundID)) } k.IncreaseNextRoundID(ctx, tokenID) + // skip post processing for nil deterministic ID + if detID == types.NilDetID { + return true + } + // skip post processing for empty price if len(priceTR.Price) == 0 { return true } + if nstAssetID := p.GetAssetIDForNSTFromTokenID(tokenID); len(nstAssetID) > 0 { nstVersion, err := getNSTVersionFromDetID(detID) if err != nil || nstVersion == 0 { @@ -232,21 +238,29 @@ func (k Keeper) AppendPriceTR(ctx sdk.Context, tokenID uint64, priceTR types.Pri } // GrowRoundID Increases roundID with the previous price -// func (k Keeper) GrowRoundID(ctx sdk.Context, tokenID uint64) (price *types.PriceTimeRound, roundID uint64) { -func (k Keeper) GrowRoundID(ctx sdk.Context, tokenID uint64) (price string, roundID uint64) { - if pTR, ok := k.GetPriceTRLatest(ctx, tokenID); ok { - pTR.RoundID++ - k.AppendPriceTR(ctx, tokenID, pTR, "") +func (k Keeper) GrowRoundID(ctx sdk.Context, tokenID, nextRoundID uint64) (price string, roundID uint64) { + storedNextRoundID := k.GetNextRoundID(ctx, tokenID) + pTR, ok := k.GetPriceTRLatest(ctx, tokenID) + if ok { price = pTR.Price - roundID = pTR.RoundID } else { - nextRoundID := k.GetNextRoundID(ctx, tokenID) - k.AppendPriceTR(ctx, tokenID, types.PriceTimeRound{ - RoundID: nextRoundID, - }, "") - roundID = nextRoundID - price = "" + pTR = types.PriceTimeRound{} + } + if nextRoundID < storedNextRoundID { + roundID = storedNextRoundID - 1 + // we don't append new price if storedNextRoundID is larger than expected + return + } + if nextRoundID > storedNextRoundID { + // if storedNextRoundID is too old, we just set it with input params + store := k.getPriceTRStore(ctx, tokenID) + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, nextRoundID) + store.Set(types.PricesNextRoundIDKey, b) } + roundID = nextRoundID + pTR.RoundID = nextRoundID + k.AppendPriceTR(ctx, tokenID, pTR, types.NilDetID) return } diff --git a/x/oracle/keeper/prices_test.go b/x/oracle/keeper/prices_test.go index 9555b4a56..562f31699 100644 --- a/x/oracle/keeper/prices_test.go +++ b/x/oracle/keeper/prices_test.go @@ -48,8 +48,6 @@ func TestPricesGet(t *testing.T) { func TestPricesGetMultiAssets(t *testing.T) { keeper, ctx := keepertest.OracleKeeper(t) - keeper.FeederManager.SetNilCaches() - keeper.FeederManager.BeginBlock(ctx) keeper.SetPrices(ctx, testdata.P1) assets := make(map[string]interface{}) assets["0x0b34c4d876cd569129cf56bafabb3f9e97a4ff42_0x9ce1"] = new(interface{}) @@ -91,3 +89,36 @@ func TestPricesGetAll(t *testing.T) { nullify.Fill(keeper.GetAllPrices(ctx)), ) } + +func TestPriceGrowID(t *testing.T) { + id1Uint := uint64(1) + id2Uint := uint64(2) + id3Uint := uint64(3) + id4Uint := uint64(4) + id7Uint := uint64(7) + keeper, ctx := keepertest.OracleKeeper(t) + keeper.SetPrices(ctx, types.Prices{ + TokenID: 1, + NextRoundID: id3Uint, + PriceList: []*types.PriceTimeRound{ + {Price: "123", RoundID: id1Uint}, + {Price: "799", RoundID: id2Uint}, + }, + }) + price, latestRoundID := keeper.GrowRoundID(ctx, 1, id2Uint) + require.Equal(t, "799", price) + require.Equal(t, id2Uint, latestRoundID) + + price, latestRoundID = keeper.GrowRoundID(ctx, 1, id3Uint) + require.Equal(t, "799", price) + require.Equal(t, id3Uint, latestRoundID) + + price, latestRoundID = keeper.GrowRoundID(ctx, 1, id4Uint) + require.Equal(t, "799", price) + require.Equal(t, id4Uint, latestRoundID) + + price, latestRoundID = keeper.GrowRoundID(ctx, 1, id7Uint) + require.Equal(t, "799", price) + require.Equal(t, id7Uint, latestRoundID) + +} diff --git a/x/oracle/types/types.go b/x/oracle/types/types.go index a93d980f6..4383aeb67 100644 --- a/x/oracle/types/types.go +++ b/x/oracle/types/types.go @@ -67,6 +67,8 @@ const ( TimeLayout = "2006-01-02 15:04:05" DelimiterForCombinedKey = byte('/') + + NilDetID = "" ) var (