github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/delegation.go (about) 1 package keeper 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "fmt" 8 "time" 9 10 corestore "cosmossdk.io/core/store" 11 errorsmod "cosmossdk.io/errors" 12 "cosmossdk.io/math" 13 storetypes "cosmossdk.io/store/types" 14 15 sdk "github.com/cosmos/cosmos-sdk/types" 16 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 17 "github.com/cosmos/cosmos-sdk/x/staking/types" 18 ) 19 20 // GetDelegation returns a specific delegation. 21 func (k Keeper) GetDelegation(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (types.Delegation, error) { 22 store := k.storeService.OpenKVStore(ctx) 23 key := types.GetDelegationKey(delAddr, valAddr) 24 25 value, err := store.Get(key) 26 if err != nil { 27 return types.Delegation{}, err 28 } 29 30 if value == nil { 31 return types.Delegation{}, types.ErrNoDelegation 32 } 33 34 return types.UnmarshalDelegation(k.cdc, value) 35 } 36 37 // IterateAllDelegations iterates through all of the delegations. 38 func (k Keeper) IterateAllDelegations(ctx context.Context, cb func(delegation types.Delegation) (stop bool)) error { 39 store := k.storeService.OpenKVStore(ctx) 40 iterator, err := store.Iterator(types.DelegationKey, storetypes.PrefixEndBytes(types.DelegationKey)) 41 if err != nil { 42 return err 43 } 44 defer iterator.Close() 45 46 for ; iterator.Valid(); iterator.Next() { 47 delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value()) 48 if cb(delegation) { 49 break 50 } 51 } 52 53 return nil 54 } 55 56 // GetAllDelegations returns all delegations used during genesis dump. 57 func (k Keeper) GetAllDelegations(ctx context.Context) (delegations []types.Delegation, err error) { 58 err = k.IterateAllDelegations(ctx, func(delegation types.Delegation) bool { 59 delegations = append(delegations, delegation) 60 return false 61 }) 62 63 return delegations, err 64 } 65 66 // GetValidatorDelegations returns all delegations to a specific validator. 67 // Useful for querier. 68 func (k Keeper) GetValidatorDelegations(ctx context.Context, valAddr sdk.ValAddress) (delegations []types.Delegation, err error) { 69 store := k.storeService.OpenKVStore(ctx) 70 prefix := types.GetDelegationsByValPrefixKey(valAddr) 71 iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix)) 72 if err != nil { 73 return delegations, err 74 } 75 defer iterator.Close() 76 77 for ; iterator.Valid(); iterator.Next() { 78 var delegation types.Delegation 79 valAddr, delAddr, err := types.ParseDelegationsByValKey(iterator.Key()) 80 if err != nil { 81 return delegations, err 82 } 83 84 bz, err := store.Get(types.GetDelegationKey(delAddr, valAddr)) 85 if err != nil { 86 return delegations, err 87 } 88 89 if err := k.cdc.Unmarshal(bz, &delegation); err != nil { 90 return delegations, err 91 } 92 93 delegations = append(delegations, delegation) 94 } 95 96 return delegations, nil 97 } 98 99 // GetDelegatorDelegations returns a given amount of all the delegations from a 100 // delegator. 101 func (k Keeper) GetDelegatorDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (delegations []types.Delegation, err error) { 102 delegations = make([]types.Delegation, maxRetrieve) 103 store := k.storeService.OpenKVStore(ctx) 104 delegatorPrefixKey := types.GetDelegationsKey(delegator) 105 106 iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) 107 if err != nil { 108 return delegations, err 109 } 110 defer iterator.Close() 111 112 i := 0 113 for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() { 114 delegation, err := types.UnmarshalDelegation(k.cdc, iterator.Value()) 115 if err != nil { 116 return delegations, err 117 } 118 delegations[i] = delegation 119 i++ 120 } 121 122 return delegations[:i], nil // trim if the array length < maxRetrieve 123 } 124 125 // SetDelegation sets a delegation. 126 func (k Keeper) SetDelegation(ctx context.Context, delegation types.Delegation) error { 127 delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(delegation.DelegatorAddress) 128 if err != nil { 129 return err 130 } 131 132 valAddr, err := k.validatorAddressCodec.StringToBytes(delegation.GetValidatorAddr()) 133 if err != nil { 134 return err 135 } 136 137 store := k.storeService.OpenKVStore(ctx) 138 b := types.MustMarshalDelegation(k.cdc, delegation) 139 err = store.Set(types.GetDelegationKey(delegatorAddress, valAddr), b) 140 if err != nil { 141 return err 142 } 143 144 // set the delegation in validator delegator index 145 return store.Set(types.GetDelegationsByValKey(valAddr, delegatorAddress), []byte{}) 146 } 147 148 // RemoveDelegation removes a delegation 149 func (k Keeper) RemoveDelegation(ctx context.Context, delegation types.Delegation) error { 150 delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(delegation.DelegatorAddress) 151 if err != nil { 152 return err 153 } 154 155 valAddr, err := k.validatorAddressCodec.StringToBytes(delegation.GetValidatorAddr()) 156 if err != nil { 157 return err 158 } 159 160 // TODO: Consider calling hooks outside of the store wrapper functions, it's unobvious. 161 if err := k.Hooks().BeforeDelegationRemoved(ctx, delegatorAddress, valAddr); err != nil { 162 return err 163 } 164 165 store := k.storeService.OpenKVStore(ctx) 166 err = store.Delete(types.GetDelegationKey(delegatorAddress, valAddr)) 167 if err != nil { 168 return err 169 } 170 171 return store.Delete(types.GetDelegationsByValKey(valAddr, delegatorAddress)) 172 } 173 174 // GetUnbondingDelegations returns a given amount of all the delegator unbonding-delegations. 175 func (k Keeper) GetUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation, err error) { 176 unbondingDelegations = make([]types.UnbondingDelegation, maxRetrieve) 177 178 store := k.storeService.OpenKVStore(ctx) 179 delegatorPrefixKey := types.GetUBDsKey(delegator) 180 181 iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) 182 if err != nil { 183 return unbondingDelegations, err 184 } 185 defer iterator.Close() 186 187 i := 0 188 for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() { 189 unbondingDelegation, err := types.UnmarshalUBD(k.cdc, iterator.Value()) 190 if err != nil { 191 return unbondingDelegations, err 192 } 193 unbondingDelegations[i] = unbondingDelegation 194 i++ 195 } 196 197 return unbondingDelegations[:i], nil // trim if the array length < maxRetrieve 198 } 199 200 // GetUnbondingDelegation returns a unbonding delegation. 201 func (k Keeper) GetUnbondingDelegation(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (ubd types.UnbondingDelegation, err error) { 202 store := k.storeService.OpenKVStore(ctx) 203 key := types.GetUBDKey(delAddr, valAddr) 204 value, err := store.Get(key) 205 if err != nil { 206 return ubd, err 207 } 208 209 if value == nil { 210 return ubd, types.ErrNoUnbondingDelegation 211 } 212 213 return types.UnmarshalUBD(k.cdc, value) 214 } 215 216 // GetUnbondingDelegationsFromValidator returns all unbonding delegations from a 217 // particular validator. 218 func (k Keeper) GetUnbondingDelegationsFromValidator(ctx context.Context, valAddr sdk.ValAddress) (ubds []types.UnbondingDelegation, err error) { 219 store := k.storeService.OpenKVStore(ctx) 220 prefix := types.GetUBDsByValIndexKey(valAddr) 221 iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix)) 222 if err != nil { 223 return ubds, err 224 } 225 defer iterator.Close() 226 227 for ; iterator.Valid(); iterator.Next() { 228 key := types.GetUBDKeyFromValIndexKey(iterator.Key()) 229 value, err := store.Get(key) 230 if err != nil { 231 return ubds, err 232 } 233 ubd, err := types.UnmarshalUBD(k.cdc, value) 234 if err != nil { 235 return ubds, err 236 } 237 ubds = append(ubds, ubd) 238 } 239 240 return ubds, nil 241 } 242 243 // IterateUnbondingDelegations iterates through all of the unbonding delegations. 244 func (k Keeper) IterateUnbondingDelegations(ctx context.Context, fn func(index int64, ubd types.UnbondingDelegation) (stop bool)) error { 245 store := k.storeService.OpenKVStore(ctx) 246 prefix := types.UnbondingDelegationKey 247 iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix)) 248 if err != nil { 249 return err 250 } 251 defer iterator.Close() 252 253 for i := int64(0); iterator.Valid(); iterator.Next() { 254 ubd, err := types.UnmarshalUBD(k.cdc, iterator.Value()) 255 if err != nil { 256 return err 257 } 258 if stop := fn(i, ubd); stop { 259 break 260 } 261 i++ 262 } 263 264 return nil 265 } 266 267 // GetDelegatorUnbonding returns the total amount a delegator has unbonding. 268 func (k Keeper) GetDelegatorUnbonding(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) { 269 unbonding := math.ZeroInt() 270 err := k.IterateDelegatorUnbondingDelegations(ctx, delegator, func(ubd types.UnbondingDelegation) bool { 271 for _, entry := range ubd.Entries { 272 unbonding = unbonding.Add(entry.Balance) 273 } 274 return false 275 }) 276 return unbonding, err 277 } 278 279 // IterateDelegatorUnbondingDelegations iterates through a delegator's unbonding delegations. 280 func (k Keeper) IterateDelegatorUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress, cb func(ubd types.UnbondingDelegation) (stop bool)) error { 281 store := k.storeService.OpenKVStore(ctx) 282 prefix := types.GetUBDsKey(delegator) 283 iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix)) 284 if err != nil { 285 return err 286 } 287 defer iterator.Close() 288 289 for ; iterator.Valid(); iterator.Next() { 290 ubd, err := types.UnmarshalUBD(k.cdc, iterator.Value()) 291 if err != nil { 292 return err 293 } 294 if cb(ubd) { 295 break 296 } 297 } 298 299 return nil 300 } 301 302 // GetDelegatorBonded returs the total amount a delegator has bonded. 303 func (k Keeper) GetDelegatorBonded(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) { 304 bonded := math.LegacyZeroDec() 305 306 err := k.IterateDelegatorDelegations(ctx, delegator, func(delegation types.Delegation) bool { 307 validatorAddr, err := k.validatorAddressCodec.StringToBytes(delegation.ValidatorAddress) 308 if err != nil { 309 panic(err) // shouldn't happen 310 } 311 validator, err := k.GetValidator(ctx, validatorAddr) 312 if err == nil { 313 shares := delegation.Shares 314 tokens := validator.TokensFromSharesTruncated(shares) 315 bonded = bonded.Add(tokens) 316 } 317 return false 318 }) 319 return bonded.RoundInt(), err 320 } 321 322 // IterateDelegatorDelegations iterates through one delegator's delegations. 323 func (k Keeper) IterateDelegatorDelegations(ctx context.Context, delegator sdk.AccAddress, cb func(delegation types.Delegation) (stop bool)) error { 324 store := k.storeService.OpenKVStore(ctx) 325 prefix := types.GetDelegationsKey(delegator) 326 iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix)) 327 if err != nil { 328 return err 329 } 330 defer iterator.Close() 331 332 for ; iterator.Valid(); iterator.Next() { 333 delegation, err := types.UnmarshalDelegation(k.cdc, iterator.Value()) 334 if err != nil { 335 return err 336 } 337 if cb(delegation) { 338 break 339 } 340 } 341 return nil 342 } 343 344 // IterateDelegatorRedelegations iterates through one delegator's redelegations. 345 func (k Keeper) IterateDelegatorRedelegations(ctx context.Context, delegator sdk.AccAddress, cb func(red types.Redelegation) (stop bool)) error { 346 store := k.storeService.OpenKVStore(ctx) 347 delegatorPrefixKey := types.GetREDsKey(delegator) 348 iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) 349 if err != nil { 350 return err 351 } 352 353 for ; iterator.Valid(); iterator.Next() { 354 red, err := types.UnmarshalRED(k.cdc, iterator.Value()) 355 if err != nil { 356 return err 357 } 358 if cb(red) { 359 break 360 } 361 } 362 return nil 363 } 364 365 // HasMaxUnbondingDelegationEntries checks if unbonding delegation has maximum number of entries. 366 func (k Keeper) HasMaxUnbondingDelegationEntries(ctx context.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) (bool, error) { 367 ubd, err := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) 368 if err != nil && !errors.Is(err, types.ErrNoUnbondingDelegation) { 369 return false, err 370 } 371 372 maxEntries, err := k.MaxEntries(ctx) 373 if err != nil { 374 return false, err 375 } 376 return len(ubd.Entries) >= int(maxEntries), nil 377 } 378 379 // SetUnbondingDelegation sets the unbonding delegation and associated index. 380 func (k Keeper) SetUnbondingDelegation(ctx context.Context, ubd types.UnbondingDelegation) error { 381 delAddr, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress) 382 if err != nil { 383 return err 384 } 385 386 store := k.storeService.OpenKVStore(ctx) 387 bz := types.MustMarshalUBD(k.cdc, ubd) 388 valAddr, err := k.validatorAddressCodec.StringToBytes(ubd.ValidatorAddress) 389 if err != nil { 390 return err 391 } 392 key := types.GetUBDKey(delAddr, valAddr) 393 err = store.Set(key, bz) 394 if err != nil { 395 return err 396 } 397 398 return store.Set(types.GetUBDByValIndexKey(delAddr, valAddr), []byte{}) // index, store empty bytes 399 } 400 401 // RemoveUnbondingDelegation removes the unbonding delegation object and associated index. 402 func (k Keeper) RemoveUnbondingDelegation(ctx context.Context, ubd types.UnbondingDelegation) error { 403 delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress) 404 if err != nil { 405 return err 406 } 407 408 store := k.storeService.OpenKVStore(ctx) 409 addr, err := k.validatorAddressCodec.StringToBytes(ubd.ValidatorAddress) 410 if err != nil { 411 return err 412 } 413 key := types.GetUBDKey(delegatorAddress, addr) 414 err = store.Delete(key) 415 if err != nil { 416 return err 417 } 418 419 return store.Delete(types.GetUBDByValIndexKey(delegatorAddress, addr)) 420 } 421 422 // SetUnbondingDelegationEntry adds an entry to the unbonding delegation at 423 // the given addresses. It creates the unbonding delegation if it does not exist. 424 func (k Keeper) SetUnbondingDelegationEntry( 425 ctx context.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, 426 creationHeight int64, minTime time.Time, balance math.Int, 427 ) (types.UnbondingDelegation, error) { 428 id, err := k.IncrementUnbondingID(ctx) 429 if err != nil { 430 return types.UnbondingDelegation{}, err 431 } 432 433 isNewUbdEntry := true 434 ubd, err := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) 435 if err == nil { 436 isNewUbdEntry = ubd.AddEntry(creationHeight, minTime, balance, id) 437 } else if errors.Is(err, types.ErrNoUnbondingDelegation) { 438 ubd = types.NewUnbondingDelegation(delegatorAddr, validatorAddr, creationHeight, minTime, balance, id, k.validatorAddressCodec, k.authKeeper.AddressCodec()) 439 } else { 440 return ubd, err 441 } 442 443 if err = k.SetUnbondingDelegation(ctx, ubd); err != nil { 444 return ubd, err 445 } 446 447 // only call the hook for new entries since 448 // calls to AfterUnbondingInitiated are not idempotent 449 if isNewUbdEntry { 450 // Add to the UBDByUnbondingOp index to look up the UBD by the UBDE ID 451 if err = k.SetUnbondingDelegationByUnbondingID(ctx, ubd, id); err != nil { 452 return ubd, err 453 } 454 455 if err := k.Hooks().AfterUnbondingInitiated(ctx, id); err != nil { 456 k.Logger(ctx).Error("failed to call after unbonding initiated hook", "error", err) 457 } 458 } 459 return ubd, nil 460 } 461 462 // unbonding delegation queue timeslice operations 463 464 // GetUBDQueueTimeSlice gets a specific unbonding queue timeslice. A timeslice 465 // is a slice of DVPairs corresponding to unbonding delegations that expire at a 466 // certain time. 467 func (k Keeper) GetUBDQueueTimeSlice(ctx context.Context, timestamp time.Time) (dvPairs []types.DVPair, err error) { 468 store := k.storeService.OpenKVStore(ctx) 469 470 bz, err := store.Get(types.GetUnbondingDelegationTimeKey(timestamp)) 471 if bz == nil || err != nil { 472 return []types.DVPair{}, err 473 } 474 475 pairs := types.DVPairs{} 476 err = k.cdc.Unmarshal(bz, &pairs) 477 478 return pairs.Pairs, err 479 } 480 481 // SetUBDQueueTimeSlice sets a specific unbonding queue timeslice. 482 func (k Keeper) SetUBDQueueTimeSlice(ctx context.Context, timestamp time.Time, keys []types.DVPair) error { 483 store := k.storeService.OpenKVStore(ctx) 484 bz, err := k.cdc.Marshal(&types.DVPairs{Pairs: keys}) 485 if err != nil { 486 return err 487 } 488 return store.Set(types.GetUnbondingDelegationTimeKey(timestamp), bz) 489 } 490 491 // InsertUBDQueue inserts an unbonding delegation to the appropriate timeslice 492 // in the unbonding queue. 493 func (k Keeper) InsertUBDQueue(ctx context.Context, ubd types.UnbondingDelegation, completionTime time.Time) error { 494 dvPair := types.DVPair{DelegatorAddress: ubd.DelegatorAddress, ValidatorAddress: ubd.ValidatorAddress} 495 496 timeSlice, err := k.GetUBDQueueTimeSlice(ctx, completionTime) 497 if err != nil { 498 return err 499 } 500 501 if len(timeSlice) == 0 { 502 if err = k.SetUBDQueueTimeSlice(ctx, completionTime, []types.DVPair{dvPair}); err != nil { 503 return err 504 } 505 return nil 506 } 507 508 timeSlice = append(timeSlice, dvPair) 509 return k.SetUBDQueueTimeSlice(ctx, completionTime, timeSlice) 510 } 511 512 // UBDQueueIterator returns all the unbonding queue timeslices from time 0 until endTime. 513 func (k Keeper) UBDQueueIterator(ctx context.Context, endTime time.Time) (corestore.Iterator, error) { 514 store := k.storeService.OpenKVStore(ctx) 515 return store.Iterator(types.UnbondingQueueKey, 516 storetypes.InclusiveEndBytes(types.GetUnbondingDelegationTimeKey(endTime))) 517 } 518 519 // DequeueAllMatureUBDQueue returns a concatenated list of all the timeslices inclusively previous to 520 // currTime, and deletes the timeslices from the queue. 521 func (k Keeper) DequeueAllMatureUBDQueue(ctx context.Context, currTime time.Time) (matureUnbonds []types.DVPair, err error) { 522 store := k.storeService.OpenKVStore(ctx) 523 524 // gets an iterator for all timeslices from time 0 until the current Blockheader time 525 unbondingTimesliceIterator, err := k.UBDQueueIterator(ctx, currTime) 526 if err != nil { 527 return matureUnbonds, err 528 } 529 defer unbondingTimesliceIterator.Close() 530 531 for ; unbondingTimesliceIterator.Valid(); unbondingTimesliceIterator.Next() { 532 timeslice := types.DVPairs{} 533 value := unbondingTimesliceIterator.Value() 534 if err = k.cdc.Unmarshal(value, ×lice); err != nil { 535 return matureUnbonds, err 536 } 537 538 matureUnbonds = append(matureUnbonds, timeslice.Pairs...) 539 540 if err = store.Delete(unbondingTimesliceIterator.Key()); err != nil { 541 return matureUnbonds, err 542 } 543 544 } 545 546 return matureUnbonds, nil 547 } 548 549 // GetRedelegations returns a given amount of all the delegator redelegations. 550 func (k Keeper) GetRedelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (redelegations []types.Redelegation, err error) { 551 redelegations = make([]types.Redelegation, maxRetrieve) 552 553 store := k.storeService.OpenKVStore(ctx) 554 delegatorPrefixKey := types.GetREDsKey(delegator) 555 iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) 556 if err != nil { 557 return nil, err 558 } 559 560 i := 0 561 for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() { 562 redelegation, err := types.UnmarshalRED(k.cdc, iterator.Value()) 563 if err != nil { 564 return nil, err 565 } 566 redelegations[i] = redelegation 567 i++ 568 } 569 570 return redelegations[:i], nil // trim if the array length < maxRetrieve 571 } 572 573 // GetRedelegation returns a redelegation. 574 func (k Keeper) GetRedelegation(ctx context.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) (red types.Redelegation, err error) { 575 store := k.storeService.OpenKVStore(ctx) 576 key := types.GetREDKey(delAddr, valSrcAddr, valDstAddr) 577 578 value, err := store.Get(key) 579 if err != nil { 580 return red, err 581 } 582 583 if value == nil { 584 return red, types.ErrNoRedelegation 585 } 586 587 return types.UnmarshalRED(k.cdc, value) 588 } 589 590 // GetRedelegationsFromSrcValidator returns all redelegations from a particular 591 // validator. 592 func (k Keeper) GetRedelegationsFromSrcValidator(ctx context.Context, valAddr sdk.ValAddress) (reds []types.Redelegation, err error) { 593 store := k.storeService.OpenKVStore(ctx) 594 prefix := types.GetREDsFromValSrcIndexKey(valAddr) 595 iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix)) 596 if err != nil { 597 return nil, err 598 } 599 defer iterator.Close() 600 601 for ; iterator.Valid(); iterator.Next() { 602 key := types.GetREDKeyFromValSrcIndexKey(iterator.Key()) 603 value, err := store.Get(key) 604 if err != nil { 605 return nil, err 606 } 607 red, err := types.UnmarshalRED(k.cdc, value) 608 if err != nil { 609 return nil, err 610 } 611 reds = append(reds, red) 612 } 613 614 return reds, nil 615 } 616 617 // HasReceivingRedelegation checks if validator is receiving a redelegation. 618 func (k Keeper) HasReceivingRedelegation(ctx context.Context, delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) (bool, error) { 619 store := k.storeService.OpenKVStore(ctx) 620 prefix := types.GetREDsByDelToValDstIndexKey(delAddr, valDstAddr) 621 iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix)) 622 if err != nil { 623 return false, err 624 } 625 defer iterator.Close() 626 return iterator.Valid(), nil 627 } 628 629 // HasMaxRedelegationEntries checks if the redelegation entries reached maximum limit. 630 func (k Keeper) HasMaxRedelegationEntries(ctx context.Context, delegatorAddr sdk.AccAddress, validatorSrcAddr, validatorDstAddr sdk.ValAddress) (bool, error) { 631 red, err := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr) 632 if err != nil { 633 if err == types.ErrNoRedelegation { 634 return false, nil 635 } 636 637 return false, err 638 } 639 maxEntries, err := k.MaxEntries(ctx) 640 if err != nil { 641 return false, err 642 } 643 644 return len(red.Entries) >= int(maxEntries), nil 645 } 646 647 // SetRedelegation sets a redelegation and associated index. 648 func (k Keeper) SetRedelegation(ctx context.Context, red types.Redelegation) error { 649 delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(red.DelegatorAddress) 650 if err != nil { 651 return err 652 } 653 654 store := k.storeService.OpenKVStore(ctx) 655 bz := types.MustMarshalRED(k.cdc, red) 656 valSrcAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorSrcAddress) 657 if err != nil { 658 return err 659 } 660 valDestAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorDstAddress) 661 if err != nil { 662 return err 663 } 664 key := types.GetREDKey(delegatorAddress, valSrcAddr, valDestAddr) 665 if err = store.Set(key, bz); err != nil { 666 return err 667 } 668 669 if err = store.Set(types.GetREDByValSrcIndexKey(delegatorAddress, valSrcAddr, valDestAddr), []byte{}); err != nil { 670 return err 671 } 672 673 return store.Set(types.GetREDByValDstIndexKey(delegatorAddress, valSrcAddr, valDestAddr), []byte{}) 674 } 675 676 // SetRedelegationEntry adds an entry to the unbonding delegation at the given 677 // addresses. It creates the unbonding delegation if it does not exist. 678 func (k Keeper) SetRedelegationEntry(ctx context.Context, 679 delegatorAddr sdk.AccAddress, validatorSrcAddr, 680 validatorDstAddr sdk.ValAddress, creationHeight int64, 681 minTime time.Time, balance math.Int, 682 sharesSrc, sharesDst math.LegacyDec, 683 ) (types.Redelegation, error) { 684 id, err := k.IncrementUnbondingID(ctx) 685 if err != nil { 686 return types.Redelegation{}, err 687 } 688 689 red, err := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr) 690 if err == nil { 691 red.AddEntry(creationHeight, minTime, balance, sharesDst, id) 692 } else if errors.Is(err, types.ErrNoRedelegation) { 693 red = types.NewRedelegation(delegatorAddr, validatorSrcAddr, 694 validatorDstAddr, creationHeight, minTime, balance, sharesDst, id, k.validatorAddressCodec, k.authKeeper.AddressCodec()) 695 } else { 696 return types.Redelegation{}, err 697 } 698 699 if err = k.SetRedelegation(ctx, red); err != nil { 700 return types.Redelegation{}, err 701 } 702 703 // Add to the UBDByEntry index to look up the UBD by the UBDE ID 704 if err = k.SetRedelegationByUnbondingID(ctx, red, id); err != nil { 705 return types.Redelegation{}, err 706 } 707 708 if err := k.Hooks().AfterUnbondingInitiated(ctx, id); err != nil { 709 k.Logger(ctx).Error("failed to call after unbonding initiated hook", "error", err) 710 // TODO (Facu): Should we return here? We are ignoring this error 711 } 712 713 return red, nil 714 } 715 716 // IterateRedelegations iterates through all redelegations. 717 func (k Keeper) IterateRedelegations(ctx context.Context, fn func(index int64, red types.Redelegation) (stop bool)) error { 718 store := k.storeService.OpenKVStore(ctx) 719 iterator, err := store.Iterator(types.RedelegationKey, storetypes.PrefixEndBytes(types.RedelegationKey)) 720 if err != nil { 721 return err 722 } 723 defer iterator.Close() 724 725 for i := int64(0); iterator.Valid(); iterator.Next() { 726 red, err := types.UnmarshalRED(k.cdc, iterator.Value()) 727 if err != nil { 728 return err 729 } 730 if stop := fn(i, red); stop { 731 break 732 } 733 i++ 734 } 735 736 return nil 737 } 738 739 // RemoveRedelegation removes a redelegation object and associated index. 740 func (k Keeper) RemoveRedelegation(ctx context.Context, red types.Redelegation) error { 741 delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(red.DelegatorAddress) 742 if err != nil { 743 return err 744 } 745 746 store := k.storeService.OpenKVStore(ctx) 747 valSrcAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorSrcAddress) 748 if err != nil { 749 return err 750 } 751 valDestAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorDstAddress) 752 if err != nil { 753 return err 754 } 755 redKey := types.GetREDKey(delegatorAddress, valSrcAddr, valDestAddr) 756 if err = store.Delete(redKey); err != nil { 757 return err 758 } 759 760 if err = store.Delete(types.GetREDByValSrcIndexKey(delegatorAddress, valSrcAddr, valDestAddr)); err != nil { 761 return err 762 } 763 764 return store.Delete(types.GetREDByValDstIndexKey(delegatorAddress, valSrcAddr, valDestAddr)) 765 } 766 767 // redelegation queue timeslice operations 768 769 // GetRedelegationQueueTimeSlice gets a specific redelegation queue timeslice. A 770 // timeslice is a slice of DVVTriplets corresponding to redelegations that 771 // expire at a certain time. 772 func (k Keeper) GetRedelegationQueueTimeSlice(ctx context.Context, timestamp time.Time) (dvvTriplets []types.DVVTriplet, err error) { 773 store := k.storeService.OpenKVStore(ctx) 774 bz, err := store.Get(types.GetRedelegationTimeKey(timestamp)) 775 if err != nil { 776 return nil, err 777 } 778 779 if bz == nil { 780 return []types.DVVTriplet{}, nil 781 } 782 783 triplets := types.DVVTriplets{} 784 err = k.cdc.Unmarshal(bz, &triplets) 785 if err != nil { 786 return nil, err 787 } 788 789 return triplets.Triplets, nil 790 } 791 792 // SetRedelegationQueueTimeSlice sets a specific redelegation queue timeslice. 793 func (k Keeper) SetRedelegationQueueTimeSlice(ctx context.Context, timestamp time.Time, keys []types.DVVTriplet) error { 794 store := k.storeService.OpenKVStore(ctx) 795 bz, err := k.cdc.Marshal(&types.DVVTriplets{Triplets: keys}) 796 if err != nil { 797 return err 798 } 799 return store.Set(types.GetRedelegationTimeKey(timestamp), bz) 800 } 801 802 // InsertRedelegationQueue insert an redelegation delegation to the appropriate 803 // timeslice in the redelegation queue. 804 func (k Keeper) InsertRedelegationQueue(ctx context.Context, red types.Redelegation, completionTime time.Time) error { 805 timeSlice, err := k.GetRedelegationQueueTimeSlice(ctx, completionTime) 806 if err != nil { 807 return err 808 } 809 dvvTriplet := types.DVVTriplet{ 810 DelegatorAddress: red.DelegatorAddress, 811 ValidatorSrcAddress: red.ValidatorSrcAddress, 812 ValidatorDstAddress: red.ValidatorDstAddress, 813 } 814 815 if len(timeSlice) == 0 { 816 return k.SetRedelegationQueueTimeSlice(ctx, completionTime, []types.DVVTriplet{dvvTriplet}) 817 } 818 819 timeSlice = append(timeSlice, dvvTriplet) 820 return k.SetRedelegationQueueTimeSlice(ctx, completionTime, timeSlice) 821 } 822 823 // RedelegationQueueIterator returns all the redelegation queue timeslices from 824 // time 0 until endTime. 825 func (k Keeper) RedelegationQueueIterator(ctx context.Context, endTime time.Time) (storetypes.Iterator, error) { 826 store := k.storeService.OpenKVStore(ctx) 827 return store.Iterator(types.RedelegationQueueKey, storetypes.InclusiveEndBytes(types.GetRedelegationTimeKey(endTime))) 828 } 829 830 // DequeueAllMatureRedelegationQueue returns a concatenated list of all the 831 // timeslices inclusively previous to currTime, and deletes the timeslices from 832 // the queue. 833 func (k Keeper) DequeueAllMatureRedelegationQueue(ctx context.Context, currTime time.Time) (matureRedelegations []types.DVVTriplet, err error) { 834 store := k.storeService.OpenKVStore(ctx) 835 836 // gets an iterator for all timeslices from time 0 until the current Blockheader time 837 sdkCtx := sdk.UnwrapSDKContext(ctx) 838 redelegationTimesliceIterator, err := k.RedelegationQueueIterator(ctx, sdkCtx.HeaderInfo().Time) 839 if err != nil { 840 return nil, err 841 } 842 defer redelegationTimesliceIterator.Close() 843 844 for ; redelegationTimesliceIterator.Valid(); redelegationTimesliceIterator.Next() { 845 timeslice := types.DVVTriplets{} 846 value := redelegationTimesliceIterator.Value() 847 if err = k.cdc.Unmarshal(value, ×lice); err != nil { 848 return nil, err 849 } 850 851 matureRedelegations = append(matureRedelegations, timeslice.Triplets...) 852 853 if err = store.Delete(redelegationTimesliceIterator.Key()); err != nil { 854 return nil, err 855 } 856 } 857 858 return matureRedelegations, nil 859 } 860 861 // Delegate performs a delegation, set/update everything necessary within the store. 862 // tokenSrc indicates the bond status of the incoming funds. 863 func (k Keeper) Delegate( 864 ctx context.Context, delAddr sdk.AccAddress, bondAmt math.Int, tokenSrc types.BondStatus, 865 validator types.Validator, subtractAccount bool, 866 ) (newShares math.LegacyDec, err error) { 867 // In some situations, the exchange rate becomes invalid, e.g. if 868 // Validator loses all tokens due to slashing. In this case, 869 // make all future delegations invalid. 870 if validator.InvalidExRate() { 871 return math.LegacyZeroDec(), types.ErrDelegatorShareExRateInvalid 872 } 873 874 valbz, err := k.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) 875 if err != nil { 876 return math.LegacyZeroDec(), err 877 } 878 879 // Get or create the delegation object and call the appropriate hook if present 880 delegation, err := k.GetDelegation(ctx, delAddr, valbz) 881 if err == nil { 882 // found 883 err = k.Hooks().BeforeDelegationSharesModified(ctx, delAddr, valbz) 884 } else if errors.Is(err, types.ErrNoDelegation) { 885 // not found 886 delAddrStr, err1 := k.authKeeper.AddressCodec().BytesToString(delAddr) 887 if err1 != nil { 888 return math.LegacyDec{}, err1 889 } 890 891 delegation = types.NewDelegation(delAddrStr, validator.GetOperator(), math.LegacyZeroDec()) 892 err = k.Hooks().BeforeDelegationCreated(ctx, delAddr, valbz) 893 } else { 894 return math.LegacyZeroDec(), err 895 } 896 897 if err != nil { 898 return math.LegacyZeroDec(), err 899 } 900 901 // if subtractAccount is true then we are 902 // performing a delegation and not a redelegation, thus the source tokens are 903 // all non bonded 904 if subtractAccount { 905 if tokenSrc == types.Bonded { 906 panic("delegation token source cannot be bonded") 907 } 908 909 var sendName string 910 911 switch { 912 case validator.IsBonded(): 913 sendName = types.BondedPoolName 914 case validator.IsUnbonding(), validator.IsUnbonded(): 915 sendName = types.NotBondedPoolName 916 default: 917 panic("invalid validator status") 918 } 919 920 bondDenom, err := k.BondDenom(ctx) 921 if err != nil { 922 return math.LegacyDec{}, err 923 } 924 925 coins := sdk.NewCoins(sdk.NewCoin(bondDenom, bondAmt)) 926 if err := k.bankKeeper.DelegateCoinsFromAccountToModule(ctx, delAddr, sendName, coins); err != nil { 927 return math.LegacyDec{}, err 928 } 929 } else { 930 // potentially transfer tokens between pools, if 931 switch { 932 case tokenSrc == types.Bonded && validator.IsBonded(): 933 // do nothing 934 case (tokenSrc == types.Unbonded || tokenSrc == types.Unbonding) && !validator.IsBonded(): 935 // do nothing 936 case (tokenSrc == types.Unbonded || tokenSrc == types.Unbonding) && validator.IsBonded(): 937 // transfer pools 938 err = k.notBondedTokensToBonded(ctx, bondAmt) 939 if err != nil { 940 return math.LegacyDec{}, err 941 } 942 case tokenSrc == types.Bonded && !validator.IsBonded(): 943 // transfer pools 944 err = k.bondedTokensToNotBonded(ctx, bondAmt) 945 if err != nil { 946 return math.LegacyDec{}, err 947 } 948 default: 949 panic("unknown token source bond status") 950 } 951 } 952 953 _, newShares, err = k.AddValidatorTokensAndShares(ctx, validator, bondAmt) 954 if err != nil { 955 return newShares, err 956 } 957 958 // Update delegation 959 delegation.Shares = delegation.Shares.Add(newShares) 960 if err = k.SetDelegation(ctx, delegation); err != nil { 961 return newShares, err 962 } 963 964 // Call the after-modification hook 965 if err := k.Hooks().AfterDelegationModified(ctx, delAddr, valbz); err != nil { 966 return newShares, err 967 } 968 969 return newShares, nil 970 } 971 972 // Unbond unbonds a particular delegation and perform associated store operations. 973 func (k Keeper) Unbond( 974 ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, shares math.LegacyDec, 975 ) (amount math.Int, err error) { 976 // check if a delegation object exists in the store 977 delegation, err := k.GetDelegation(ctx, delAddr, valAddr) 978 if errors.Is(err, types.ErrNoDelegation) { 979 return amount, types.ErrNoDelegatorForAddress 980 } else if err != nil { 981 return amount, err 982 } 983 984 // call the before-delegation-modified hook 985 if err := k.Hooks().BeforeDelegationSharesModified(ctx, delAddr, valAddr); err != nil { 986 return amount, err 987 } 988 989 // ensure that we have enough shares to remove 990 if delegation.Shares.LT(shares) { 991 return amount, errorsmod.Wrap(types.ErrNotEnoughDelegationShares, delegation.Shares.String()) 992 } 993 994 // get validator 995 validator, err := k.GetValidator(ctx, valAddr) 996 if err != nil { 997 return amount, err 998 } 999 1000 // subtract shares from delegation 1001 delegation.Shares = delegation.Shares.Sub(shares) 1002 1003 delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(delegation.DelegatorAddress) 1004 if err != nil { 1005 return amount, err 1006 } 1007 1008 valbz, err := k.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) 1009 if err != nil { 1010 return amount, err 1011 } 1012 1013 isValidatorOperator := bytes.Equal(delegatorAddress, valbz) 1014 1015 // If the delegation is the operator of the validator and undelegating will decrease the validator's 1016 // self-delegation below their minimum, we jail the validator. 1017 if isValidatorOperator && !validator.Jailed && 1018 validator.TokensFromShares(delegation.Shares).TruncateInt().LT(validator.MinSelfDelegation) { 1019 err = k.jailValidator(ctx, validator) 1020 if err != nil { 1021 return amount, err 1022 } 1023 validator = k.mustGetValidator(ctx, valbz) 1024 } 1025 1026 if delegation.Shares.IsZero() { 1027 err = k.RemoveDelegation(ctx, delegation) 1028 } else { 1029 if err = k.SetDelegation(ctx, delegation); err != nil { 1030 return amount, err 1031 } 1032 1033 valAddr, err1 := k.validatorAddressCodec.StringToBytes(delegation.GetValidatorAddr()) 1034 if err1 != nil { 1035 return amount, err1 1036 } 1037 1038 // call the after delegation modification hook 1039 err = k.Hooks().AfterDelegationModified(ctx, delegatorAddress, valAddr) 1040 } 1041 1042 if err != nil { 1043 return amount, err 1044 } 1045 1046 // remove the shares and coins from the validator 1047 // NOTE that the amount is later (in keeper.Delegation) moved between staking module pools 1048 validator, amount, err = k.RemoveValidatorTokensAndShares(ctx, validator, shares) 1049 if err != nil { 1050 return amount, err 1051 } 1052 1053 if validator.DelegatorShares.IsZero() && validator.IsUnbonded() { 1054 // if not unbonded, we must instead remove validator in EndBlocker once it finishes its unbonding period 1055 if err = k.RemoveValidator(ctx, valbz); err != nil { 1056 return amount, err 1057 } 1058 } 1059 1060 return amount, nil 1061 } 1062 1063 // getBeginInfo returns the completion time and height of a redelegation, along 1064 // with a boolean signaling if the redelegation is complete based on the source 1065 // validator. 1066 func (k Keeper) getBeginInfo( 1067 ctx context.Context, valSrcAddr sdk.ValAddress, 1068 ) (completionTime time.Time, height int64, completeNow bool, err error) { 1069 validator, err := k.GetValidator(ctx, valSrcAddr) 1070 if err != nil && errors.Is(err, types.ErrNoValidatorFound) { 1071 return 1072 } 1073 sdkCtx := sdk.UnwrapSDKContext(ctx) 1074 unbondingTime, err := k.UnbondingTime(ctx) 1075 if err != nil { 1076 return 1077 } 1078 1079 // TODO: When would the validator not be found? 1080 switch { 1081 case errors.Is(err, types.ErrNoValidatorFound) || validator.IsBonded(): 1082 // the longest wait - just unbonding period from now 1083 completionTime = sdkCtx.BlockHeader().Time.Add(unbondingTime) 1084 height = sdkCtx.BlockHeight() 1085 1086 return completionTime, height, false, nil 1087 1088 case validator.IsUnbonded(): 1089 return completionTime, height, true, nil 1090 1091 case validator.IsUnbonding(): 1092 return validator.UnbondingTime, validator.UnbondingHeight, false, nil 1093 1094 default: 1095 panic(fmt.Sprintf("unknown validator status: %s", validator.Status)) 1096 } 1097 } 1098 1099 // Undelegate unbonds an amount of delegator shares from a given validator. It 1100 // will verify that the unbonding entries between the delegator and validator 1101 // are not exceeded and unbond the staked tokens (based on shares) by creating 1102 // an unbonding object and inserting it into the unbonding queue which will be 1103 // processed during the staking EndBlocker. 1104 func (k Keeper) Undelegate( 1105 ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount math.LegacyDec, 1106 ) (time.Time, math.Int, error) { 1107 validator, err := k.GetValidator(ctx, valAddr) 1108 if err != nil { 1109 return time.Time{}, math.Int{}, err 1110 } 1111 1112 hasMaxEntries, err := k.HasMaxUnbondingDelegationEntries(ctx, delAddr, valAddr) 1113 if err != nil { 1114 return time.Time{}, math.Int{}, err 1115 } 1116 1117 if hasMaxEntries { 1118 return time.Time{}, math.Int{}, types.ErrMaxUnbondingDelegationEntries 1119 } 1120 1121 returnAmount, err := k.Unbond(ctx, delAddr, valAddr, sharesAmount) 1122 if err != nil { 1123 return time.Time{}, math.Int{}, err 1124 } 1125 1126 // transfer the validator tokens to the not bonded pool 1127 if validator.IsBonded() { 1128 err = k.bondedTokensToNotBonded(ctx, returnAmount) 1129 if err != nil { 1130 return time.Time{}, math.Int{}, err 1131 } 1132 } 1133 1134 unbondingTime, err := k.UnbondingTime(ctx) 1135 if err != nil { 1136 return time.Time{}, math.Int{}, err 1137 } 1138 1139 sdkCtx := sdk.UnwrapSDKContext(ctx) 1140 completionTime := sdkCtx.BlockHeader().Time.Add(unbondingTime) 1141 ubd, err := k.SetUnbondingDelegationEntry(ctx, delAddr, valAddr, sdkCtx.BlockHeight(), completionTime, returnAmount) 1142 if err != nil { 1143 return time.Time{}, math.Int{}, err 1144 } 1145 1146 err = k.InsertUBDQueue(ctx, ubd, completionTime) 1147 if err != nil { 1148 return time.Time{}, math.Int{}, err 1149 } 1150 1151 return completionTime, returnAmount, nil 1152 } 1153 1154 // CompleteUnbonding completes the unbonding of all mature entries in the 1155 // retrieved unbonding delegation object and returns the total unbonding balance 1156 // or an error upon failure. 1157 func (k Keeper) CompleteUnbonding(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, error) { 1158 ubd, err := k.GetUnbondingDelegation(ctx, delAddr, valAddr) 1159 if err != nil { 1160 return nil, err 1161 } 1162 1163 bondDenom, err := k.BondDenom(ctx) 1164 if err != nil { 1165 return nil, err 1166 } 1167 1168 balances := sdk.NewCoins() 1169 sdkCtx := sdk.UnwrapSDKContext(ctx) 1170 ctxTime := sdkCtx.BlockHeader().Time 1171 1172 delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress) 1173 if err != nil { 1174 return nil, err 1175 } 1176 1177 // loop through all the entries and complete unbonding mature entries 1178 for i := 0; i < len(ubd.Entries); i++ { 1179 entry := ubd.Entries[i] 1180 if entry.IsMature(ctxTime) && !entry.OnHold() { 1181 ubd.RemoveEntry(int64(i)) 1182 i-- 1183 if err = k.DeleteUnbondingIndex(ctx, entry.UnbondingId); err != nil { 1184 return nil, err 1185 } 1186 1187 // track undelegation only when remaining or truncated shares are non-zero 1188 if !entry.Balance.IsZero() { 1189 amt := sdk.NewCoin(bondDenom, entry.Balance) 1190 if err := k.bankKeeper.UndelegateCoinsFromModuleToAccount( 1191 ctx, types.NotBondedPoolName, delegatorAddress, sdk.NewCoins(amt), 1192 ); err != nil { 1193 return nil, err 1194 } 1195 1196 balances = balances.Add(amt) 1197 } 1198 } 1199 } 1200 1201 // set the unbonding delegation or remove it if there are no more entries 1202 if len(ubd.Entries) == 0 { 1203 err = k.RemoveUnbondingDelegation(ctx, ubd) 1204 } else { 1205 err = k.SetUnbondingDelegation(ctx, ubd) 1206 } 1207 1208 if err != nil { 1209 return nil, err 1210 } 1211 1212 return balances, nil 1213 } 1214 1215 // BeginRedelegation begins unbonding / redelegation and creates a redelegation 1216 // record. 1217 func (k Keeper) BeginRedelegation( 1218 ctx context.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount math.LegacyDec, 1219 ) (completionTime time.Time, err error) { 1220 if bytes.Equal(valSrcAddr, valDstAddr) { 1221 return time.Time{}, types.ErrSelfRedelegation 1222 } 1223 1224 dstValidator, err := k.GetValidator(ctx, valDstAddr) 1225 if errors.Is(err, types.ErrNoValidatorFound) { 1226 return time.Time{}, types.ErrBadRedelegationDst 1227 } else if err != nil { 1228 return time.Time{}, err 1229 } 1230 1231 srcValidator, err := k.GetValidator(ctx, valSrcAddr) 1232 if errors.Is(err, types.ErrNoValidatorFound) { 1233 return time.Time{}, types.ErrBadRedelegationSrc 1234 } else if err != nil { 1235 return time.Time{}, err 1236 } 1237 1238 // check if this is a transitive redelegation 1239 hasRecRedel, err := k.HasReceivingRedelegation(ctx, delAddr, valSrcAddr) 1240 if err != nil { 1241 return time.Time{}, err 1242 } 1243 1244 if hasRecRedel { 1245 return time.Time{}, types.ErrTransitiveRedelegation 1246 } 1247 1248 hasMaxRedels, err := k.HasMaxRedelegationEntries(ctx, delAddr, valSrcAddr, valDstAddr) 1249 if err != nil { 1250 return time.Time{}, err 1251 } 1252 1253 if hasMaxRedels { 1254 return time.Time{}, types.ErrMaxRedelegationEntries 1255 } 1256 1257 returnAmount, err := k.Unbond(ctx, delAddr, valSrcAddr, sharesAmount) 1258 if err != nil { 1259 return time.Time{}, err 1260 } 1261 1262 if returnAmount.IsZero() { 1263 return time.Time{}, types.ErrTinyRedelegationAmount 1264 } 1265 1266 sharesCreated, err := k.Delegate(ctx, delAddr, returnAmount, srcValidator.GetStatus(), dstValidator, false) 1267 if err != nil { 1268 return time.Time{}, err 1269 } 1270 1271 // create the unbonding delegation 1272 completionTime, height, completeNow, err := k.getBeginInfo(ctx, valSrcAddr) 1273 if err != nil { 1274 return time.Time{}, err 1275 } 1276 1277 if completeNow { // no need to create the redelegation object 1278 return completionTime, nil 1279 } 1280 1281 red, err := k.SetRedelegationEntry( 1282 ctx, delAddr, valSrcAddr, valDstAddr, 1283 height, completionTime, returnAmount, sharesAmount, sharesCreated, 1284 ) 1285 if err != nil { 1286 return time.Time{}, err 1287 } 1288 1289 err = k.InsertRedelegationQueue(ctx, red, completionTime) 1290 if err != nil { 1291 return time.Time{}, err 1292 } 1293 1294 return completionTime, nil 1295 } 1296 1297 // CompleteRedelegation completes the redelegations of all mature entries in the 1298 // retrieved redelegation object and returns the total redelegation (initial) 1299 // balance or an error upon failure. 1300 func (k Keeper) CompleteRedelegation( 1301 ctx context.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, 1302 ) (sdk.Coins, error) { 1303 red, err := k.GetRedelegation(ctx, delAddr, valSrcAddr, valDstAddr) 1304 if err != nil { 1305 return nil, err 1306 } 1307 1308 bondDenom, err := k.BondDenom(ctx) 1309 if err != nil { 1310 return nil, err 1311 } 1312 1313 balances := sdk.NewCoins() 1314 sdkCtx := sdk.UnwrapSDKContext(ctx) 1315 ctxTime := sdkCtx.BlockHeader().Time 1316 1317 // loop through all the entries and complete mature redelegation entries 1318 for i := 0; i < len(red.Entries); i++ { 1319 entry := red.Entries[i] 1320 if entry.IsMature(ctxTime) && !entry.OnHold() { 1321 red.RemoveEntry(int64(i)) 1322 i-- 1323 if err = k.DeleteUnbondingIndex(ctx, entry.UnbondingId); err != nil { 1324 return nil, err 1325 } 1326 1327 if !entry.InitialBalance.IsZero() { 1328 balances = balances.Add(sdk.NewCoin(bondDenom, entry.InitialBalance)) 1329 } 1330 } 1331 } 1332 1333 // set the redelegation or remove it if there are no more entries 1334 if len(red.Entries) == 0 { 1335 err = k.RemoveRedelegation(ctx, red) 1336 } else { 1337 err = k.SetRedelegation(ctx, red) 1338 } 1339 1340 if err != nil { 1341 return nil, err 1342 } 1343 1344 return balances, nil 1345 } 1346 1347 // ValidateUnbondAmount validates that a given unbond or redelegation amount is 1348 // valid based on upon the converted shares. If the amount is valid, the total 1349 // amount of respective shares is returned, otherwise an error is returned. 1350 func (k Keeper) ValidateUnbondAmount( 1351 ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt math.Int, 1352 ) (shares math.LegacyDec, err error) { 1353 validator, err := k.GetValidator(ctx, valAddr) 1354 if err != nil { 1355 return shares, err 1356 } 1357 1358 del, err := k.GetDelegation(ctx, delAddr, valAddr) 1359 if err != nil { 1360 return shares, err 1361 } 1362 1363 shares, err = validator.SharesFromTokens(amt) 1364 if err != nil { 1365 return shares, err 1366 } 1367 1368 sharesTruncated, err := validator.SharesFromTokensTruncated(amt) 1369 if err != nil { 1370 return shares, err 1371 } 1372 1373 delShares := del.GetShares() 1374 if sharesTruncated.GT(delShares) { 1375 return shares, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid shares amount") 1376 } 1377 1378 // Cap the shares at the delegation's shares. Shares being greater could occur 1379 // due to rounding, however we don't want to truncate the shares or take the 1380 // minimum because we want to allow for the full withdraw of shares from a 1381 // delegation. 1382 if shares.GT(delShares) { 1383 shares = delShares 1384 } 1385 1386 return shares, nil 1387 }