func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) {
	store := ctx.KVStore(k.storeKey)
	bz := types.MustMarshalRED(k.cdc, red)
	key := types.GetREDKey(red.DelegatorAccount.StoreKey(), red.ValidatorSrcAccount.StoreKey(), red.ValidatorDstAccount.StoreKey())
	store.Set(key, bz)
	store.Set(types.GetREDByValSrcIndexKey(red.DelegatorAccount.StoreKey(), red.ValidatorSrcAccount.StoreKey(), red.ValidatorDstAccount.StoreKey()), bz)
	store.Set(types.GetREDByValDstIndexKey(red.DelegatorAccount, red.ValidatorSrcAccount, red.ValidatorDstAccount), bz)
}
set a redelegation and associated index
package keeper
import (
	"bytes"
	"fmt"
	"time"
	"github.com/KuChainNetwork/kuchain/chain/constants"
	stakingexport "github.com/KuChainNetwork/kuchain/x/staking/exported"
	"github.com/KuChainNetwork/kuchain/x/staking/types"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
func (k Keeper) GetDelegation(ctx sdk.Context,
	delAddr AccountID, valAddr AccountID) (
	delegation types.Delegation, found bool) {
	store := ctx.KVStore(k.storeKey)
	key := types.GetDelegationKey(delAddr, valAddr)
	value := store.Get(key)
	if value == nil {
		return delegation, false
	}
	delegation = types.MustUnmarshalDelegation(k.cdc, value)
	return delegation, true
}
func (k Keeper) IterateAllDelegations(ctx sdk.Context, cb func(delegation types.Delegation) (stop bool)) {
	store := ctx.KVStore(k.storeKey)
	iterator := sdk.KVStorePrefixIterator(store, types.DelegationKey)
	defer iterator.Close()
	for ; iterator.Valid(); iterator.Next() {
		delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
		if cb(delegation) {
			break
		}
	}
}
func (k Keeper) GetAllDelegations(ctx sdk.Context) (delegations []types.Delegation) {
	k.IterateAllDelegations(ctx, func(delegation types.Delegation) bool {
		delegations = append(delegations, delegation)
		return false
	})
	return delegations
}
func (k Keeper) GetValidatorDelegations(ctx sdk.Context, valAddr AccountID) (delegations []types.Delegation) {  
	store := ctx.KVStore(k.storeKey)
	iterator := sdk.KVStorePrefixIterator(store, types.DelegationKey)
	defer iterator.Close()
	for ; iterator.Valid(); iterator.Next() {
		delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
		if delegation.GetValidatorAccountID().Eq(valAddr) {
			delegations = append(delegations, delegation)
		}
	}
	return delegations
}
func (k Keeper) GetDelegatorDelegations(ctx sdk.Context, delegator AccountID,
	maxRetrieve uint16) (delegations []types.Delegation) {
	delegations = make([]types.Delegation, maxRetrieve)
	store := ctx.KVStore(k.storeKey)
	delegatorPrefixKey := types.GetDelegationsKey(delegator)
	iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey)
	defer iterator.Close()
	i := 0
	for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
		delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
		delegations[i] = delegation
		i++
	}
	return delegations[:i]  
}
func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) {
	store := ctx.KVStore(k.storeKey)
	b := types.MustMarshalDelegation(k.cdc, delegation)
	store.Set(types.GetDelegationKey(delegation.DelegatorAccount, delegation.ValidatorAccount), b)
}
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
	k.BeforeDelegationRemoved(ctx, delegation.ValidatorAccount, delegation.DelegatorAccount)
	store := ctx.KVStore(k.storeKey)
	store.Delete(types.GetDelegationKey(delegation.DelegatorAccount, delegation.ValidatorAccount))
}
func (k Keeper) GetUnbondingDelegations(ctx sdk.Context, delegator AccountID,
	maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation) {
	unbondingDelegations = make([]types.UnbondingDelegation, maxRetrieve)
	store := ctx.KVStore(k.storeKey)
	delegatorPrefixKey := types.GetUBDsKey(delegator.StoreKey())
	iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey)
	defer iterator.Close()
	i := 0
	for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
		unbondingDelegation := types.MustUnmarshalUBD(k.cdc, iterator.Value())
		unbondingDelegations[i] = unbondingDelegation
		i++
	}
	return unbondingDelegations[:i]  
}
func (k Keeper) GetUnbondingDelegation(
	ctx sdk.Context, delAddr AccountID, valAddr AccountID,
) (ubd types.UnbondingDelegation, found bool) {
	store := ctx.KVStore(k.storeKey)
	key := types.GetUBDKey(delAddr.StoreKey(), valAddr.StoreKey())
	value := store.Get(key)
	if value == nil {
		return ubd, false
	}
	ubd = types.MustUnmarshalUBD(k.cdc, value)
	return ubd, true
}
func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr AccountID) (ubds []types.UnbondingDelegation) {
	store := ctx.KVStore(k.storeKey)
	iterator := sdk.KVStorePrefixIterator(store, types.GetUBDsByValIndexKey(valAddr))
	defer iterator.Close()
	for ; iterator.Valid(); iterator.Next() {
		key := types.GetUBDKeyFromValIndexKey(iterator.Key())
		value := store.Get(key)
		ubd := types.MustUnmarshalUBD(k.cdc, value)
		ubds = append(ubds, ubd)
	}
	return ubds
}
func (k Keeper) IterateUnbondingDelegations(ctx sdk.Context, fn func(index int64, ubd types.UnbondingDelegation) (stop bool)) {
	store := ctx.KVStore(k.storeKey)
	iterator := sdk.KVStorePrefixIterator(store, types.UnbondingDelegationKey)
	defer iterator.Close()
	for i := int64(0); iterator.Valid(); iterator.Next() {
		ubd := types.MustUnmarshalUBD(k.cdc, iterator.Value())
		if stop := fn(i, ubd); stop {
			break
		}
		i++
	}
}
func (k Keeper) HasMaxUnbondingDelegationEntries(ctx sdk.Context,
	delegatorAddr AccountID, validatorAddr AccountID) bool {
	name, ok := delegatorAddr.ToName()
	if ok && constants.IsSystemAccount(name) {
		return false
	}
	ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
	if !found {
		return false
	}
	return len(ubd.Entries) >= int(k.MaxEntries(ctx))
}
func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) {
	store := ctx.KVStore(k.storeKey)
	bz := types.MustMarshalUBD(k.cdc, ubd)
	key := types.GetUBDKey(ubd.DelegatorAccount.StoreKey(), ubd.ValidatorAccount.StoreKey())
	store.Set(key, bz)
	store.Set(types.GetUBDByValIndexKey(ubd.DelegatorAccount, ubd.ValidatorAccount), bz)  
}
func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) {
	store := ctx.KVStore(k.storeKey)
	key := types.GetUBDKey(ubd.DelegatorAccount.StoreKey(), ubd.ValidatorAccount.StoreKey())
	store.Delete(key)
	store.Delete(types.GetUBDByValIndexKey(ubd.DelegatorAccount, ubd.ValidatorAccount))
}
func (k Keeper) SetUnbondingDelegationEntry(
	ctx sdk.Context, delegatorAddr AccountID, validatorAddr AccountID,
	creationHeight int64, minTime time.Time, balance sdk.Int,
) types.UnbondingDelegation {
	ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
	if found {
		ubd.AddEntry(creationHeight, minTime, balance)
	} else {
		ubd = types.NewUnbondingDelegation(delegatorAddr, validatorAddr, creationHeight, minTime, balance)
	}
	k.SetUnbondingDelegation(ctx, ubd)
	return ubd
}
func (k Keeper) GetUBDQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (dvPairs []types.DVPair) {
	store := ctx.KVStore(k.storeKey)
	bz := store.Get(types.GetUnbondingDelegationTimeKey(timestamp))
	if bz == nil {
		return []types.DVPair{}
	}
	pairs := types.DVPairs{}
	k.cdc.MustUnmarshalBinaryBare(bz, &pairs)
	return pairs.Pairs
}
func (k Keeper) SetUBDQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []types.DVPair) {
	store := ctx.KVStore(k.storeKey)
	bz := k.cdc.MustMarshalBinaryBare(&types.DVPairs{Pairs: keys})
	store.Set(types.GetUnbondingDelegationTimeKey(timestamp), bz)
}
func (k Keeper) InsertUBDQueue(ctx sdk.Context, ubd types.UnbondingDelegation,
	completionTime time.Time) {
	timeSlice := k.GetUBDQueueTimeSlice(ctx, completionTime)
	dvPair := types.DVPair{DelegatorAccount: ubd.DelegatorAccount, ValidatorAccount: ubd.ValidatorAccount}
	if len(timeSlice) == 0 {
		k.SetUBDQueueTimeSlice(ctx, completionTime, []types.DVPair{dvPair})
	} else {
		timeSlice = append(timeSlice, dvPair)
		k.SetUBDQueueTimeSlice(ctx, completionTime, timeSlice)
	}
}
func (k Keeper) UBDQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
	store := ctx.KVStore(k.storeKey)
	return store.Iterator(types.UnbondingQueueKey,
		sdk.InclusiveEndBytes(types.GetUnbondingDelegationTimeKey(endTime)))
}
func (k Keeper) DequeueAllMatureUBDQueue(ctx sdk.Context, currTime time.Time) (matureUnbonds []types.DVPair) {
	store := ctx.KVStore(k.storeKey)
	unbondingTimesliceIterator := k.UBDQueueIterator(ctx, ctx.BlockHeader().Time)
	for ; unbondingTimesliceIterator.Valid(); unbondingTimesliceIterator.Next() {
		timeslice := types.DVPairs{}
		value := unbondingTimesliceIterator.Value()
		k.cdc.MustUnmarshalBinaryBare(value, &timeslice)
		matureUnbonds = append(matureUnbonds, timeslice.Pairs...)
		store.Delete(unbondingTimesliceIterator.Key())
	}
	return matureUnbonds
}
func (k Keeper) GetRedelegations(ctx sdk.Context, delegator AccountID,
	maxRetrieve uint16) (redelegations []types.Redelegation) {
	redelegations = make([]types.Redelegation, maxRetrieve)
	store := ctx.KVStore(k.storeKey)
	delegatorPrefixKey := types.GetREDsKey(delegator.StoreKey())
	iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey)
	defer iterator.Close()
	i := 0
	for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
		redelegation := types.MustUnmarshalRED(k.cdc, iterator.Value())
		redelegations[i] = redelegation
		i++
	}
	return redelegations[:i]  
}
func (k Keeper) GetRedelegation(ctx sdk.Context,
	delAddr AccountID, valSrcAddr, valDstAddr AccountID) (red types.Redelegation, found bool) {
	store := ctx.KVStore(k.storeKey)
	key := types.GetREDKey(delAddr.StoreKey(), valSrcAddr.StoreKey(), valDstAddr.StoreKey())
	value := store.Get(key)
	if value == nil {
		return red, false
	}
	red = types.MustUnmarshalRED(k.cdc, value)
	return red, true
}
func (k Keeper) GetRedelegationsFromSrcValidator(ctx sdk.Context, valAddr AccountID) (reds []types.Redelegation) {
	store := ctx.KVStore(k.storeKey)
	iterator := sdk.KVStorePrefixIterator(store, types.GetREDsFromValSrcIndexKey(valAddr.StoreKey()))
	defer iterator.Close()
	for ; iterator.Valid(); iterator.Next() {
		key := types.GetREDKeyFromValSrcIndexKey(iterator.Key())
		value := store.Get(key)
		red := types.MustUnmarshalRED(k.cdc, value)
		reds = append(reds, red)
	}
	return reds
}
func (k Keeper) HasReceivingRedelegation(ctx sdk.Context,
	delAddr AccountID, valDstAddr AccountID) bool {
	name, ok := delAddr.ToName()
	if ok && constants.IsSystemAccount(name) {
		return false
	}
	store := ctx.KVStore(k.storeKey)
	prefix := types.GetREDsByDelToValDstIndexKey(delAddr, valDstAddr)
	iterator := sdk.KVStorePrefixIterator(store, prefix)
	defer iterator.Close()
	return iterator.Valid()
}
func (k Keeper) HasMaxRedelegationEntries(ctx sdk.Context,
	delegatorAddr AccountID, validatorSrcAddr,
	validatorDstAddr AccountID) bool {
	name, ok := delegatorAddr.ToName()
	if ok && constants.IsSystemAccount(name) {
		return false
	}
	red, found := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr)
	if !found {
		return false
	}
	return len(red.Entries) >= int(k.MaxEntries(ctx))
}