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, &timeslice); 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, &timeslice); 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  }