From 9cd004f0ac3331568b711f1744b8a6bda51fece6 Mon Sep 17 00:00:00 2001 From: Xiaoyu Chen Date: Sun, 5 Jun 2022 11:46:49 -0700 Subject: [PATCH 1/2] Use slice based loop instead of map based loop in Begin/EndBlock --- x/dex/cache/cache.go | 26 ++++++++ x/dex/keeper/end_block_cancel_orders.go | 38 ++++++----- x/dex/keeper/end_block_liquidation.go | 23 +++---- x/dex/keeper/end_block_place_orders.go | 66 ++++++++++---------- x/dex/keeper/keeper.go | 6 +- x/dex/keeper/msg_server_liquidate.go | 4 +- x/dex/keeper/msg_server_register_contract.go | 2 +- x/dex/module.go | 25 ++++---- 8 files changed, 112 insertions(+), 78 deletions(-) diff --git a/x/dex/cache/cache.go b/x/dex/cache/cache.go index 268d04047d..48d186897e 100644 --- a/x/dex/cache/cache.go +++ b/x/dex/cache/cache.go @@ -326,3 +326,29 @@ func (o *OrderCancellations) UpdateForLiquidation(liquidatedAccounts []string) { }) } } + +type LiquidationRequest struct { + Requestor string + AccountToLiquidate string +} + +type LiquidationRequests []LiquidationRequest + +func (lrs *LiquidationRequests) IsAccountLiquidating(accountToLiquidate string) bool { + for _, lr := range *lrs { + if lr.AccountToLiquidate == accountToLiquidate { + return true + } + } + return false +} + +func (lrs *LiquidationRequests) AddNewLiquidationRequest(requestor string, accountToLiquidate string) { + if lrs.IsAccountLiquidating(accountToLiquidate) { + return + } + *lrs = append(*lrs, LiquidationRequest{ + Requestor: requestor, + AccountToLiquidate: accountToLiquidate, + }) +} diff --git a/x/dex/keeper/end_block_cancel_orders.go b/x/dex/keeper/end_block_cancel_orders.go index f2b736cdd2..a6cd37b251 100644 --- a/x/dex/keeper/end_block_cancel_orders.go +++ b/x/dex/keeper/end_block_cancel_orders.go @@ -10,33 +10,37 @@ import ( otrace "go.opentelemetry.io/otel/trace" ) -func (k *Keeper) HandleEBCancelOrders(ctx context.Context, sdkCtx sdk.Context, tracer *otrace.Tracer, contractAddr string) { +func (k *Keeper) HandleEBCancelOrders(ctx context.Context, sdkCtx sdk.Context, tracer *otrace.Tracer, contractAddr string, registeredPairs []types.Pair) { _, span := (*tracer).Start(ctx, "SudoCancelOrders") span.SetAttributes(attribute.String("contractAddr", contractAddr)) - msg := k.getCancelSudoMsg(contractAddr) + msg := k.getCancelSudoMsg(contractAddr, registeredPairs) _ = k.CallContractSudo(sdkCtx, contractAddr, msg) - for pair, orderCancellations := range k.OrderCancellations[contractAddr] { - for _, orderCancellation := range orderCancellations.OrderCancellations { - k.Orders[contractAddr][pair].AddCancelOrder(dexcache.CancelOrder{ - Creator: orderCancellation.Creator, - Price: orderCancellation.Price, - Quantity: orderCancellation.Quantity, - Direction: orderCancellation.Direction, - Effect: orderCancellation.Effect, - Leverage: orderCancellation.Leverage, - }) + for _, pair := range registeredPairs { + pairStr := pair.String() + if orderCancellations, ok := k.OrderCancellations[contractAddr][pairStr]; ok { + for _, orderCancellation := range orderCancellations.OrderCancellations { + k.Orders[contractAddr][pairStr].AddCancelOrder(dexcache.CancelOrder{ + Creator: orderCancellation.Creator, + Price: orderCancellation.Price, + Quantity: orderCancellation.Quantity, + Direction: orderCancellation.Direction, + Effect: orderCancellation.Effect, + Leverage: orderCancellation.Leverage, + }) + } } } span.End() } -func (k *Keeper) getCancelSudoMsg(contractAddr string) types.SudoOrderCancellationMsg { - pairToOrderCancellations := k.OrderCancellations[contractAddr] +func (k *Keeper) getCancelSudoMsg(contractAddr string, registeredPairs []types.Pair) types.SudoOrderCancellationMsg { contractOrderCancellations := []types.ContractOrderCancellation{} - for _, orderCancellations := range pairToOrderCancellations { - for _, orderCancellation := range orderCancellations.OrderCancellations { - contractOrderCancellations = append(contractOrderCancellations, dexcache.ToContractOrderCancellation(orderCancellation)) + for _, pair := range registeredPairs { + if orderCancellations, ok := k.OrderCancellations[contractAddr][pair.String()]; ok { + for _, orderCancellation := range orderCancellations.OrderCancellations { + contractOrderCancellations = append(contractOrderCancellations, dexcache.ToContractOrderCancellation(orderCancellation)) + } } } return types.SudoOrderCancellationMsg{ diff --git a/x/dex/keeper/end_block_liquidation.go b/x/dex/keeper/end_block_liquidation.go index 7124e26ba1..996546a4be 100644 --- a/x/dex/keeper/end_block_liquidation.go +++ b/x/dex/keeper/end_block_liquidation.go @@ -12,7 +12,7 @@ import ( otrace "go.opentelemetry.io/otel/trace" ) -func (k *Keeper) HandleEBLiquidation(ctx context.Context, sdkCtx sdk.Context, tracer *otrace.Tracer, contractAddr string) { +func (k *Keeper) HandleEBLiquidation(ctx context.Context, sdkCtx sdk.Context, tracer *otrace.Tracer, contractAddr string, registeredPairs []types.Pair) { _, liquidationSpan := (*tracer).Start(ctx, "SudoLiquidation") liquidationSpan.SetAttributes(attribute.String("contractAddr", contractAddr)) @@ -22,12 +22,13 @@ func (k *Keeper) HandleEBLiquidation(ctx context.Context, sdkCtx sdk.Context, tr json.Unmarshal(data, &response) sdkCtx.Logger().Info(fmt.Sprintf("Sudo liquidate response data: %s", response)) - for _, cancellations := range k.OrderCancellations[contractAddr] { - cancellations.UpdateForLiquidation(response.SuccessfulAccounts) - } - - for _, placements := range k.OrderPlacements[contractAddr] { - placements.FilterOutAccounts(response.SuccessfulAccounts) + for _, pair := range registeredPairs { + if cancellations, ok := k.OrderCancellations[contractAddr][pair.String()]; ok { + cancellations.UpdateForLiquidation(response.SuccessfulAccounts) + } + if placements, ok := k.OrderPlacements[contractAddr][pair.String()]; ok { + placements.FilterOutAccounts(response.SuccessfulAccounts) + } } k.placeLiquidationOrders(sdkCtx, contractAddr, response.LiquidationOrders) @@ -54,12 +55,12 @@ func (k *Keeper) placeLiquidationOrders(ctx sdk.Context, contractAddr string, li } func (k *Keeper) getLiquidationSudoMsg(contractAddr string) types.SudoLiquidationMsg { - liquidationRequestorToAccounts := k.LiquidationRequests[contractAddr] + cachedLiquidationRequests := k.LiquidationRequests[contractAddr] liquidationRequests := []types.LiquidationRequest{} - for requestor, account := range liquidationRequestorToAccounts { + for _, cachedLiquidationRequest := range *cachedLiquidationRequests { liquidationRequests = append(liquidationRequests, types.LiquidationRequest{ - Requestor: requestor, - Account: account, + Requestor: cachedLiquidationRequest.Requestor, + Account: cachedLiquidationRequest.AccountToLiquidate, }) } return types.SudoLiquidationMsg{ diff --git a/x/dex/keeper/end_block_place_orders.go b/x/dex/keeper/end_block_place_orders.go index 7b4342b43d..17f8128b9e 100644 --- a/x/dex/keeper/end_block_place_orders.go +++ b/x/dex/keeper/end_block_place_orders.go @@ -12,52 +12,54 @@ import ( otrace "go.opentelemetry.io/otel/trace" ) -func (k *Keeper) HandleEBPlaceOrders(ctx context.Context, sdkCtx sdk.Context, tracer *otrace.Tracer, contractAddr string) { +func (k *Keeper) HandleEBPlaceOrders(ctx context.Context, sdkCtx sdk.Context, tracer *otrace.Tracer, contractAddr string, registeredPairs []types.Pair) { _, span := (*tracer).Start(ctx, "SudoPlaceOrders") span.SetAttributes(attribute.String("contractAddr", contractAddr)) - msg := k.getPlaceSudoMsg(contractAddr) + msg := k.getPlaceSudoMsg(contractAddr, registeredPairs) data := k.CallContractSudo(sdkCtx, contractAddr, msg) response := types.SudoOrderPlacementResponse{} json.Unmarshal(data, &response) sdkCtx.Logger().Info(fmt.Sprintf("Sudo response data: %s", response)) - for pair, orderPlacements := range k.OrderPlacements[contractAddr] { - orderPlacements.FilterOutIds(response.UnsuccessfulOrderIds) - for _, orderPlacement := range orderPlacements.Orders { - switch orderPlacement.OrderType { - case types.OrderType_LIMIT: - k.Orders[contractAddr][pair].AddLimitOrder(dexcache.LimitOrder{ - Creator: orderPlacement.Creator, - Price: orderPlacement.Price, - Quantity: orderPlacement.Quantity, - Direction: orderPlacement.Direction, - Effect: orderPlacement.Effect, - Leverage: orderPlacement.Leverage, - }) - case types.OrderType_MARKET: - k.Orders[contractAddr][pair].AddMarketOrder(dexcache.MarketOrder{ - Creator: orderPlacement.Creator, - WorstPrice: orderPlacement.Price, - Quantity: orderPlacement.Quantity, - Direction: orderPlacement.Direction, - Effect: orderPlacement.Effect, - Leverage: orderPlacement.Leverage, - }) - default: - panic("Unknown order type") + for _, pair := range registeredPairs { + pairStr := pair.String() + if orderPlacements, ok := k.OrderPlacements[contractAddr][pairStr]; ok { + orderPlacements.FilterOutIds(response.UnsuccessfulOrderIds) + for _, orderPlacement := range orderPlacements.Orders { + switch orderPlacement.OrderType { + case types.OrderType_LIMIT: + k.Orders[contractAddr][pairStr].AddLimitOrder(dexcache.LimitOrder{ + Creator: orderPlacement.Creator, + Price: orderPlacement.Price, + Quantity: orderPlacement.Quantity, + Direction: orderPlacement.Direction, + Effect: orderPlacement.Effect, + Leverage: orderPlacement.Leverage, + }) + case types.OrderType_MARKET: + k.Orders[contractAddr][pairStr].AddMarketOrder(dexcache.MarketOrder{ + Creator: orderPlacement.Creator, + WorstPrice: orderPlacement.Price, + Quantity: orderPlacement.Quantity, + Direction: orderPlacement.Direction, + Effect: orderPlacement.Effect, + Leverage: orderPlacement.Leverage, + }) + } } } } span.End() } -func (k *Keeper) getPlaceSudoMsg(contractAddr string) types.SudoOrderPlacementMsg { - pairToOrderPlacements := k.OrderPlacements[contractAddr] +func (k *Keeper) getPlaceSudoMsg(contractAddr string, registeredPairs []types.Pair) types.SudoOrderPlacementMsg { contractOrderPlacements := []types.ContractOrderPlacement{} - for _, orderPlacements := range pairToOrderPlacements { - for _, orderPlacement := range orderPlacements.Orders { - if !orderPlacement.Liquidation { - contractOrderPlacements = append(contractOrderPlacements, dexcache.ToContractOrderPlacement(orderPlacement)) + for _, pair := range registeredPairs { + if orderPlacements, ok := k.OrderPlacements[contractAddr][pair.String()]; ok { + for _, orderPlacement := range orderPlacements.Orders { + if !orderPlacement.Liquidation { + contractOrderPlacements = append(contractOrderPlacements, dexcache.ToContractOrderPlacement(orderPlacement)) + } } } } diff --git a/x/dex/keeper/keeper.go b/x/dex/keeper/keeper.go index b6b7ff3689..d2098dce5e 100644 --- a/x/dex/keeper/keeper.go +++ b/x/dex/keeper/keeper.go @@ -27,7 +27,7 @@ type ( DepositInfo map[string]*dexcache.DepositInfo BankKeeper bankkeeper.Keeper OrderCancellations map[string]map[string]*dexcache.OrderCancellations - LiquidationRequests map[string]map[string]string + LiquidationRequests map[string]*dexcache.LiquidationRequests WasmKeeper wasm.Keeper } ) @@ -51,7 +51,7 @@ func NewPlainKeeper( OrderPlacements: map[string]map[string]*dexcache.OrderPlacements{}, DepositInfo: map[string]*dexcache.DepositInfo{}, OrderCancellations: map[string]map[string]*dexcache.OrderCancellations{}, - LiquidationRequests: map[string]map[string]string{}, + LiquidationRequests: map[string]*dexcache.LiquidationRequests{}, } } @@ -79,7 +79,7 @@ func NewKeeper( DepositInfo: map[string]*dexcache.DepositInfo{}, BankKeeper: bankKeeper, OrderCancellations: map[string]map[string]*dexcache.OrderCancellations{}, - LiquidationRequests: map[string]map[string]string{}, + LiquidationRequests: map[string]*dexcache.LiquidationRequests{}, WasmKeeper: wasmKeeper, } } diff --git a/x/dex/keeper/msg_server_liquidate.go b/x/dex/keeper/msg_server_liquidate.go index 43da9bfbd4..4897602e2b 100644 --- a/x/dex/keeper/msg_server_liquidate.go +++ b/x/dex/keeper/msg_server_liquidate.go @@ -11,9 +11,7 @@ func (k msgServer) Liquidate(goCtx context.Context, msg *types.MsgLiquidation) ( defer span.End() liquidationRequestorToAccount := k.LiquidationRequests[msg.GetContractAddr()] - if _, ok := liquidationRequestorToAccount[msg.GetAccountToLiquidate()]; !ok { - liquidationRequestorToAccount[msg.GetAccountToLiquidate()] = msg.GetAccountToLiquidate() - } + liquidationRequestorToAccount.AddNewLiquidationRequest(msg.Creator, msg.AccountToLiquidate) return &types.MsgLiquidationResponse{}, nil } diff --git a/x/dex/keeper/msg_server_register_contract.go b/x/dex/keeper/msg_server_register_contract.go index c18147f150..cd14c2d1b8 100644 --- a/x/dex/keeper/msg_server_register_contract.go +++ b/x/dex/keeper/msg_server_register_contract.go @@ -21,7 +21,7 @@ func (k msgServer) RegisterContract(goCtx context.Context, msg *types.MsgRegiste k.OrderPlacements[contractAddr] = map[string]*dexcache.OrderPlacements{} k.OrderCancellations[contractAddr] = map[string]*dexcache.OrderCancellations{} k.DepositInfo[contractAddr] = dexcache.NewDepositInfo() - k.LiquidationRequests[contractAddr] = map[string]string{} + k.LiquidationRequests[contractAddr] = &dexcache.LiquidationRequests{} return &types.MsgRegisterContractResponse{}, nil } diff --git a/x/dex/module.go b/x/dex/module.go index 31fbc657d4..c8538a0fe4 100644 --- a/x/dex/module.go +++ b/x/dex/module.go @@ -218,7 +218,7 @@ func (am AppModule) beginBlockForContract(ctx sdk.Context, contractAddr string) am.keeper.OrderPlacements[contractAddr] = map[string]*dexcache.OrderPlacements{} am.keeper.OrderCancellations[contractAddr] = map[string]*dexcache.OrderCancellations{} am.keeper.DepositInfo[contractAddr] = dexcache.NewDepositInfo() - am.keeper.LiquidationRequests[contractAddr] = map[string]string{} + am.keeper.LiquidationRequests[contractAddr] = &dexcache.LiquidationRequests{} for _, pair := range am.keeper.GetAllRegisteredPairs(ctx, contractAddr) { ctx.Logger().Info(pair.String()) am.keeper.Orders[contractAddr][pair.String()] = dexcache.NewOrders() @@ -291,12 +291,13 @@ func (am AppModule) endBlockForContract(ctx sdk.Context, contractAddr string) { span.SetAttributes(attribute.String("contract", contractAddr)) defer span.End() - am.keeper.HandleEBLiquidation(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr) - am.keeper.HandleEBCancelOrders(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr) - am.keeper.HandleEBPlaceOrders(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr) + registeredPairs := am.keeper.GetAllRegisteredPairs(ctx, contractAddr) + am.keeper.HandleEBLiquidation(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr, registeredPairs) + am.keeper.HandleEBCancelOrders(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr, registeredPairs) + am.keeper.HandleEBPlaceOrders(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr, registeredPairs) am.keeper.OrderCancellations[contractAddr] = map[string]*dexcache.OrderCancellations{} - for _, pair := range am.keeper.GetAllRegisteredPairs(ctx, contractAddr) { + for _, pair := range registeredPairs { am.keeper.OrderCancellations[contractAddr][pair.String()] = dexcache.NewOrderCancellations() orders := am.keeper.Orders[contractAddr][pair.String()] ctx.Logger().Info(pair.String()) @@ -378,7 +379,7 @@ func (am AppModule) endBlockForContract(ctx sdk.Context, contractAddr string) { Epoch: int64(currentEpoch), Entries: []*types.SettlementEntry{}, } - settlementMap := map[types.Pair]*types.Settlements{} + settlementMap := map[string]*types.Settlements{} for _, s := range settlements { ctx.Logger().Info(s.String()) @@ -389,18 +390,20 @@ func (am AppModule) endBlockForContract(ctx sdk.Context, contractAddr string) { PriceDenom: priceDenom, AssetDenom: assetDenom, } - if settlements, ok := settlementMap[pair]; ok { + if settlements, ok := settlementMap[pair.String()]; ok { settlements.Entries = append(settlements.Entries, &settlementEntry) } else { - settlementMap[pair] = &types.Settlements{ + settlementMap[pair.String()] = &types.Settlements{ Epoch: int64(currentEpoch), Entries: []*types.SettlementEntry{&settlementEntry}, } } allSettlements.Entries = append(allSettlements.Entries, &settlementEntry) } - for s, settlementEntries := range settlementMap { - am.keeper.SetSettlements(ctx, contractAddr, s.PriceDenom, s.AssetDenom, *settlementEntries) + for _, pair := range registeredPairs { + if settlementEntries, ok := settlementMap[pair.String()]; ok { + am.keeper.SetSettlements(ctx, contractAddr, pair.PriceDenom, pair.AssetDenom, *settlementEntries) + } } nativeSettlementMsg := types.SudoSettlementMsg{ @@ -450,7 +453,7 @@ func (am AppModule) endBlockForContract(ctx sdk.Context, contractAddr string) { } } // Cancel unfilled market orders - am.keeper.HandleEBCancelOrders(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr) + am.keeper.HandleEBCancelOrders(spanCtx, ctx, am.tracingInfo.Tracer, contractAddr, registeredPairs) } func getTwapPrice(prices []uint64) uint64 { From dece1602a550976228a7f1bcec430a9fdf0ffa8a Mon Sep 17 00:00:00 2001 From: Xiaoyu Chen Date: Sun, 5 Jun 2022 17:15:39 -0700 Subject: [PATCH 2/2] add idempotency test --- app/abci.go | 4 +- app/app.go | 3 +- app/app_test.go | 29 ++++++ app/test_helpers.go | 211 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 app/app_test.go create mode 100644 app/test_helpers.go diff --git a/app/abci.go b/app/abci.go index 1ca0735364..69cbb6cdc3 100644 --- a/app/abci.go +++ b/app/abci.go @@ -39,7 +39,9 @@ func (app *App) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { } func (app *App) Commit() (res abci.ResponseCommit) { - defer (*app.tracingInfo.BlockSpan).End() + if app.tracingInfo.BlockSpan != nil { + defer (*app.tracingInfo.BlockSpan).End() + } _, span := (*app.tracingInfo.Tracer).Start(app.tracingInfo.TracerContext, "Commit") defer span.End() app.tracingInfo.TracerContext = context.Background() diff --git a/app/app.go b/app/app.go index 3e8ad22fc9..ebcb04bd3b 100644 --- a/app/app.go +++ b/app/app.go @@ -3,12 +3,13 @@ package app import ( "context" "fmt" - appparams "github.com/sei-protocol/sei-chain/app/params" "io" "os" "path/filepath" "strings" + appparams "github.com/sei-protocol/sei-chain/app/params" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" diff --git a/app/app_test.go b/app/app_test.go new file mode 100644 index 0000000000..6e35e34a70 --- /dev/null +++ b/app/app_test.go @@ -0,0 +1,29 @@ +package app_test + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/sei-protocol/sei-chain/app" + "github.com/stretchr/testify/require" +) + +func TestEmptyBlockIdempotency(t *testing.T) { + commitData := [][]byte{} + tm := time.Now().UTC() + valPub := secp256k1.GenPrivKey().PubKey() + + for i := 1; i <= 10; i++ { + testWrapper := app.NewTestWrapper(t, tm, valPub) + testWrapper.BeginBlock() + testWrapper.EndBlock() + data := testWrapper.App.Commit().Data + commitData = append(commitData, data) + } + + referenceData := commitData[0] + for _, data := range commitData[1:] { + require.Equal(t, len(referenceData), len(data)) + } +} diff --git a/app/test_helpers.go b/app/test_helpers.go new file mode 100644 index 0000000000..5ab3d7733d --- /dev/null +++ b/app/test_helpers.go @@ -0,0 +1,211 @@ +package app + +import ( + "encoding/json" + "os" + "testing" + "time" + + "github.com/CosmWasm/wasmd/x/wasm" + crptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking/teststaking" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" +) + +type TestWrapper struct { + suite.Suite + + App *App + Ctx sdk.Context +} + +func NewTestWrapper(t *testing.T, tm time.Time, valPub crptotypes.PubKey) *TestWrapper { + appPtr := Setup(false) + wrapper := &TestWrapper{ + App: appPtr, + Ctx: appPtr.BaseApp.NewContext(false, tmproto.Header{Height: 1, ChainID: "sei-test", Time: tm}), + } + wrapper.SetT(t) + wrapper.setupValidator(stakingtypes.Bonded, valPub) + return wrapper +} + +func (s *TestWrapper) FundAcc(acc sdk.AccAddress, amounts sdk.Coins) { + err := s.App.BankKeeper.MintCoins(s.Ctx, minttypes.ModuleName, amounts) + s.Require().NoError(err) + + err = s.App.BankKeeper.SendCoinsFromModuleToAccount(s.Ctx, minttypes.ModuleName, acc, amounts) + s.Require().NoError(err) +} + +func (s *TestWrapper) setupValidator(bondStatus stakingtypes.BondStatus, valPub crptotypes.PubKey) sdk.ValAddress { + valAddr := sdk.ValAddress(valPub.Address()) + bondDenom := s.App.StakingKeeper.GetParams(s.Ctx).BondDenom + selfBond := sdk.NewCoins(sdk.Coin{Amount: sdk.NewInt(100), Denom: bondDenom}) + + s.FundAcc(sdk.AccAddress(valAddr), selfBond) + + sh := teststaking.NewHelper(s.Suite.T(), s.Ctx, s.App.StakingKeeper) + msg := sh.CreateValidatorMsg(valAddr, valPub, selfBond[0].Amount) + sh.Handle(msg, true) + + val, found := s.App.StakingKeeper.GetValidator(s.Ctx, valAddr) + s.Require().True(found) + + val = val.UpdateStatus(bondStatus) + s.App.StakingKeeper.SetValidator(s.Ctx, val) + + consAddr, err := val.GetConsAddr() + s.Suite.Require().NoError(err) + + signingInfo := slashingtypes.NewValidatorSigningInfo( + consAddr, + s.Ctx.BlockHeight(), + 0, + time.Unix(0, 0), + false, + 0, + ) + s.App.SlashingKeeper.SetValidatorSigningInfo(s.Ctx, consAddr, signingInfo) + + return valAddr +} + +func (s *TestWrapper) BeginBlock() { + var proposer sdk.ValAddress + + validators := s.App.StakingKeeper.GetAllValidators(s.Ctx) + s.Require().Equal(1, len(validators)) + + valAddrFancy, err := validators[0].GetConsAddr() + s.Require().NoError(err) + proposer = valAddrFancy.Bytes() + + validator, found := s.App.StakingKeeper.GetValidator(s.Ctx, proposer) + s.Assert().True(found) + + valConsAddr, err := validator.GetConsAddr() + + s.Require().NoError(err) + + valAddr := valConsAddr.Bytes() + + newBlockTime := s.Ctx.BlockTime().Add(2 * time.Second) + + header := tmproto.Header{Height: s.Ctx.BlockHeight() + 1, Time: newBlockTime} + newCtx := s.Ctx.WithBlockTime(newBlockTime).WithBlockHeight(s.Ctx.BlockHeight() + 1) + s.Ctx = newCtx + lastCommitInfo := abci.LastCommitInfo{ + Votes: []abci.VoteInfo{{ + Validator: abci.Validator{Address: valAddr, Power: 1000}, + SignedLastBlock: true, + }}, + } + reqBeginBlock := abci.RequestBeginBlock{Header: header, LastCommitInfo: lastCommitInfo} + + s.App.BeginBlocker(s.Ctx, reqBeginBlock) +} + +func (s *TestWrapper) EndBlock() { + reqEndBlock := abci.RequestEndBlock{Height: s.Ctx.BlockHeight()} + s.App.EndBlocker(s.Ctx, reqEndBlock) +} + +type EmptyAppOptions struct{} + +func (ao EmptyAppOptions) Get(o string) interface{} { + return nil +} + +func Setup(isCheckTx bool) *App { + db := dbm.NewMemDB() + encodingConfig := MakeEncodingConfig() + cdc := encodingConfig.Marshaler + app := New( + log.NewNopLogger(), + db, + nil, + true, + map[int64]bool{}, + DefaultNodeHome, + 5, + encodingConfig, + wasm.EnableAllProposals, + EmptyAppOptions{}, + EmptyWasmOpts, + ) + if !isCheckTx { + genesisState := NewDefaultGenesisState(cdc) + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + if err != nil { + panic(err) + } + + app.InitChain( + abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: simapp.DefaultConsensusParams, + AppStateBytes: stateBytes, + }, + ) + } + + return app +} + +func SetupTestingAppWithLevelDb(isCheckTx bool) (*App, func()) { + dir := "sei_testing" + db, err := sdk.NewLevelDB("sei_leveldb_testing", dir) + if err != nil { + panic(err) + } + encodingConfig := MakeEncodingConfig() + cdc := encodingConfig.Marshaler + app := New( + log.NewNopLogger(), + db, + nil, + true, + map[int64]bool{}, + DefaultNodeHome, + 5, + encodingConfig, + wasm.EnableAllProposals, + EmptyAppOptions{}, + EmptyWasmOpts, + ) + if !isCheckTx { + genesisState := NewDefaultGenesisState(cdc) + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + if err != nil { + panic(err) + } + + app.InitChain( + abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: simapp.DefaultConsensusParams, + AppStateBytes: stateBytes, + }, + ) + } + + cleanupFn := func() { + db.Close() + err = os.RemoveAll(dir) + if err != nil { + panic(err) + } + } + + return app, cleanupFn +}