diff --git a/e2e/tests/virtualgroup_test.go b/e2e/tests/virtualgroup_test.go index 188e4eebb..459eeabda 100644 --- a/e2e/tests/virtualgroup_test.go +++ b/e2e/tests/virtualgroup_test.go @@ -797,8 +797,8 @@ func (s *VirtualGroupTestSuite) TestSPExit() { // 7. SP-x complete exit, it would fail due to there are family and GVG binded to it. s.SendTxBlockWithExpectErrorString( &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{ - Operator: spx.OperatorKey.GetAddr().String(), - StorageProvider: spx.OperatorKey.GetAddr().String()}, + StorageProvider: spx.OperatorKey.GetAddr().String(), + ExitStorageProvider: spx.OperatorKey.GetAddr().String()}, spx.OperatorKey, "not swap out from all the family") @@ -857,8 +857,8 @@ func (s *VirtualGroupTestSuite) TestSPExit() { // 15. SP-x tries to complete exit, but would fail, since SP-2 has a GVG that includes SP-x [2|x,3,4,5,6,7] s.SendTxBlockWithExpectErrorString( &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{ - Operator: spx.OperatorKey.GetAddr().String(), - StorageProvider: spx.OperatorKey.GetAddr().String()}, + StorageProvider: spx.OperatorKey.GetAddr().String(), + ExitStorageProvider: spx.OperatorKey.GetAddr().String()}, spx.OperatorKey, "not swap out from all the gvgs") @@ -908,7 +908,7 @@ func (s *VirtualGroupTestSuite) TestSPExit() { // 23. SP-x complete exit success s.SendTxBlock( spx.OperatorKey, - &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{StorageProvider: spx.OperatorKey.GetAddr().String()}, + &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{StorageProvider: spx.OperatorKey.GetAddr().String(), ExitStorageProvider: spx.OperatorKey.GetAddr().String()}, ) // 24 SP-x no longer found on chain @@ -957,8 +957,8 @@ func (s *VirtualGroupTestSuite) TestSPExit2() { s.SendTxBlock( spx.OperatorKey, &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{ - Operator: spx.OperatorKey.GetAddr().String(), - StorageProvider: spx.OperatorKey.GetAddr().String()}, + StorageProvider: spx.OperatorKey.GetAddr().String(), + ExitStorageProvider: spx.OperatorKey.GetAddr().String()}, ) _, err = s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: spx.Info.Id}) s.Require().Error(err) @@ -1001,24 +1001,32 @@ func (s *VirtualGroupTestSuite) TestSPExit2() { s.Require().Equal(familyID, gvgAfterSwapIn.GlobalVirtualGroup.FamilyId) s.Require().Equal([]uint32{spz.Info.Id, 3, 4, 5, 6, 7}, gvgAfterSwapIn.GlobalVirtualGroup.SecondarySpIds) - // 11 SP-y complete the exit by sp-z + // 11 complete SPy's exit by sp-z s.SendTxBlock( - spy.OperatorKey, + spz.OperatorKey, &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{ - Operator: spz.OperatorKey.GetAddr().String(), - StorageProvider: spy.OperatorKey.GetAddr().String()}, + StorageProvider: spz.OperatorKey.GetAddr().String(), + ExitStorageProvider: spy.OperatorKey.GetAddr().String()}, ) _, err = s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: spy.Info.Id}) s.Require().Error(err) } func (s *VirtualGroupTestSuite) TestSPForceExit() { + ctx := context.Background() user := s.GenAndChargeAccounts(1, 1000000)[0] // 1. create SPs spx := s.BaseSuite.CreateNewStorageProvider() spy := s.BaseSuite.CreateNewStorageProvider() + + // gov module balance + govModuleBalance, err := s.Client.Balance(context.Background(), &types2.QueryBalanceRequest{ + Denom: s.Config.Denom, + Address: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + }) + s.Require().NoError(err) // 2. SP-x creates a new family with a gvg: {[x|2,3,4,5,6,7]} gvgID, familyID := s.BaseSuite.CreateGlobalVirtualGroup(spx, 0, []uint32{2, 3, 4, 5, 6, 7}, 1) @@ -1093,7 +1101,7 @@ func (s *VirtualGroupTestSuite) TestSPForceExit() { s.Require().Equal(swapInInfo.SwapInInfo.SuccessorSpId, spy.Info.Id) s.Require().Equal(swapInInfo.SwapInInfo.TargetSpId, spx.Info.Id) - // object not found + // swapin info not found _, err = s.Client.SwapInInfo(context.Background(), &virtualgroupmoduletypes.QuerySwapInInfoRequest{ GlobalVirtualGroupId: gvgID, }) @@ -1131,10 +1139,17 @@ func (s *VirtualGroupTestSuite) TestSPForceExit() { // 11 SP-y help complete the exit s.SendTxBlock( spy.OperatorKey, - &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{Operator: spy.OperatorKey.GetAddr().String(), StorageProvider: spx.OperatorKey.GetAddr().String()}, + &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{StorageProvider: spy.OperatorKey.GetAddr().String(), ExitStorageProvider: spx.OperatorKey.GetAddr().String()}, ) - _, err = s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: spy.Info.Id}) + _, err = s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: spx.Info.Id}) s.Require().Error(err) + + govModuleBalanceAfterSPForcedExit, err := s.Client.Balance(context.Background(), &types2.QueryBalanceRequest{ + Denom: s.Config.Denom, + Address: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + }) + s.Require().NoError(err) + s.Require().Equal(govModuleBalance.Balance.Amount.Add(types.NewIntFromInt64WithDecimal(10000, types.DecimalBNB)), govModuleBalanceAfterSPForcedExit.Balance.Amount) } func (s *VirtualGroupTestSuite) updateParams(params virtualgroupmoduletypes.Params) { @@ -1273,7 +1288,7 @@ func (s *VirtualGroupTestSuite) TestSPExit_SwapInfo_Expired() { // sp-x completes the exit s.SendTxBlock( spx.OperatorKey, - &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{StorageProvider: spx.OperatorKey.GetAddr().String()}, + &virtualgroupmoduletypes.MsgCompleteStorageProviderExit{StorageProvider: spx.OperatorKey.GetAddr().String(), ExitStorageProvider: spx.OperatorKey.GetAddr().String()}, ) _, err = s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: spx.Info.Id}) s.Require().Error(err) diff --git a/x/challenge/abci.go b/x/challenge/abci.go index 990bed693..c6fc07360 100644 --- a/x/challenge/abci.go +++ b/x/challenge/abci.go @@ -2,6 +2,7 @@ package challenge import ( "fmt" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/x/challenge/keeper/msg_server_submit.go b/x/challenge/keeper/msg_server_submit.go index d8b32de1a..291824e48 100644 --- a/x/challenge/keeper/msg_server_submit.go +++ b/x/challenge/keeper/msg_server_submit.go @@ -2,6 +2,7 @@ package keeper import ( "context" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "cosmossdk.io/errors" diff --git a/x/storage/keeper/keeper.go b/x/storage/keeper/keeper.go index 940d00983..25d25ad05 100644 --- a/x/storage/keeper/keeper.go +++ b/x/storage/keeper/keeper.go @@ -1182,7 +1182,7 @@ func (k Keeper) DiscontinueObject(ctx sdk.Context, operator sdk.AccAddress, buck } swapInInfo, found := k.virtualGroupKeeper.GetSwapInInfo(ctx, bucketInfo.GlobalVirtualGroupFamilyId, virtualgroupmoduletypes.NoSpecifiedGVGId) if !found || swapInInfo.TargetSpId != spInState.Id || swapInInfo.SuccessorSpId != sp.Id || uint64(ctx.BlockTime().Unix()) >= swapInInfo.ExpirationTime { - return errors.Wrapf(types.ErrAccessDenied, "the sp is allowed to do discontinue objects") + return errors.Wrapf(types.ErrAccessDenied, "the sp is not allowed to do discontinue objects") } } diff --git a/x/virtualgroup/keeper/keeper.go b/x/virtualgroup/keeper/keeper.go index dfccefcc8..a74b50091 100644 --- a/x/virtualgroup/keeper/keeper.go +++ b/x/virtualgroup/keeper/keeper.go @@ -708,31 +708,26 @@ func (k Keeper) SwapIn(ctx sdk.Context, gvgFamilyID uint32, gvgID uint32, succes func (k Keeper) setSwapInInfo(ctx sdk.Context, key []byte, successorSPID, targetSPID uint32, curTime uint64) error { store := ctx.KVStore(k.storeKey) + swapInInfo := &types.SwapInInfo{ + SuccessorSpId: successorSPID, + TargetSpId: targetSPID, + ExpirationTime: curTime + k.SwapInValidityPeriod(ctx), + } bz := store.Get(key) if bz == nil { - swapInInfo := &types.SwapInInfo{ - SuccessorSpId: successorSPID, - TargetSpId: targetSPID, - ExpirationTime: curTime + k.SwapInValidityPeriod(ctx), - } - store.Set(key, k.cdc.MustMarshal(swapInInfo)) - } else { - curSwapInInfo := &types.SwapInInfo{} - k.cdc.MustUnmarshal(bz, curSwapInInfo) - if curTime < curSwapInInfo.ExpirationTime { - return types.ErrSwapInFailed.Wrapf("already exist SP(ID=%d) try to swap in", curSwapInInfo.SuccessorSpId) - } - // override the stale swapIn info of prev successor sp - if curSwapInInfo.SuccessorSpId == successorSPID { - return types.ErrSwapInFailed.Wrapf("already tried to swap in but expired") - } - swapInInfo := &types.SwapInInfo{ - SuccessorSpId: successorSPID, - TargetSpId: targetSPID, - ExpirationTime: curTime + k.SwapInValidityPeriod(ctx), - } store.Set(key, k.cdc.MustMarshal(swapInInfo)) + return nil } + curSwapInInfo := &types.SwapInInfo{} + k.cdc.MustUnmarshal(bz, curSwapInInfo) + if curTime < curSwapInInfo.ExpirationTime { + return types.ErrSwapInFailed.Wrapf("already exist SP(ID=%d) try to swap in", curSwapInInfo.SuccessorSpId) + } + // override the stale swapIn info of prev successor sp + if curSwapInInfo.SuccessorSpId == successorSPID { + return types.ErrSwapInFailed.Wrapf("already tried to swap in but expired") + } + store.Set(key, k.cdc.MustMarshal(swapInInfo)) return nil } @@ -740,8 +735,7 @@ func (k Keeper) DeleteSwapInInfo(ctx sdk.Context, gvgFamilyID, gvgID uint32, suc store := ctx.KVStore(k.storeKey) swapInInfo := types.SwapInInfo{} - if gvgFamilyID != types.NoSpecifiedFamilyId { - key := types.GetSwapInFamilyKey(gvgFamilyID) + deleteSwapInfo := func(key []byte) error { bz := store.Get(key) if bz == nil { return types.ErrSwapInFailed.Wrapf("The swap info not found in blockchain.") @@ -751,17 +745,17 @@ func (k Keeper) DeleteSwapInInfo(ctx sdk.Context, gvgFamilyID, gvgID uint32, suc return sptypes.ErrStorageProviderNotFound.Wrapf("spID(%d) is different from the spID(%d) in swapInInfo", successorSPID, swapInInfo.SuccessorSpId) } store.Delete(key) - } else { - key := types.GetSwapInGVGKey(gvgID) - bz := store.Get(key) - if bz == nil { - return types.ErrSwapInFailed.Wrapf("The swap info not found in blockchain.") + return nil + } + + if gvgFamilyID != types.NoSpecifiedFamilyId { + if err := deleteSwapInfo(types.GetSwapInFamilyKey(gvgFamilyID)); err != nil { + return err } - k.cdc.MustUnmarshal(bz, &swapInInfo) - if swapInInfo.SuccessorSpId != successorSPID { - return sptypes.ErrStorageProviderNotFound.Wrapf("spID(%d) is different from the spID(%d) in swapInInfo", successorSPID, swapInInfo.SuccessorSpId) + } else { + if err := deleteSwapInfo(types.GetSwapInGVGKey(gvgID)); err != nil { + return err } - store.Delete(key) } if err := ctx.EventManager().EmitTypedEvents(&types.EventCancelSwapIn{ diff --git a/x/virtualgroup/keeper/msg_server.go b/x/virtualgroup/keeper/msg_server.go index 2f284fc90..eee3ae52a 100644 --- a/x/virtualgroup/keeper/msg_server.go +++ b/x/virtualgroup/keeper/msg_server.go @@ -2,7 +2,6 @@ package keeper import ( "context" - paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" sdkerrors "cosmossdk.io/errors" "cosmossdk.io/math" @@ -516,7 +515,7 @@ func (k msgServer) CompleteStorageProviderExit(goCtx context.Context, msg *types return nil, sptypes.ErrStorageProviderNotFound.Wrapf("Invalid address of SP") } - exitSP, found := k.spKeeper.GetStorageProviderByOperatorAddr(ctx, exitSPAddr) + exitSP, found = k.spKeeper.GetStorageProviderByOperatorAddr(ctx, exitSPAddr) if !found { return nil, sptypes.ErrStorageProviderNotFound.Wrapf("The address of SP is not found") } @@ -543,7 +542,7 @@ func (k msgServer) CompleteStorageProviderExit(goCtx context.Context, msg *types } else { forcedExit = true coins := sdk.NewCoins(sdk.NewCoin(k.spKeeper.DepositDenomForSP(ctx), exitSP.TotalDeposit)) - err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, sptypes.ModuleName, paymenttypes.ModuleName, coins) + err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, sptypes.ModuleName, govtypes.ModuleName, coins) if err != nil { return nil, err } @@ -631,21 +630,21 @@ func (k msgServer) StorageProviderForceExit(goCtx context.Context, msg *types.Ms sp, found := k.spKeeper.GetStorageProviderByOperatorAddr(ctx, spAddr) if !found { - return nil, sptypes.ErrStorageProviderNotFound.Wrapf("The SP with operator address %s must not found", msg.StorageProvider) + return nil, sptypes.ErrStorageProviderNotFound.Wrapf("The SP with operator address %s not found", msg.StorageProvider) } - exittingSPNum := uint32(0) + exitingSPNum := uint32(0) + maxSPExitingNum := k.SpConcurrentExitNum(ctx) sps := k.spKeeper.GetAllStorageProviders(ctx) for _, curSP := range sps { if curSP.Status == sptypes.STATUS_GRACEFUL_EXITING || curSP.Status == sptypes.STATUS_FORCED_EXITING { - exittingSPNum++ + exitingSPNum++ + if exitingSPNum >= maxSPExitingNum { + return nil, sptypes.ErrStorageProviderExitFailed.Wrapf("%d SP are exiting, allow %d sp exit concurrently", exitingSPNum, maxSPExitingNum) + } } } - maxSPExitingNum := k.SpConcurrentExitNum(ctx) - if exittingSPNum >= maxSPExitingNum { - return nil, sptypes.ErrStorageProviderExitFailed.Wrapf("%d SP are exiting, allow %d sp exit concurrently", exittingSPNum, maxSPExitingNum) - } // Governance can put an SP into force exiting status no matter what status it is in. sp.Status = sptypes.STATUS_FORCED_EXITING diff --git a/x/virtualgroup/keeper/v1/params.pb.go b/x/virtualgroup/keeper/v1/params.pb.go index 145ad035e..14d83dfdc 100644 --- a/x/virtualgroup/keeper/v1/params.pb.go +++ b/x/virtualgroup/keeper/v1/params.pb.go @@ -1,7 +1,4 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: greenfield/virtualgroup/params.proto - -package types +package v1 import ( fmt "fmt" @@ -105,13 +102,13 @@ func (m *Params) GetMaxStoreSizePerFamily() uint64 { return 0 } -func init() { - proto.RegisterType((*Params)(nil), "greenfield.virtualgroup.Params") -} - -func init() { - proto.RegisterFile("greenfield/virtualgroup/params.proto", fileDescriptor_d8ecf89dd5128885) -} +//func init() { +// proto.RegisterType((*Params)(nil), "greenfield.virtualgroup.Params") +//} +// +//func init() { +// proto.RegisterFile("greenfield/virtualgroup/params.proto", fileDescriptor_d8ecf89dd5128885) +//} var fileDescriptor_d8ecf89dd5128885 = []byte{ // 414 bytes of a gzipped FileDescriptorProto diff --git a/x/virtualgroup/module.go b/x/virtualgroup/module.go index 29b3e65f1..f64b43438 100644 --- a/x/virtualgroup/module.go +++ b/x/virtualgroup/module.go @@ -143,7 +143,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion is a sequence number for state-breaking change of the module. It should be incremented on each consensus-breaking change introduced by the module. To avoid wrong/empty versions, the initial version should be set to 1 -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock contains the logic that is automatically triggered at the beginning of each block func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/virtualgroup/types/expected_keepers_mocks.go b/x/virtualgroup/types/expected_keepers_mocks.go index 06f27e5e2..3ea161160 100644 --- a/x/virtualgroup/types/expected_keepers_mocks.go +++ b/x/virtualgroup/types/expected_keepers_mocks.go @@ -231,6 +231,11 @@ type MockBankKeeper struct { recorder *MockBankKeeperMockRecorder } +func (m *MockBankKeeper) SendCoinsFromModuleToModule(ctx types0.Context, senderModule, recipientModule string, amt types0.Coins) error { + //TODO implement me + panic("implement me") +} + // MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. type MockBankKeeperMockRecorder struct { mock *MockBankKeeper