Skip to content

Commit

Permalink
chore: LSM changes to staking (#7)
Browse files Browse the repository at this point in the history
* set min_self_delegation to 0 in TestAminoCodecFullDecodeAndEncode

* add WithdrawTokenizeShareRecordReward and WithdrawAllTokenizeShareRecordReward

* add methods to distribution/keeper

* register distribution msgs

* add SimulateMsgWithdrawTokenizeShareRecordReward

* LSM distribution queries

* LSM distr cli

* add BeforeTokenizeShareRecordRemoved hook

* add signers to proto distribution

* set signers correctly

* minimum refactor to build

* tag LSM test to be refactored

* Merge with feat/lsm/v0.47.x

tag LSM tests to be refactored

Fix nits

* nit

* comments more failing tests

* make protos

* Update x/staking/keeper/msg_server.go

Co-authored-by: Marius Poke <[email protected]>

* Update x/staking/keeper/msg_server.go

Co-authored-by: Marius Poke <[email protected]>

* add go.work and fix silent errors

* address comments

* tests: add lsm distribution tests (#6)

---------

Co-authored-by: mpoke <[email protected]>
Co-authored-by: MSalopek <[email protected]>
  • Loading branch information
3 people authored Dec 5, 2023
1 parent c22e127 commit e7220e3
Show file tree
Hide file tree
Showing 43 changed files with 6,161 additions and 276 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*.swm
*.swn
*.pyc
*.fail

# private files
private[.-]*
Expand Down
7 changes: 4 additions & 3 deletions runtime/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ func (a *App) Load(loadLatest bool) error {
a.SetEndBlocker(a.EndBlocker)
}

if len(a.config.OrderMigrations) != 0 {
a.ModuleManager.SetOrderMigrations(a.config.OrderMigrations...)
}
// TODO LSM refactor fix this
// if len(a.config.OrderMigrations) != 0 {
// a.ModuleManager.SetOrderMigrations(a.config.OrderMigrations...)
// }

if loadLatest {
if err := a.LoadLatestVersion(); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/staking/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (s *E2ETestSuite) TestGRPCQueryValidatorDelegations() {
&types.QueryValidatorDelegationsResponse{},
&types.QueryValidatorDelegationsResponse{
DelegationResponses: types.DelegationResponses{
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), false, sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
},
Pagination: &query.PageResponse{Total: 1},
},
Expand Down Expand Up @@ -398,7 +398,7 @@ func (s *E2ETestSuite) TestGRPCQueryDelegatorDelegations() {
&types.QueryDelegatorDelegationsResponse{},
&types.QueryDelegatorDelegationsResponse{
DelegationResponses: types.DelegationResponses{
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), false, sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
},
Pagination: &query.PageResponse{Total: 1},
},
Expand Down
34 changes: 27 additions & 7 deletions tests/e2e/staking/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ func (s *E2ETestSuite) SetupSuite() {
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
s.Require().NoError(err)

unbond, err := sdk.ParseCoinNormalized("10stake")
unbondCoin, err := sdk.ParseCoinNormalized("10stake")
s.Require().NoError(err)

tokenizeCoin, err := sdk.ParseCoinNormalized("1000stake")
s.Require().NoError(err)

val := s.network.Validators[0]
Expand All @@ -61,7 +64,7 @@ func (s *E2ETestSuite) SetupSuite() {
val.Address,
val.ValAddress,
val2.ValAddress,
unbond,
unbondCoin,
fmt.Sprintf("--%s=%d", flags.FlagGas, 300000),
)
s.Require().NoError(err)
Expand All @@ -70,15 +73,32 @@ func (s *E2ETestSuite) SetupSuite() {
s.Require().Equal(uint32(0), txRes.Code)
s.Require().NoError(s.network.WaitForNextBlock())

unbondingAmount := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5))

// unbonding the amount
out, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbondingAmount)
out, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbondCoin)
s.Require().NoError(err)
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes))
s.Require().Equal(uint32(0), txRes.Code)
s.Require().NoError(s.network.WaitForNextBlock())

