github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/unbonding_test.go (about) 1 package keeper_test 2 3 import ( 4 "time" 5 6 "cosmossdk.io/math" 7 8 addresscodec "github.com/cosmos/cosmos-sdk/codec/address" 9 sdk "github.com/cosmos/cosmos-sdk/types" 10 "github.com/cosmos/cosmos-sdk/x/staking/testutil" 11 "github.com/cosmos/cosmos-sdk/x/staking/types" 12 ) 13 14 func (s *KeeperTestSuite) TestIncrementUnbondingID() { 15 for i := 1; i < 10; i++ { 16 id, err := s.stakingKeeper.IncrementUnbondingID(s.ctx) 17 s.Require().NoError(err) 18 s.Require().Equal(uint64(i), id) 19 } 20 } 21 22 func (s *KeeperTestSuite) TestUnbondingTypeAccessors() { 23 require := s.Require() 24 cases := []struct { 25 exists bool 26 name string 27 expected types.UnbondingType 28 }{ 29 { 30 name: "existing 1", 31 exists: true, 32 expected: types.UnbondingType_UnbondingDelegation, 33 }, 34 { 35 name: "existing 2", 36 exists: true, 37 expected: types.UnbondingType_Redelegation, 38 }, 39 { 40 name: "not existing", 41 exists: false, 42 }, 43 } 44 45 for i, tc := range cases { 46 s.Run(tc.name, func() { 47 if tc.exists { 48 require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, uint64(i), tc.expected)) 49 } 50 51 unbondingType, err := s.stakingKeeper.GetUnbondingType(s.ctx, uint64(i)) 52 if tc.exists { 53 require.NoError(err) 54 require.Equal(tc.expected, unbondingType) 55 } else { 56 require.ErrorIs(err, types.ErrNoUnbondingType) 57 } 58 }) 59 } 60 } 61 62 func (s *KeeperTestSuite) TestUnbondingDelegationByUnbondingIDAccessors() { 63 delAddrs, valAddrs := createValAddrs(2) 64 require := s.Require() 65 66 type exists struct { 67 setUnbondingDelegation bool 68 setUnbondingDelegationByUnbondingID bool 69 } 70 71 cases := []struct { 72 exists exists 73 name string 74 expected types.UnbondingDelegation 75 }{ 76 { 77 name: "existing 1", 78 exists: exists{true, true}, 79 expected: types.NewUnbondingDelegation( 80 delAddrs[0], 81 valAddrs[0], 82 0, 83 time.Unix(0, 0).UTC(), 84 math.NewInt(5), 85 0, 86 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 87 ), 88 }, 89 { 90 name: "not existing 1", 91 exists: exists{false, true}, 92 expected: types.NewUnbondingDelegation( 93 delAddrs[1], 94 valAddrs[1], 95 0, 96 time.Unix(0, 0).UTC(), 97 math.NewInt(5), 98 0, 99 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 100 ), 101 }, 102 { 103 name: "not existing 2", 104 exists: exists{false, false}, 105 expected: types.NewUnbondingDelegation( 106 delAddrs[0], 107 valAddrs[0], 108 0, 109 time.Unix(0, 0).UTC(), 110 math.NewInt(5), 111 0, 112 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 113 ), 114 }, 115 } 116 117 for i, tc := range cases { 118 s.Run(tc.name, func() { 119 if tc.exists.setUnbondingDelegation { 120 require.NoError(s.stakingKeeper.SetUnbondingDelegation(s.ctx, tc.expected)) 121 } 122 123 if tc.exists.setUnbondingDelegationByUnbondingID { 124 require.NoError(s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, tc.expected, uint64(i))) 125 } 126 127 ubd, err := s.stakingKeeper.GetUnbondingDelegationByUnbondingID(s.ctx, uint64(i)) 128 if tc.exists.setUnbondingDelegation && tc.exists.setUnbondingDelegationByUnbondingID { 129 require.NoError(err) 130 require.Equal(tc.expected, ubd) 131 } else { 132 require.ErrorIs(err, types.ErrNoUnbondingDelegation) 133 } 134 }) 135 } 136 } 137 138 func (s *KeeperTestSuite) TestRedelegationByUnbondingIDAccessors() { 139 delAddrs, valAddrs := createValAddrs(2) 140 require := s.Require() 141 142 type exists struct { 143 setRedelegation bool 144 setRedelegationByUnbondingID bool 145 } 146 147 cases := []struct { 148 exists exists 149 name string 150 expected types.Redelegation 151 }{ 152 { 153 name: "existing 1", 154 exists: exists{true, true}, 155 expected: types.NewRedelegation( 156 delAddrs[0], 157 valAddrs[0], 158 valAddrs[1], 159 0, 160 time.Unix(5, 0).UTC(), 161 math.NewInt(10), 162 math.LegacyNewDec(10), 163 0, 164 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 165 ), 166 }, 167 { 168 name: "not existing 1", 169 exists: exists{false, true}, 170 expected: types.NewRedelegation( 171 delAddrs[1], 172 valAddrs[0], 173 valAddrs[1], 174 0, 175 time.Unix(5, 0).UTC(), 176 math.NewInt(10), 177 math.LegacyNewDec(10), 178 0, 179 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 180 ), 181 }, 182 { 183 name: "not existing 2", 184 exists: exists{false, false}, 185 expected: types.NewRedelegation( 186 delAddrs[1], 187 valAddrs[1], 188 valAddrs[0], 189 0, 190 time.Unix(5, 0).UTC(), 191 math.NewInt(10), 192 math.LegacyNewDec(10), 193 0, 194 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 195 ), 196 }, 197 } 198 199 for i, tc := range cases { 200 s.Run(tc.name, func() { 201 if tc.exists.setRedelegation { 202 require.NoError(s.stakingKeeper.SetRedelegation(s.ctx, tc.expected)) 203 } 204 205 if tc.exists.setRedelegationByUnbondingID { 206 require.NoError(s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, tc.expected, uint64(i))) 207 } 208 209 red, err := s.stakingKeeper.GetRedelegationByUnbondingID(s.ctx, uint64(i)) 210 if tc.exists.setRedelegation && tc.exists.setRedelegationByUnbondingID { 211 require.NoError(err) 212 require.Equal(tc.expected, red) 213 } else { 214 require.ErrorIs(err, types.ErrNoRedelegation) 215 } 216 }) 217 } 218 } 219 220 func (s *KeeperTestSuite) TestValidatorByUnbondingIDAccessors() { 221 _, valAddrs := createValAddrs(3) 222 require := s.Require() 223 224 type exists struct { 225 setValidator bool 226 setValidatorByUnbondingID bool 227 } 228 229 cases := []struct { 230 exists exists 231 name string 232 validator types.Validator 233 }{ 234 { 235 name: "existing 1", 236 exists: exists{true, true}, 237 validator: testutil.NewValidator(s.T(), valAddrs[0], PKs[0]), 238 }, 239 { 240 name: "not existing 1", 241 exists: exists{false, true}, 242 validator: testutil.NewValidator(s.T(), valAddrs[1], PKs[1]), 243 }, 244 { 245 name: "not existing 2", 246 exists: exists{false, false}, 247 validator: testutil.NewValidator(s.T(), valAddrs[2], PKs[0]), 248 }, 249 } 250 251 for i, tc := range cases { 252 s.Run(tc.name, func() { 253 if tc.exists.setValidator { 254 require.NoError(s.stakingKeeper.SetValidator(s.ctx, tc.validator)) 255 } 256 257 if tc.exists.setValidatorByUnbondingID { 258 require.NoError(s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, tc.validator, uint64(i))) 259 } 260 261 val, err := s.stakingKeeper.GetValidatorByUnbondingID(s.ctx, uint64(i)) 262 if tc.exists.setValidator && tc.exists.setValidatorByUnbondingID { 263 require.NoError(err) 264 require.Equal(tc.validator, val) 265 } else { 266 require.ErrorIs(err, types.ErrNoValidatorFound) 267 } 268 }) 269 } 270 } 271 272 func (s *KeeperTestSuite) TestUnbondingCanComplete() { 273 delAddrs, valAddrs := createValAddrs(3) 274 require := s.Require() 275 276 unbondingID := uint64(1) 277 278 // no unbondingID set 279 err := s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 280 require.ErrorIs(err, types.ErrNoUnbondingType) 281 282 // unbonding delegation 283 require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_UnbondingDelegation)) 284 err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 285 require.ErrorIs(err, types.ErrNoUnbondingDelegation) 286 287 ubd := types.NewUnbondingDelegation( 288 delAddrs[0], 289 valAddrs[0], 290 0, 291 time.Unix(0, 0).UTC(), 292 math.NewInt(5), 293 unbondingID, 294 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 295 ) 296 require.NoError(s.stakingKeeper.SetUnbondingDelegation(s.ctx, ubd)) 297 require.NoError(s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, ubd, unbondingID)) 298 err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 299 require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative) 300 301 err = s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID) 302 require.NoError(err) 303 s.bankKeeper.EXPECT().UndelegateCoinsFromModuleToAccount(s.ctx, types.NotBondedPoolName, delAddrs[0], sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(5)))).Return(nil) 304 err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 305 require.NoError(err) 306 307 // redelegation 308 unbondingID++ 309 require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_Redelegation)) 310 err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 311 require.ErrorIs(err, types.ErrNoRedelegation) 312 313 red := types.NewRedelegation( 314 delAddrs[0], 315 valAddrs[0], 316 valAddrs[1], 317 0, 318 time.Unix(5, 0).UTC(), 319 math.NewInt(10), 320 math.LegacyNewDec(10), 321 unbondingID, 322 addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"), 323 ) 324 require.NoError(s.stakingKeeper.SetRedelegation(s.ctx, red)) 325 require.NoError(s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, red, unbondingID)) 326 err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 327 require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative) 328 329 require.NoError(s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID)) 330 require.NoError(s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)) 331 332 // validator unbonding 333 unbondingID++ 334 require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_ValidatorUnbonding)) 335 err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 336 require.ErrorIs(err, types.ErrNoValidatorFound) 337 338 val := testutil.NewValidator(s.T(), valAddrs[0], PKs[0]) 339 require.NoError(s.stakingKeeper.SetValidator(s.ctx, val)) 340 require.NoError(s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, val, unbondingID)) 341 err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID) 342 require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative) 343 344 require.NoError(s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID)) 345 require.NoError(s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)) 346 }