-
Notifications
You must be signed in to change notification settings - Fork 29
feat(poa): add validator self-removal message #146
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
Changes from all commits
417d913
453c00b
ae63a8d
0c66f64
5015bbc
e5f1793
2feeba8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,15 +5,20 @@ import ( | |||||||||||||||||||||||||||||||
| "math/rand" | ||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| sdkmath "cosmossdk.io/math" | ||||||||||||||||||||||||||||||||
| abcitypes "github.com/cometbft/cometbft/abci/types" | ||||||||||||||||||||||||||||||||
| cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" | ||||||||||||||||||||||||||||||||
| cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" | ||||||||||||||||||||||||||||||||
| sdktypes "github.com/cosmos/cosmos-sdk/types" | ||||||||||||||||||||||||||||||||
| "github.com/cosmos/cosmos-sdk/types/address" | ||||||||||||||||||||||||||||||||
| sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||||||||||||||||||||||||||||||||
| simtypes "github.com/cosmos/cosmos-sdk/types/simulation" | ||||||||||||||||||||||||||||||||
| banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||||||||||||||||||||||||||||||||
| govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" | ||||||||||||||||||||||||||||||||
| slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" | ||||||||||||||||||||||||||||||||
| stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||||||||||||||||||||||||||||||||
| "github.com/cosmos/evm/testutil/integration/base/factory" | ||||||||||||||||||||||||||||||||
| "github.com/cosmos/evm/testutil/keyring" | ||||||||||||||||||||||||||||||||
| "github.com/stretchr/testify/require" | ||||||||||||||||||||||||||||||||
| "github.com/xrplevm/node/v10/testutil/integration/exrp/utils" | ||||||||||||||||||||||||||||||||
| poatypes "github.com/xrplevm/node/v10/x/poa/types" | ||||||||||||||||||||||||||||||||
|
|
@@ -592,6 +597,264 @@ func (s *TestSuite) TestAddValidator_MaximumValidators() { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // SelfRemoveValidator tests | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| func (s *TestSuite) TestSelfRemoveValidator_ExistingValidator() { | ||||||||||||||||||||||||||||||||
| tt := []struct { | ||||||||||||||||||||||||||||||||
| name string | ||||||||||||||||||||||||||||||||
| valIndex int | ||||||||||||||||||||||||||||||||
| beforeRun func(valIndex int, valAddr sdktypes.ValAddress) | ||||||||||||||||||||||||||||||||
| afterRun func(valIndex int) | ||||||||||||||||||||||||||||||||
| }{ | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| name: "self remove existing validator - status bonded", | ||||||||||||||||||||||||||||||||
| valIndex: 0, | ||||||||||||||||||||||||||||||||
| beforeRun: func(_ int, valAddr sdktypes.ValAddress) { | ||||||||||||||||||||||||||||||||
| resVal, err := s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: valAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), stakingtypes.Bonded, resVal.Validator.Status) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), sdktypes.DefaultPowerReduction.ToLegacyDec(), resVal.Validator.DelegatorShares) | ||||||||||||||||||||||||||||||||
| require.NotZero(s.T(), resVal.Validator.Tokens) | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| name: "self remove existing validator - status jailed", | ||||||||||||||||||||||||||||||||
| valIndex: 1, | ||||||||||||||||||||||||||||||||
| beforeRun: func(valIndex int, valAddr sdktypes.ValAddress) { | ||||||||||||||||||||||||||||||||
| valSet := s.Network().GetValidatorSet() | ||||||||||||||||||||||||||||||||
| require.NoError( | ||||||||||||||||||||||||||||||||
| s.T(), | ||||||||||||||||||||||||||||||||
| s.Network().NextNBlocksWithValidatorFlags( | ||||||||||||||||||||||||||||||||
| slashingtypes.DefaultSignedBlocksWindow, | ||||||||||||||||||||||||||||||||
| utils.NewValidatorFlags( | ||||||||||||||||||||||||||||||||
| len(valSet.Validators), | ||||||||||||||||||||||||||||||||
| utils.NewValidatorFlagOverride(valIndex, cmtproto.BlockIDFlagAbsent), | ||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| resVal, err := s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: valAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.True(s.T(), resVal.Validator.Jailed) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), stakingtypes.Unbonding, resVal.Validator.Status) | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| name: "self remove existing validator - status tombstoned", | ||||||||||||||||||||||||||||||||
| valIndex: 1, | ||||||||||||||||||||||||||||||||
| beforeRun: func(valIndex int, _ sdktypes.ValAddress) { | ||||||||||||||||||||||||||||||||
| valSet := s.Network().GetValidatorSet() | ||||||||||||||||||||||||||||||||
| cmtValAddr := sdktypes.AccAddress(valSet.Validators[valIndex].Address.Bytes()) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| require.NoError(s.T(), s.Network().NextBlockWithMisBehaviors( | ||||||||||||||||||||||||||||||||
| []abcitypes.Misbehavior{ | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| Type: abcitypes.MisbehaviorType_DUPLICATE_VOTE, | ||||||||||||||||||||||||||||||||
| Validator: abcitypes.Validator{ | ||||||||||||||||||||||||||||||||
| Address: cmtValAddr, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| Height: s.Network().GetContext().BlockHeight(), | ||||||||||||||||||||||||||||||||
| TotalVotingPower: s.Network().GetValidatorSet().TotalVotingPower(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| )) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| cmtValConsAddr := sdktypes.ConsAddress(valSet.Validators[valIndex].Address.Bytes()) | ||||||||||||||||||||||||||||||||
| info, err := s.Network().GetSlashingClient().SigningInfo( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &slashingtypes.QuerySigningInfoRequest{ | ||||||||||||||||||||||||||||||||
| ConsAddress: cmtValConsAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.True(s.T(), info.ValSigningInfo.Tombstoned) | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| afterRun: func(valIndex int) { | ||||||||||||||||||||||||||||||||
| valSet := s.Network().GetValidatorSet() | ||||||||||||||||||||||||||||||||
| cmtValConsAddr := sdktypes.ConsAddress(valSet.Validators[valIndex].Address.Bytes()) | ||||||||||||||||||||||||||||||||
| info, err := s.Network().GetSlashingClient().SigningInfo( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &slashingtypes.QuerySigningInfoRequest{ | ||||||||||||||||||||||||||||||||
| ConsAddress: cmtValConsAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.True(s.T(), info.ValSigningInfo.Tombstoned) | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| for _, tc := range tt { | ||||||||||||||||||||||||||||||||
| s.Run(tc.name, func() { | ||||||||||||||||||||||||||||||||
| s.SetupTest() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| validators := s.Network().GetValidators() | ||||||||||||||||||||||||||||||||
| require.NotZero(s.T(), len(validators)) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| validator := validators[tc.valIndex] | ||||||||||||||||||||||||||||||||
| valAddr, err := sdktypes.ValAddressFromBech32(validator.OperatorAddress) | ||||||||||||||||||||||||||||||||
|
Comment on lines
+701
to
+705
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win Validate Line 702 only checks non-empty validators, but cases use index Suggested fix validators := s.Network().GetValidators()
require.NotZero(s.T(), len(validators))
+ require.Greater(s.T(), len(validators), tc.valIndex)
validator := validators[tc.valIndex]🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| valKey := s.keyring.GetKey(tc.valIndex) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), valAddr, sdktypes.ValAddress(valKey.AccAddr)) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if tc.beforeRun != nil { | ||||||||||||||||||||||||||||||||
| tc.beforeRun(tc.valIndex, valAddr) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| msg := poatypes.NewMsgSelfRemoveValidator(valKey.AccAddr.String()) | ||||||||||||||||||||||||||||||||
| res, err := s.factory.CommitCosmosTx(valKey.Priv, factory.CosmosTxArgs{ | ||||||||||||||||||||||||||||||||
| Msgs: []sdktypes.Msg{msg}, | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), uint32(0), res.Code, res.Log) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| resVal, err := s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: valAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.True(s.T(), resVal.Validator.DelegatorShares.IsZero()) | ||||||||||||||||||||||||||||||||
| require.True(s.T(), resVal.Validator.Tokens.IsZero()) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), stakingtypes.Unbonding, resVal.Validator.Status) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| require.NoError(s.T(), s.Network().NextBlockAfter(stakingtypes.DefaultUnbondingTime)) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| _, err = s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: valAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.Contains(s.T(), err.Error(), fmt.Sprintf("validator %s not found", valAddr.String())) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if tc.afterRun != nil { | ||||||||||||||||||||||||||||||||
| tc.afterRun(tc.valIndex) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| func (s *TestSuite) TestSelfRemoveValidator_UnexistingValidator() { | ||||||||||||||||||||||||||||||||
| funder := s.keyring.GetKey(0) | ||||||||||||||||||||||||||||||||
| nonValidator := keyring.NewKey() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| fundAmount := sdktypes.NewCoins(sdktypes.NewCoin(s.Network().GetBaseDenom(), sdkmath.NewInt(1_000_000_000_000_000_000))) | ||||||||||||||||||||||||||||||||
| sendRes, err := s.factory.CommitCosmosTx(funder.Priv, factory.CosmosTxArgs{ | ||||||||||||||||||||||||||||||||
| Msgs: []sdktypes.Msg{banktypes.NewMsgSend(funder.AccAddr, nonValidator.AccAddr, fundAmount)}, | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), uint32(0), sendRes.Code, sendRes.Log) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| nonValAddr := sdktypes.ValAddress(nonValidator.AccAddr) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| _, err = s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: nonValAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.Contains(s.T(), err.Error(), fmt.Sprintf("validator %s not found", nonValAddr.String())) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+763
to
+770
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Guard Line 769 dereferences Suggested fix _, err = s.Network().GetStakingClient().Validator(
s.Network().GetContext(),
&stakingtypes.QueryValidatorRequest{
ValidatorAddr: nonValAddr.String(),
},
)
+ require.Error(s.T(), err)
require.Contains(s.T(), err.Error(), fmt.Sprintf("validator %s not found", nonValAddr.String()))📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| gas := uint64(1_000_000) | ||||||||||||||||||||||||||||||||
| msg := poatypes.NewMsgSelfRemoveValidator(nonValidator.AccAddr.String()) | ||||||||||||||||||||||||||||||||
| res, err := s.factory.CommitCosmosTx(nonValidator.Priv, factory.CosmosTxArgs{ | ||||||||||||||||||||||||||||||||
| Msgs: []sdktypes.Msg{msg}, | ||||||||||||||||||||||||||||||||
| Gas: &gas, | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.NotEqual(s.T(), uint32(0), res.Code) | ||||||||||||||||||||||||||||||||
| require.Contains(s.T(), res.Log, poatypes.ErrAddressIsNotAValidator.Error()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| func (s *TestSuite) TestSelfRemoveValidator_DifferentSigner() { | ||||||||||||||||||||||||||||||||
| signer := s.keyring.GetKey(0) | ||||||||||||||||||||||||||||||||
| target := s.keyring.GetKey(1) | ||||||||||||||||||||||||||||||||
| targetValAddr := sdktypes.ValAddress(target.AccAddr) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| gas := uint64(1_000_000) | ||||||||||||||||||||||||||||||||
| msg := poatypes.NewMsgSelfRemoveValidator(target.AccAddr.String()) | ||||||||||||||||||||||||||||||||
| res, err := s.factory.CommitCosmosTx(signer.Priv, factory.CosmosTxArgs{ | ||||||||||||||||||||||||||||||||
| Msgs: []sdktypes.Msg{msg}, | ||||||||||||||||||||||||||||||||
| Gas: &gas, | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.NotEqual(s.T(), uint32(0), res.Code) | ||||||||||||||||||||||||||||||||
| require.Contains(s.T(), res.Log, sdkerrors.ErrUnauthorized.Error()) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| resVal, err := s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: targetValAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), stakingtypes.Bonded, resVal.Validator.Status) | ||||||||||||||||||||||||||||||||
| require.False(s.T(), resVal.Validator.Tokens.IsZero()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| func (s *TestSuite) TestSelfRemoveValidator_AlreadyRemoved() { | ||||||||||||||||||||||||||||||||
| validators := s.Network().GetValidators() | ||||||||||||||||||||||||||||||||
| require.NotZero(s.T(), len(validators)) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| valIndex := 0 | ||||||||||||||||||||||||||||||||
| validator := validators[valIndex] | ||||||||||||||||||||||||||||||||
| valAddr, err := sdktypes.ValAddressFromBech32(validator.OperatorAddress) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| valKey := s.keyring.GetKey(valIndex) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), valAddr, sdktypes.ValAddress(valKey.AccAddr)) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| msg := poatypes.NewMsgSelfRemoveValidator(valKey.AccAddr.String()) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| res, err := s.factory.CommitCosmosTx(valKey.Priv, factory.CosmosTxArgs{ | ||||||||||||||||||||||||||||||||
| Msgs: []sdktypes.Msg{msg}, | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), uint32(0), res.Code, res.Log) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| resVal, err := s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: valAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), stakingtypes.Unbonding, resVal.Validator.Status) | ||||||||||||||||||||||||||||||||
| require.True(s.T(), resVal.Validator.Tokens.IsZero()) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| gas := uint64(1_000_000) | ||||||||||||||||||||||||||||||||
| res, err = s.factory.CommitCosmosTx(valKey.Priv, factory.CosmosTxArgs{ | ||||||||||||||||||||||||||||||||
| Msgs: []sdktypes.Msg{msg}, | ||||||||||||||||||||||||||||||||
| Gas: &gas, | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.NotEqual(s.T(), uint32(0), res.Code) | ||||||||||||||||||||||||||||||||
| require.Contains(s.T(), res.Log, stakingtypes.ErrNoDelegatorForAddress.Error()) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| resVal, err = s.Network().GetStakingClient().Validator( | ||||||||||||||||||||||||||||||||
| s.Network().GetContext(), | ||||||||||||||||||||||||||||||||
| &stakingtypes.QueryValidatorRequest{ | ||||||||||||||||||||||||||||||||
| ValidatorAddr: valAddr.String(), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| require.NoError(s.T(), err) | ||||||||||||||||||||||||||||||||
| require.Equal(s.T(), stakingtypes.Unbonding, resVal.Validator.Status) | ||||||||||||||||||||||||||||||||
| require.True(s.T(), resVal.Validator.Tokens.IsZero()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // RemoveValidator tests | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| func (s *TestSuite) TestRemoveValidator_UnexistingValidator() { | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -289,3 +289,33 @@ func (k Keeper) ExecuteRemoveValidator(ctx sdk.Context, validatorAddress string) | |
|
|
||
| return nil | ||
| } | ||
|
|
||
| func (k Keeper) ExecuteSelfRemoveValidator(ctx sdk.Context, validatorAddress string) error { | ||
| accAddress, err := sdk.AccAddressFromBech32(validatorAddress) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| valAddress := sdk.ValAddress(accAddress) | ||
|
AdriaCarrera marked this conversation as resolved.
|
||
|
|
||
| validator, err := k.sk.GetValidator(ctx, valAddress) | ||
| if err != nil { | ||
| ctx.Logger().Warn("Error getting validator", "error", err) | ||
| return types.ErrAddressIsNotAValidator | ||
| } | ||
|
Comment on lines
+300
to
+304
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not collapse all Returning Proposed fix validator, err := k.sk.GetValidator(ctx, valAddress)
if err != nil {
- return types.ErrAddressIsNotAValidator
+ if errors.IsOf(err, stakingtypes.ErrNoValidatorFound) {
+ return types.ErrAddressIsNotAValidator
+ }
+ return err
}🤖 Prompt for AI Agents |
||
|
|
||
| err = k.ExecuteRemoveValidator(ctx, accAddress.String()) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| ctx.EventManager().EmitEvent( | ||
| sdk.NewEvent( | ||
| types.EventTypeSelfRemoveValidator, | ||
| sdk.NewAttribute(types.AttributeValidator, valAddress.String()), | ||
| sdk.NewAttribute(types.AttributeHeight, fmt.Sprintf("%d", ctx.BlockHeight())), | ||
| sdk.NewAttribute(types.AttributeStakingTokens, fmt.Sprintf("%d", validator.Tokens)), | ||
| ), | ||
| ) | ||
|
|
||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package keeper | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| sdk "github.com/cosmos/cosmos-sdk/types" | ||
| "github.com/xrplevm/node/v10/x/poa/types" | ||
| ) | ||
|
|
||
| func (k msgServer) SelfRemoveValidator(goCtx context.Context, msg *types.MsgSelfRemoveValidator) (*types.MsgSelfRemoveValidatorResponse, error) { | ||
| ctx := sdk.UnwrapSDKContext(goCtx) | ||
| err := k.ExecuteSelfRemoveValidator(ctx, msg.Address) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return &types.MsgSelfRemoveValidatorResponse{}, nil | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.