// tokenize shares twice (once for the transfer and one for the redeem)
for i := 1; i <= 2; i++ {
out, err := MsgTokenizeSharesExec(
val.ClientCtx,
val.Address,
val.ValAddress,
val.Address,
tokenizeCoin,
fmt.Sprintf("--%s=%d", flags.FlagGas, 1000000),
)

s.Require().NoError(err)
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes))
s.Require().Equal(uint32(0), txRes.Code)
s.Require().NoError(s.network.WaitForNextBlock())
}

unbondingAmount := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5))

// unbonding the amount
out, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbondingAmount)
s.Require().NoError(err)
Expand Down Expand Up @@ -420,7 +440,7 @@ func (s *E2ETestSuite) TestGetCmdQueryDelegations() {
&types.QueryDelegatorDelegationsResponse{},
&types.QueryDelegatorDelegationsResponse{
DelegationResponses: types.DelegationResponses{
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), false, sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
},
Pagination: &query.PageResponse{},
},
Expand Down Expand Up @@ -476,7 +496,7 @@ func (s *E2ETestSuite) TestGetCmdQueryValidatorDelegations() {
&types.QueryValidatorDelegationsResponse{},
&types.QueryValidatorDelegationsResponse{
DelegationResponses: types.DelegationResponses{
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), false, sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
},
Pagination: &query.PageResponse{},
},
Expand Down
16 changes: 16 additions & 0 deletions tests/e2e/staking/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,19 @@ func MsgUnbondExec(clientCtx client.Context, from fmt.Stringer, valAddress,
args = append(args, extraArgs...)
return clitestutil.ExecTestCLICmd(clientCtx, stakingcli.NewUnbondCmd(), args)
}

// MsgTokenizeSharesExec creates a delegation message.
func MsgTokenizeSharesExec(clientCtx client.Context, from fmt.Stringer, valAddress,
rewardOwner, amount fmt.Stringer, extraArgs ...string,
) (testutil.BufferWriter, error) {
args := []string{
valAddress.String(),
amount.String(),
rewardOwner.String(),
fmt.Sprintf("--%s=%s", flags.FlagFrom, from.String()),
}

args = append(args, commonArgs...)
args = append(args, extraArgs...)
return clitestutil.ExecTestCLICmd(clientCtx, stakingcli.NewTokenizeSharesCmd(), args)
}
136 changes: 136 additions & 0 deletions tests/integration/distribution/keeper/delegation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import (
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil"
Expand Down Expand Up @@ -818,3 +821,136 @@ func Test100PercentCommissionReward(t *testing.T) {
}
require.True(t, hasValue)
}

func TestWithdrawTokenizeShareRecordReward(t *testing.T) {
var (
accountKeeper authkeeper.AccountKeeper
bankKeeper bankkeeper.Keeper
distrKeeper keeper.Keeper
stakingKeeper *stakingkeeper.Keeper
mintKeeper mintkeeper.Keeper
)

app, err := simtestutil.Setup(testutil.AppConfig,
&accountKeeper,
&bankKeeper,
&distrKeeper,
&stakingKeeper,
&mintKeeper,
)
require.NoError(t, err)

ctx := app.BaseApp.NewContext(false, tmproto.Header{})

addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(100000000))
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
tstaking := stakingtestutil.NewHelper(t, ctx, stakingKeeper)

// create validator with 50% commission
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
valPower := int64(100)
tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk1, valPower, true)

// end block to bond validator
staking.EndBlocker(ctx, stakingKeeper)

// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)

// fetch validator and delegation
val := stakingKeeper.Validator(ctx, valAddrs[0])
del := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])

// end period
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)

// calculate delegation rewards
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)

// rewards should be zero
require.True(t, rewards.IsZero())

// start out block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)

// retrieve validator
val = stakingKeeper.Validator(ctx, valAddrs[0])

// increase block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)

// allocate some rewards
initial := stakingKeeper.TokensFromConsensusPower(ctx, 10)
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromInt(initial)}}
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)

// end period
distrKeeper.IncrementValidatorPeriod(ctx, val)

coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, initial)}
err = mintKeeper.MintCoins(ctx, coins)
require.NoError(t, err)
err = bankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, types.ModuleName, coins)
require.NoError(t, err)

// tokenize share amount
delTokens := sdk.NewInt(1000000)
msgServer := stakingkeeper.NewMsgServerImpl(stakingKeeper)
resp, err := msgServer.TokenizeShares(sdk.WrapSDKContext(ctx), &stakingtypes.MsgTokenizeShares{
DelegatorAddress: sdk.AccAddress(valAddrs[0]).String(),
ValidatorAddress: valAddrs[0].String(),
TokenizedShareOwner: sdk.AccAddress(valAddrs[1]).String(),
Amount: sdk.NewCoin(sdk.DefaultBondDenom, delTokens),
})
require.NoError(t, err)

// try withdrawing rewards before no reward is allocated
coins, err = distrKeeper.WithdrawAllTokenizeShareRecordReward(ctx, sdk.AccAddress(valAddrs[1]))
require.Nil(t, err)
require.Equal(t, coins, sdk.Coins{})

// assert tokenize share response
require.NoError(t, err)
require.Equal(t, resp.Amount.Amount, delTokens)

// end block to bond validator
staking.EndBlocker(ctx, stakingKeeper)
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
// allocate some rewards
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
// end period
distrKeeper.IncrementValidatorPeriod(ctx, val)

beforeBalance := bankKeeper.GetBalance(ctx, sdk.AccAddress(valAddrs[1]), sdk.DefaultBondDenom)

// withdraw rewards
coins, err = distrKeeper.WithdrawAllTokenizeShareRecordReward(ctx, sdk.AccAddress(valAddrs[1]))
require.Nil(t, err)

// check return value
require.Equal(t, coins.String(), "50000stake")
// check balance changes
midBalance := bankKeeper.GetBalance(ctx, sdk.AccAddress(valAddrs[1]), sdk.DefaultBondDenom)
require.Equal(t, beforeBalance.Amount.Add(coins.AmountOf(sdk.DefaultBondDenom)), midBalance.Amount)

// allocate more rewards manually on module account and try full redeem
record, err := stakingKeeper.GetTokenizeShareRecord(ctx, 1)
require.NoError(t, err)

err = mintKeeper.MintCoins(ctx, coins)
require.NoError(t, err)
err = bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, record.GetModuleAddress(), coins)
require.NoError(t, err)

shareTokenBalance := bankKeeper.GetBalance(ctx, sdk.AccAddress(valAddrs[0]), record.GetShareTokenDenom())

_, err = msgServer.RedeemTokensForShares(sdk.WrapSDKContext(ctx), &stakingtypes.MsgRedeemTokensForShares{
DelegatorAddress: sdk.AccAddress(valAddrs[0]).String(),
Amount: shareTokenBalance,
})
require.NoError(t, err)

finalBalance := bankKeeper.GetBalance(ctx, sdk.AccAddress(valAddrs[1]), sdk.DefaultBondDenom)
require.Equal(t, midBalance.Amount.Add(coins.AmountOf(sdk.DefaultBondDenom)), finalBalance.Amount)
}
19 changes: 12 additions & 7 deletions tests/integration/gov/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,22 @@ func createValidators(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers
app.StakingKeeper.SetValidator(ctx, val1)
app.StakingKeeper.SetValidator(ctx, val2)
app.StakingKeeper.SetValidator(ctx, val3)
app.StakingKeeper.SetValidatorByConsAddr(ctx, val1)
app.StakingKeeper.SetValidatorByConsAddr(ctx, val2)
app.StakingKeeper.SetValidatorByConsAddr(ctx, val3)
err = app.StakingKeeper.SetValidatorByConsAddr(ctx, val1)
require.NoError(t, err)
err = app.StakingKeeper.SetValidatorByConsAddr(ctx, val2)
require.NoError(t, err)
err = app.StakingKeeper.SetValidatorByConsAddr(ctx, val3)
require.NoError(t, err)
app.StakingKeeper.SetNewValidatorByPowerIndex(ctx, val1)
app.StakingKeeper.SetNewValidatorByPowerIndex(ctx, val2)
app.StakingKeeper.SetNewValidatorByPowerIndex(ctx, val3)

_, _ = app.StakingKeeper.Delegate(ctx, addrs[0], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[0]), stakingtypes.Unbonded, val1, true)
_, _ = app.StakingKeeper.Delegate(ctx, addrs[1], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[1]), stakingtypes.Unbonded, val2, true)
_, _ = app.StakingKeeper.Delegate(ctx, addrs[2], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[2]), stakingtypes.Unbonded, val3, true)

