Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: handle roundid gap when do growID #311

Merged
merged 2 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x/oracle/keeper/common/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions x/oracle/keeper/feedermanagement/feedermanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 26 additions & 12 deletions x/oracle/keeper/prices.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}

Expand Down
35 changes: 33 additions & 2 deletions x/oracle/keeper/prices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{})
Expand Down Expand Up @@ -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)

}
2 changes: 2 additions & 0 deletions x/oracle/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ const (
TimeLayout = "2006-01-02 15:04:05"

DelimiterForCombinedKey = byte('/')

NilDetID = ""
)

var (
Expand Down
Loading