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

portfolio keys migration and redundant data deletion #772

Merged
merged 6 commits into from
Sep 9, 2024
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
6 changes: 3 additions & 3 deletions app/test_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@

type GenerateAccountStrategy func(int) []sdk.AccAddress

// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
func createRandomAccounts(accNum int) []sdk.AccAddress {
// CreateRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
func CreateRandomAccounts(accNum int) []sdk.AccAddress {

Check warning on line 205 in app/test_setup.go

View check run for this annotation

Codecov / codecov/patch

app/test_setup.go#L205

Added line #L205 was not covered by tests
testAddrs := make([]sdk.AccAddress, accNum)
for i := 0; i < accNum; i++ {
pk := ed25519.GenPrivKey().PubKey()
Expand All @@ -215,7 +215,7 @@
// AddTestAddrs constructs and returns accNum amount of accounts with an
// initial balance of accAmt in random order
func AddTestAddrs(app *ElysApp, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress {
return addTestAddrs(app, ctx, accNum, accAmt, createRandomAccounts)
return addTestAddrs(app, ctx, accNum, accAmt, CreateRandomAccounts)

Check warning on line 218 in app/test_setup.go

View check run for this annotation

Codecov / codecov/patch

app/test_setup.go#L218

Added line #L218 was not covered by tests
}

func addTestAddrs(app *ElysApp, ctx sdk.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress {
Expand Down
15 changes: 12 additions & 3 deletions proto/elys/tier/portfolio.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@ syntax = "proto3";
package elys.tier;

option go_package = "github.com/elys-network/elys/x/tier/types";
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";

message Portfolio {
message LegacyPortfolio {
string creator = 1;
string portfolio = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}

message Portfolio {
string date = 1;
string creator = 2;
string portfolio = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}
4 changes: 2 additions & 2 deletions x/leveragelp/keeper/msg_server_close_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,15 @@ func (suite *KeeperTestSuite) TestClose() {

for _, tc := range testCases {
suite.Run(tc.name, func() {
portfolio_old, found := suite.app.TierKeeper.GetPortfolio(suite.ctx, tc.input.Creator, suite.app.TierKeeper.GetDateFromBlock(suite.ctx.BlockTime()))
portfolio_old, found := suite.app.TierKeeper.GetPortfolio(suite.ctx, sdk.MustAccAddressFromBech32(tc.input.Creator), suite.app.TierKeeper.GetDateFromContext(suite.ctx))
tc.prerequisiteFunction()
_, err := suite.app.LeveragelpKeeper.Close(suite.ctx, tc.input)
if tc.expectErr {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.expectErrMsg)
} else {
// The new value of the portfolio after the hook is called.
portfolio_new, _ := suite.app.TierKeeper.GetPortfolio(suite.ctx, tc.input.Creator, suite.app.TierKeeper.GetDateFromBlock(suite.ctx.BlockTime()))
portfolio_new, _ := suite.app.TierKeeper.GetPortfolio(suite.ctx, sdk.MustAccAddressFromBech32(tc.input.Creator), suite.app.TierKeeper.GetDateFromContext(suite.ctx))
// Initially, there were no entries for the portfolio
if !found {
// The portfolio value changes after the hook is called.
Expand Down
5 changes: 2 additions & 3 deletions x/leveragelp/keeper/msg_server_open_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package keeper_test

import (

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
Expand Down Expand Up @@ -374,14 +373,14 @@ func (suite *KeeperTestSuite) TestOpen_PoolWithBaseCurrencyAsset() {
for _, tc := range testCases {
suite.Run(tc.name, func() {
tc.prerequisiteFunction()
portfolio_old, found := suite.app.TierKeeper.GetPortfolio(suite.ctx, tc.input.Creator, suite.app.TierKeeper.GetDateFromBlock(suite.ctx.BlockTime()))
portfolio_old, found := suite.app.TierKeeper.GetPortfolio(suite.ctx, sdk.MustAccAddressFromBech32(tc.input.Creator), suite.app.TierKeeper.GetDateFromContext(suite.ctx))
_, err := suite.app.LeveragelpKeeper.Open(suite.ctx, tc.input)
if tc.expectErr {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.expectErrMsg)
} else {
// The new value of the portfolio after the hook is called.
portfolio_new, _ := suite.app.TierKeeper.GetPortfolio(suite.ctx, tc.input.Creator, suite.app.TierKeeper.GetDateFromBlock(suite.ctx.BlockTime()))
portfolio_new, _ := suite.app.TierKeeper.GetPortfolio(suite.ctx, sdk.MustAccAddressFromBech32(tc.input.Creator), suite.app.TierKeeper.GetDateFromContext(suite.ctx))
// Initially, there were no entries for the portfolio
if !found {
// The portfolio value changes after the hook is called.
Expand Down
8 changes: 4 additions & 4 deletions x/tier/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
// InitGenesis initializes the module's state from a provided genesis state.
func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) {
// Set all the portfolio
// for _, elem := range genState.PortfolioList {
// k.SetPortfolio(ctx, elem)
// }
for _, elem := range genState.PortfolioList {
k.SetPortfolio(ctx, elem)
}
// this line is used by starport scaffolding # genesis/module/init
k.SetParams(ctx, genState.Params)
}
Expand All @@ -21,7 +21,7 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
genesis := types.DefaultGenesis()
genesis.Params = k.GetParams(ctx)

genesis.PortfolioList = k.GetAllPortfolio(ctx, k.GetDateFromBlock(ctx.BlockTime()))
genesis.PortfolioList = k.GetAllPortfolio(ctx)
// this line is used by starport scaffolding # genesis/module/export

return genesis
Expand Down
11 changes: 5 additions & 6 deletions x/tier/keeper/begin_blocker.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package keeper

import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
)

func (k Keeper) BeginBlocker(ctx sdk.Context) {
year, month, day := ctx.BlockTime().Date()
dateToday := time.Date(year, month, day, 0, 0, 0, 0, ctx.BlockTime().Location())
deleteDate := dateToday.AddDate(0, 0, -8)
deleteDate := k.GetDateAfterDaysFromContext(ctx, -8)
// Remove last 100 values at each block
k.RemovePortfolioLast(ctx, deleteDate.String(), 100)
k.RemovePortfolioLast(ctx, deleteDate, 100)
// migration does not delete all older entries as we don't know whats last date is there, deleting from past 105 days
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can put this logic in migration. will that not work ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Older entries might take a lot of time to finish deleting leading to workflow failure. So deleting in abci.

deleteDate = k.GetDateAfterDaysFromContext(ctx, -105)
k.RemoveLegacyPortfolioCounted(ctx, deleteDate, 100)
}
128 changes: 71 additions & 57 deletions x/tier/keeper/portfolio.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package keeper

import (
"github.com/cosmos/cosmos-sdk/store/prefix"
"math"
"strconv"
"strings"
"time"

"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
ammtypes "github.com/elys-network/elys/x/amm/types"
Expand All @@ -20,9 +20,9 @@

func (k Keeper) RetrieveAllPortfolio(ctx sdk.Context, user sdk.AccAddress) {
// set today + user -> amount
todayDate := k.GetDateFromBlock(ctx.BlockTime())
todayDate := k.GetDateFromContext(ctx)

_, found := k.GetPortfolio(ctx, user.String(), todayDate)
_, found := k.GetPortfolio(ctx, user, todayDate)
if found {
return
}
Expand Down Expand Up @@ -60,10 +60,7 @@

totalValue = totalValue.Add(lev)

k.SetPortfolio(ctx, todayDate, user.String(), types.Portfolio{
Creator: user.String(),
Portfolio: totalValue,
})
k.SetPortfolio(ctx, types.NewPortfolioWithContextDate(todayDate, user, totalValue))
}

func (k Keeper) RetrievePoolTotal(ctx sdk.Context, user sdk.AccAddress) sdk.Dec {
Expand Down Expand Up @@ -326,39 +323,27 @@
}

// SetPortfolio set a specific portfolio in the store from its index
func (k Keeper) SetPortfolio(ctx sdk.Context, todayDate string, user string, portfolio types.Portfolio) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(todayDate))
func (k Keeper) SetPortfolio(ctx sdk.Context, portfolio types.Portfolio) {
store := ctx.KVStore(k.storeKey)
key := types.GetPortfolioKey(portfolio.Date, portfolio.GetCreatorAddress())
b := k.cdc.MustMarshal(&portfolio)
store.Set(types.PortfolioKey(
user,
), b)
store.Set(key, b)
}

// GetPortfolio returns a portfolio from its index
func (k Keeper) GetPortfolio(
ctx sdk.Context,
user string,
timestamp string,
) (sdk.Dec, bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(timestamp))

found := store.Has(types.PortfolioKey(
user,
))

if !found {
return sdk.NewDec(0), false
func (k Keeper) GetPortfolio(ctx sdk.Context, user sdk.AccAddress, date string) (sdk.Dec, bool) {
store := ctx.KVStore(k.storeKey)
key := types.GetPortfolioKey(date, user)
portfolioBytes := store.Get(key)
if portfolioBytes == nil {
return sdk.ZeroDec(), false
}

portfolio := store.Get(types.PortfolioKey(
user,
))
var val types.Portfolio
k.cdc.MustUnmarshal(portfolio, &val)
k.cdc.MustUnmarshal(portfolioBytes, &val)
return val.Portfolio, true
}

func (k Keeper) GetMembershipTier(ctx sdk.Context, user string) (total_portfoilio sdk.Dec, tier string, discount uint64) {
func (k Keeper) GetMembershipTier(ctx sdk.Context, user sdk.AccAddress) (total_portfoilio sdk.Dec, tier string, discount uint64) {
year, month, day := ctx.BlockTime().Date()
dateToday := time.Date(year, month, day, 0, 0, 0, 0, ctx.BlockTime().Location())
startDate := dateToday.AddDate(0, 0, -7)
Expand Down Expand Up @@ -393,26 +378,10 @@
return minTotal, "bronze", 0
}

// RemovePortfolio removes a portfolio from the store
func (k Keeper) RemovePortfolio(
ctx sdk.Context,
user string,
timestamp string,
) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(timestamp))
store.Delete(types.PortfolioKey(
user,
))
}

// RemovePortfolioLast removes a portfolio from the store with a specific date
func (k Keeper) RemovePortfolioLast(
ctx sdk.Context,
timestamp string,
num uint64,
) uint64 {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(timestamp))
iterator := sdk.KVStorePrefixIterator(store, []byte{})
func (k Keeper) RemovePortfolioLast(ctx sdk.Context, date string, num uint64) uint64 {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, types.GetPortfolioByDateIteratorKey(date))

defer iterator.Close()
count := 0
Expand All @@ -428,9 +397,9 @@
}

// GetAllPortfolio returns all portfolio
func (k Keeper) GetAllPortfolio(ctx sdk.Context, timestamp string) (list []types.Portfolio) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(timestamp))
iterator := sdk.KVStorePrefixIterator(store, []byte{})
func (k Keeper) GetAllPortfolio(ctx sdk.Context) (list []types.Portfolio) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, types.PortfolioKeyPrefix)

defer iterator.Close()

Expand All @@ -443,13 +412,22 @@
return
}

func (k Keeper) GetDateFromBlock(blockTime time.Time) string {
func (k Keeper) GetDateFromContext(ctx sdk.Context) string {
contextTime := ctx.BlockTime()
// Extract the year, month, and day
year, month, day := blockTime.Date()
year, month, day := contextTime.Date()
// Create a new time.Time object with the extracted date and time set to midnight
blockDate := time.Date(year, month, day, 0, 0, 0, 0, blockTime.Location())
contextDate := time.Date(year, month, day, 0, 0, 0, 0, contextTime.Location())
// Format the date as a string in the "%Y-%m-%d" format
return blockDate.Format("2006-01-02")
return contextDate.Format(types.DateFormat)
}

func (k Keeper) GetDateAfterDaysFromContext(ctx sdk.Context, n int) string {
contextTime := ctx.BlockTime()
year, month, day := contextTime.Date()
contextDate := time.Date(year, month, day, 0, 0, 0, 0, contextTime.Location())
resultDate := contextDate.AddDate(0, 0, n)
return resultDate.Format(types.DateFormat)
}

func GetPoolIdFromShareDenom(shareDenom string) (uint64, error) {
Expand All @@ -467,3 +445,39 @@
}
return
}

// remove after migrations
func (k Keeper) GetLegacyPortfolios(ctx sdk.Context, date string) (list []types.Portfolio) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(date))
iterator := sdk.KVStorePrefixIterator(store, []byte{})

Check warning on line 452 in x/tier/keeper/portfolio.go

View check run for this annotation

Codecov / codecov/patch

x/tier/keeper/portfolio.go#L450-L452

Added lines #L450 - L452 were not covered by tests

defer iterator.Close()

Check warning on line 454 in x/tier/keeper/portfolio.go

View check run for this annotation

Codecov / codecov/patch

x/tier/keeper/portfolio.go#L454

Added line #L454 was not covered by tests

for ; iterator.Valid(); iterator.Next() {
var val types.LegacyPortfolio
k.cdc.MustUnmarshal(iterator.Value(), &val)
list = append(list, types.NewPortfolioWithContextDate(date, sdk.MustAccAddressFromBech32(val.Creator), val.Portfolio))

Check warning on line 459 in x/tier/keeper/portfolio.go

View check run for this annotation

Codecov / codecov/patch

x/tier/keeper/portfolio.go#L456-L459

Added lines #L456 - L459 were not covered by tests
}
return

Check warning on line 461 in x/tier/keeper/portfolio.go

View check run for this annotation

Codecov / codecov/patch

x/tier/keeper/portfolio.go#L461

Added line #L461 was not covered by tests
}

func (k Keeper) RemoveLegacyPortfolio(ctx sdk.Context, date string, user string) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(date))
store.Delete(types.PortfolioKey(user))

Check warning on line 466 in x/tier/keeper/portfolio.go

View check run for this annotation

Codecov / codecov/patch

x/tier/keeper/portfolio.go#L464-L466

Added lines #L464 - L466 were not covered by tests
}

func (k Keeper) RemoveLegacyPortfolioCounted(ctx sdk.Context, date string, num uint64) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(date))
iterator := sdk.KVStorePrefixIterator(store, []byte{})

defer iterator.Close()
count := uint64(0)
for ; iterator.Valid(); iterator.Next() {
count++
store.Delete(iterator.Key())
if count == num {
break

Check warning on line 479 in x/tier/keeper/portfolio.go

View check run for this annotation

Codecov / codecov/patch

x/tier/keeper/portfolio.go#L476-L479

Added lines #L476 - L479 were not covered by tests
}
}
return
}
Loading
Loading