_, err = app.StakingKeeper.Delegate(ctx, addrs[0], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[0]), stakingtypes.Unbonded, val1, true)
require.NoError(t, err)
_, err = app.StakingKeeper.Delegate(ctx, addrs[1], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[1]), stakingtypes.Unbonded, val2, true)
require.NoError(t, err)
_, err = app.StakingKeeper.Delegate(ctx, addrs[2], app.StakingKeeper.TokensFromConsensusPower(ctx, powers[2]), stakingtypes.Unbonded, val3, true)
require.NoError(t, err)
_ = staking.EndBlocker(ctx, app.StakingKeeper)

return addrs, valAddrs
Expand Down
6 changes: 6 additions & 0 deletions tests/integration/staking/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,9 @@ func createValidators(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers

return addrs, valAddrs, vals
}

func delegateCoinsFromAccount(ctx sdk.Context, app *simapp.SimApp, addr sdk.AccAddress, amount sdk.Int, val types.Validator) error {
_, err := app.StakingKeeper.Delegate(ctx, addr, amount, types.Unbonded, val, true)

return err
}
44 changes: 44 additions & 0 deletions tests/integration/staking/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,47 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
vals = vals[:100]
require.Equal(t, abcivals, vals)
}

// TODO: refactor LSM TEST
func TestInitExportLiquidStakingGenesis(t *testing.T) {
// app, ctx, addrs := bootstrapGenesisTest(t, 2)
// address1, address2 := addrs[0], addrs[1]

// // Mock out a genesis state
// inGenesisState := types.GenesisState{
// Params: types.DefaultParams(),
// TokenizeShareRecords: []types.TokenizeShareRecord{
// {Id: 1, Owner: address1.String(), ModuleAccount: "module1", Validator: "val1"},
// {Id: 2, Owner: address2.String(), ModuleAccount: "module2", Validator: "val2"},
// },
// LastTokenizeShareRecordId: 2,
// TotalLiquidStakedTokens: sdk.NewInt(1_000_000),
// TokenizeShareLocks: []types.TokenizeShareLock{
// {
// Address: address1.String(),
// Status: types.TOKENIZE_SHARE_LOCK_STATUS_LOCKED.String(),
// },
// {
// Address: address2.String(),
// Status: types.TOKENIZE_SHARE_LOCK_STATUS_LOCK_EXPIRING.String(),
// CompletionTime: time.Date(2023, 1, 1, 1, 0, 0, 0, time.UTC),
// },
// },
// }

// // Call init and then export genesis - confirming the same state is returned
// staking.InitGenesis(ctx, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, &inGenesisState)
// outGenesisState := *staking.ExportGenesis(ctx, app.StakingKeeper)

// require.ElementsMatch(t, inGenesisState.TokenizeShareRecords, outGenesisState.TokenizeShareRecords,
// "tokenize share records")

// require.Equal(t, inGenesisState.LastTokenizeShareRecordId, outGenesisState.LastTokenizeShareRecordId,
// "last tokenize share record ID")

// require.Equal(t, inGenesisState.TotalLiquidStakedTokens.Int64(), outGenesisState.TotalLiquidStakedTokens.Int64(),
// "total liquid staked")

// require.ElementsMatch(t, inGenesisState.TokenizeShareLocks, outGenesisState.TokenizeShareLocks,
// "tokenize share locks")
}
Loading

0 comments on commit e7220e3

Please sign in to comment.