github.com/KiraCore/sekai@v0.3.43/x/gov/keeper/identity_registrar.go (about)

     1  package keeper
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"regexp"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/KiraCore/sekai/x/gov/types"
    12  	stakingtypes "github.com/KiraCore/sekai/x/staking/types"
    13  	"github.com/cosmos/cosmos-sdk/store/prefix"
    14  	sdk "github.com/cosmos/cosmos-sdk/types"
    15  	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    16  )
    17  
    18  func ValidateIdentityRecordKey(key string) bool {
    19  	regex := regexp.MustCompile(`^[a-zA-Z][_0-9a-zA-Z]*$`)
    20  	return regex.MatchString(key)
    21  }
    22  
    23  func FormalizeIdentityRecordKey(key string) string {
    24  	return strings.ToLower(key)
    25  }
    26  
    27  func CheckIfWithinStringArray(key string, keys []string) bool {
    28  	for _, k := range keys {
    29  		if k == key {
    30  			return true
    31  		}
    32  	}
    33  	return false
    34  }
    35  
    36  func CheckIfWithinAddressArray(addr sdk.AccAddress, array []sdk.AccAddress) bool {
    37  	for _, itemAddr := range array {
    38  		if bytes.Equal(addr, itemAddr) {
    39  			return true
    40  		}
    41  	}
    42  	return false
    43  }
    44  
    45  func (k Keeper) GetLastIdentityRecordId(ctx sdk.Context) uint64 {
    46  	store := ctx.KVStore(k.storeKey)
    47  
    48  	bz := store.Get(types.KeyLastIdentityRecordId)
    49  	if bz == nil {
    50  		return 0
    51  	}
    52  
    53  	return sdk.BigEndianToUint64(bz)
    54  }
    55  
    56  func (k Keeper) SetLastIdentityRecordId(ctx sdk.Context, id uint64) {
    57  	store := ctx.KVStore(k.storeKey)
    58  	store.Set(types.KeyLastIdentityRecordId, sdk.Uint64ToBigEndian(id))
    59  }
    60  
    61  func (k Keeper) GetLastIdRecordVerifyRequestId(ctx sdk.Context) uint64 {
    62  	store := ctx.KVStore(k.storeKey)
    63  
    64  	bz := store.Get(types.KeyLastIdRecordVerifyRequestId)
    65  	if bz == nil {
    66  		return 0
    67  	}
    68  
    69  	return sdk.BigEndianToUint64(bz)
    70  }
    71  
    72  func (k Keeper) SetLastIdRecordVerifyRequestId(ctx sdk.Context, id uint64) {
    73  	store := ctx.KVStore(k.storeKey)
    74  	store.Set(types.KeyLastIdRecordVerifyRequestId, sdk.Uint64ToBigEndian(id))
    75  }
    76  
    77  // SetIdentityRecord defines a method to set identity record
    78  func (k Keeper) SetIdentityRecord(ctx sdk.Context, record types.IdentityRecord) {
    79  	// validate key
    80  	if !ValidateIdentityRecordKey(record.Key) {
    81  		panic("identity record key is invalid")
    82  	}
    83  	properties := k.GetNetworkProperties(ctx)
    84  	uniqueKeys := strings.Split(properties.UniqueIdentityKeys, ",")
    85  	if CheckIfWithinStringArray(record.Key, uniqueKeys) {
    86  		addrs := k.GetAddressesByIdRecordKey(ctx, record.Key, record.Value)
    87  		if len(addrs) == 1 && addrs[0].String() == record.Address {
    88  
    89  		} else if len(addrs) > 0 {
    90  			panic(fmt.Sprintf("the key %s, value %s is already registered by %s", record.Key, record.Value, addrs[0].String()))
    91  		}
    92  	}
    93  	// set the key to non case-sensitive
    94  	record.Key = FormalizeIdentityRecordKey(record.Key)
    95  
    96  	prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixIdentityRecord)
    97  	bz := k.cdc.MustMarshal(&record)
    98  	prefixStore.Set(sdk.Uint64ToBigEndian(record.Id), bz)
    99  
   100  	// connect address + key to id
   101  	store := ctx.KVStore(k.storeKey)
   102  	addrPrefixStore := prefix.NewStore(store, types.IdentityRecordByAddressPrefix(record.Address))
   103  	addrPrefixStore.Set([]byte(record.Key), sdk.Uint64ToBigEndian(record.Id))
   104  }
   105  
   106  func (k Keeper) GetIdentityRecordById(ctx sdk.Context, recordId uint64) *types.IdentityRecord {
   107  	record := types.IdentityRecord{}
   108  
   109  	prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixIdentityRecord)
   110  	bz := prefixStore.Get(sdk.Uint64ToBigEndian(recordId))
   111  	if bz == nil {
   112  		return nil
   113  	}
   114  	k.cdc.MustUnmarshal(bz, &record)
   115  	return &record
   116  }
   117  
   118  // Get identity record id by address and key
   119  func (k Keeper) GetIdentityRecordIdByAddressKey(ctx sdk.Context, address sdk.AccAddress, key string) uint64 {
   120  	// validate key
   121  	if !ValidateIdentityRecordKey(key) {
   122  		return 0
   123  	}
   124  	// set the key to non case-sensitive
   125  	key = FormalizeIdentityRecordKey(key)
   126  
   127  	store := ctx.KVStore(k.storeKey)
   128  	prefixStore := prefix.NewStore(store, types.IdentityRecordByAddressPrefix(address.String()))
   129  	recordIdBytes := prefixStore.Get([]byte(key))
   130  	if recordIdBytes == nil {
   131  		return 0
   132  	}
   133  	return sdk.BigEndianToUint64(recordIdBytes)
   134  }
   135  
   136  // DeleteIdentityRecord defines a method to delete identity record by id
   137  func (k Keeper) DeleteIdentityRecordById(ctx sdk.Context, recordId uint64) {
   138  	record := k.GetIdentityRecordById(ctx, recordId)
   139  	if record == nil {
   140  		return
   141  	}
   142  	recordKey := sdk.Uint64ToBigEndian(recordId)
   143  	prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixIdentityRecord).Delete(recordKey)
   144  	prefix.NewStore(ctx.KVStore(k.storeKey), types.IdentityRecordByAddressPrefix(record.Address)).Delete(sdk.Uint64ToBigEndian(recordId))
   145  }
   146  
   147  // RegisterIdentityRecord defines a method to register identity records for an address
   148  func (k Keeper) RegisterIdentityRecords(ctx sdk.Context, address sdk.AccAddress, infos []types.IdentityInfoEntry) error {
   149  	// validate key and set the key to non case-sensitive
   150  	properties := k.GetNetworkProperties(ctx)
   151  	uniqueKeys := strings.Split(properties.UniqueIdentityKeys, ",")
   152  	for i, info := range infos {
   153  		if !ValidateIdentityRecordKey(info.Key) {
   154  			return sdkerrors.Wrap(types.ErrInvalidIdentityRecordKey, fmt.Sprintf("invalid key exists: key=%s", info.Key))
   155  		}
   156  		infos[i].Key = FormalizeIdentityRecordKey(info.Key)
   157  
   158  		if infos[i].Key == "moniker" && len(infos[i].Info) > 32 {
   159  			return stakingtypes.ErrInvalidMonikerLength
   160  		}
   161  		if infos[i].Key == "username" && len(infos[i].Info) > 32 {
   162  			return stakingtypes.ErrInvalidUsernameLength
   163  		}
   164  
   165  		// check when the user is councilor
   166  		_, found := k.GetCouncilor(ctx, address)
   167  		if found {
   168  			monikerRecordId := k.GetIdentityRecordIdByAddressKey(ctx, address, "moniker")
   169  			usernameRecordId := k.GetIdentityRecordIdByAddressKey(ctx, address, "username")
   170  			moniker := k.GetIdentityRecordById(ctx, monikerRecordId)
   171  			username := k.GetIdentityRecordById(ctx, usernameRecordId)
   172  			if infos[i].Key == "moniker" && moniker != nil && infos[i].Info != moniker.Value {
   173  				return types.ErrCouncilorMonikerNotAllowedToBeChanged
   174  			}
   175  			if infos[i].Key == "username" && username != nil && infos[i].Info != username.Value {
   176  				return types.ErrCouncilorUsernameNotAllowedToBeChanged
   177  			}
   178  		}
   179  
   180  		if CheckIfWithinStringArray(infos[i].Key, uniqueKeys) {
   181  			addrs := k.GetAddressesByIdRecordKey(ctx, infos[i].Key, infos[i].Info)
   182  			if len(addrs) == 1 && bytes.Equal(addrs[0], address) {
   183  
   184  			} else if len(addrs) > 0 {
   185  				return sdkerrors.Wrap(types.ErrKeyShouldBeUnique, fmt.Sprintf("the key %s, value %s is already registered by %s", infos[i].Key, infos[i].Info, addrs[0].String()))
   186  			}
   187  		}
   188  	}
   189  
   190  	for _, info := range infos {
   191  		// use existing record id if it already exists
   192  		recordId := k.GetIdentityRecordIdByAddressKey(ctx, address, info.Key)
   193  		if recordId == 0 {
   194  			recordId = k.GetLastIdentityRecordId(ctx) + 1
   195  			k.SetLastIdentityRecordId(ctx, recordId)
   196  		}
   197  		// create or update identity record
   198  		k.SetIdentityRecord(ctx, types.IdentityRecord{
   199  			Id:        recordId,
   200  			Address:   address.String(),
   201  			Key:       info.Key,
   202  			Value:     info.Info,
   203  			Date:      ctx.BlockTime(),
   204  			Verifiers: []string{},
   205  		})
   206  	}
   207  	return nil
   208  }
   209  
   210  // DeleteIdentityRecords defines a method to delete identity records owned by an address
   211  func (k Keeper) DeleteIdentityRecords(ctx sdk.Context, address sdk.AccAddress, keys []string) error {
   212  	// validate key and set the key to non case-sensitive
   213  	for i, key := range keys {
   214  		if !ValidateIdentityRecordKey(key) {
   215  			return sdkerrors.Wrap(types.ErrInvalidIdentityRecordKey, fmt.Sprintf("invalid key exists: key=%s", key))
   216  		}
   217  		keys[i] = FormalizeIdentityRecordKey(key)
   218  
   219  		// we prevent deleting moniker field of a validator
   220  		if key == "moniker" {
   221  			return sdkerrors.Wrap(types.ErrMonikerDeletionNotAllowed, fmt.Sprintf("moniker field is not allowed to delete"))
   222  		}
   223  	}
   224  
   225  	store := ctx.KVStore(k.storeKey)
   226  	prefix := types.IdentityRecordByAddressPrefix(address.String())
   227  	iterator := sdk.KVStorePrefixIterator(store, prefix)
   228  	defer iterator.Close()
   229  
   230  	keyMap := make(map[string]bool)
   231  	for _, key := range keys {
   232  		keyMap[key] = true
   233  	}
   234  	recordIds := []uint64{}
   235  	for ; iterator.Valid(); iterator.Next() {
   236  		key := bytes.TrimPrefix(iterator.Key(), prefix)
   237  		if len(keys) == 0 || keyMap[string(key)] {
   238  			// if no specific keys are provided remove all
   239  			// invalid keys are ignored
   240  			recordIds = append(recordIds, sdk.BigEndianToUint64(iterator.Value()))
   241  			store.Delete(iterator.Key())
   242  		}
   243  	}
   244  
   245  	recordIdMap := make(map[uint64]bool)
   246  	for _, recordId := range recordIds {
   247  		prevRecord := k.GetIdentityRecordById(ctx, recordId)
   248  		if prevRecord == nil {
   249  			return sdkerrors.Wrap(types.ErrInvalidIdentityRecordId, fmt.Sprintf("identity record with specified id does NOT exist: id=%d", recordId))
   250  		}
   251  
   252  		recordIdMap[recordId] = true
   253  		k.DeleteIdentityRecordById(ctx, recordId)
   254  	}
   255  
   256  	// remove record ids from verification request list
   257  	requests := k.GetIdRecordsVerifyRequestsByRequester(ctx, address)
   258  	for _, request := range requests {
   259  		recordIds := []uint64{}
   260  		for _, recordid := range request.RecordIds {
   261  			if !recordIdMap[recordid] {
   262  				recordIds = append(recordIds, recordid)
   263  			}
   264  		}
   265  
   266  		if len(recordIds) == 0 {
   267  			err := k.CancelIdentityRecordsVerifyRequest(ctx, sdk.MustAccAddressFromBech32(request.Address), request.Id)
   268  			if err != nil {
   269  				return err
   270  			}
   271  		} else {
   272  			request.RecordIds = recordIds
   273  			k.SetIdentityRecordsVerifyRequest(ctx, request)
   274  		}
   275  	}
   276  	return nil
   277  }
   278  
   279  // GetAllIdentityRecords query all identity records
   280  func (k Keeper) GetAllIdentityRecords(ctx sdk.Context) []types.IdentityRecord {
   281  	records := []types.IdentityRecord{}
   282  	store := ctx.KVStore(k.storeKey)
   283  	iterator := sdk.KVStorePrefixIterator(store, types.KeyPrefixIdentityRecord)
   284  	defer iterator.Close()
   285  
   286  	for ; iterator.Valid(); iterator.Next() {
   287  		record := types.IdentityRecord{}
   288  		k.cdc.MustUnmarshal(iterator.Value(), &record)
   289  		records = append(records, record)
   290  	}
   291  
   292  	return records
   293  }
   294  
   295  // GetIdRecordsByAddressAndKeys query identity record by address and keys
   296  func (k Keeper) GetIdRecordsByAddressAndKeys(ctx sdk.Context, address sdk.AccAddress, keys []string) ([]types.IdentityRecord, error) {
   297  	// validate key and set the key to non case-sensitive
   298  	for i, key := range keys {
   299  		if !ValidateIdentityRecordKey(key) {
   300  			return []types.IdentityRecord{}, sdkerrors.Wrap(types.ErrInvalidIdentityRecordKey, fmt.Sprintf("invalid key exists: key=%s", key))
   301  		}
   302  		keys[i] = FormalizeIdentityRecordKey(key)
   303  	}
   304  
   305  	if len(keys) == 0 {
   306  		return k.GetIdRecordsByAddress(ctx, address), nil
   307  	}
   308  
   309  	store := ctx.KVStore(k.storeKey)
   310  	prefixStore := prefix.NewStore(store, types.IdentityRecordByAddressPrefix(address.String()))
   311  
   312  	records := []types.IdentityRecord{}
   313  	for _, key := range keys {
   314  		bz := prefixStore.Get([]byte(key))
   315  		recordId := sdk.BigEndianToUint64(bz)
   316  		record := k.GetIdentityRecordById(ctx, recordId)
   317  		if record == nil {
   318  			return records, sdkerrors.Wrap(types.ErrInvalidIdentityRecordId, fmt.Sprintf("identity record with specified id does NOT exist: id=%d", recordId))
   319  		}
   320  		records = append(records, *record)
   321  	}
   322  	return records, nil
   323  }
   324  
   325  func (k Keeper) GetAddressesByIdRecordKey(ctx sdk.Context, key, value string) []sdk.AccAddress {
   326  	addrs := []sdk.AccAddress{}
   327  	for _, record := range k.GetAllIdentityRecords(ctx) {
   328  		if record.Key == key && record.Value == value {
   329  			addr, err := sdk.AccAddressFromBech32(record.Address)
   330  			if err != nil {
   331  				panic(err)
   332  			}
   333  			addrs = append(addrs, addr)
   334  		}
   335  	}
   336  	return addrs
   337  }
   338  
   339  // GetIdRecordsByAddress query identity record by address
   340  func (k Keeper) GetIdRecordsByAddress(ctx sdk.Context, address sdk.AccAddress) []types.IdentityRecord {
   341  	store := ctx.KVStore(k.storeKey)
   342  	prefix := types.IdentityRecordByAddressPrefix(address.String())
   343  	iterator := sdk.KVStorePrefixIterator(store, prefix)
   344  	defer iterator.Close()
   345  
   346  	records := []types.IdentityRecord{}
   347  	for ; iterator.Valid(); iterator.Next() {
   348  		recordId := sdk.BigEndianToUint64(iterator.Value())
   349  		record := k.GetIdentityRecordById(ctx, recordId)
   350  		if record == nil {
   351  			panic(fmt.Sprintf("invalid recordId exists: recordId = %d, key=%s, value=%s", recordId, string(iterator.Key()), string(iterator.Value())))
   352  		}
   353  		records = append(records, *record)
   354  	}
   355  	return records
   356  }
   357  
   358  // SetIdentityRecordsVerifyRequest saves identity verify request into the store
   359  func (k Keeper) SetIdentityRecordsVerifyRequest(ctx sdk.Context, request types.IdentityRecordsVerify) {
   360  	requestId := request.Id
   361  	bz := k.cdc.MustMarshal(&request)
   362  	prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixIdRecordVerifyRequest).Set(sdk.Uint64ToBigEndian(requestId), bz)
   363  	prefix.NewStore(
   364  		ctx.KVStore(k.storeKey),
   365  		types.IdRecordVerifyRequestByRequesterPrefix(request.Address),
   366  	).Set(sdk.Uint64ToBigEndian(requestId), sdk.Uint64ToBigEndian(requestId))
   367  	prefix.NewStore(
   368  		ctx.KVStore(k.storeKey),
   369  		types.IdRecordVerifyRequestByApproverPrefix(request.Verifier),
   370  	).Set(sdk.Uint64ToBigEndian(requestId), sdk.Uint64ToBigEndian(requestId))
   371  }
   372  
   373  // RequestIdentityRecordsVerify defines a method to request verify request from specific verifier
   374  func (k Keeper) RequestIdentityRecordsVerify(ctx sdk.Context, address, verifier sdk.AccAddress, recordIds []uint64, tip sdk.Coin) (uint64, error) {
   375  	requestId := k.GetLastIdRecordVerifyRequestId(ctx) + 1
   376  	store := ctx.KVStore(k.storeKey)
   377  	prefix := types.IdentityRecordByAddressPrefix(address.String())
   378  	iterator := sdk.KVStorePrefixIterator(store, prefix)
   379  	defer iterator.Close()
   380  
   381  	idsMap := make(map[uint64]bool)
   382  	for ; iterator.Valid(); iterator.Next() {
   383  		idsMap[sdk.BigEndianToUint64(iterator.Value())] = true
   384  	}
   385  
   386  	for _, recordId := range recordIds {
   387  		if !idsMap[recordId] {
   388  			return requestId, sdkerrors.Wrap(types.ErrInvalidIdentityRecordId, fmt.Sprintf("executor is not owner of the identity record: id=%d", recordId))
   389  		}
   390  	}
   391  
   392  	lastRecordEditDate := time.Time{}
   393  	for _, recordId := range recordIds {
   394  		record := k.GetIdentityRecordById(ctx, recordId)
   395  		if record == nil {
   396  			return requestId, sdkerrors.Wrap(types.ErrInvalidIdentityRecordId, fmt.Sprintf("identity record with specified id does NOT exist: id=%d", recordId))
   397  		}
   398  		if lastRecordEditDate.Before(record.Date) {
   399  			lastRecordEditDate = record.Date
   400  		}
   401  	}
   402  
   403  	request := types.IdentityRecordsVerify{
   404  		Id:                 requestId,
   405  		Address:            address.String(),
   406  		Verifier:           verifier.String(),
   407  		RecordIds:          recordIds,
   408  		Tip:                tip,
   409  		LastRecordEditDate: lastRecordEditDate,
   410  	}
   411  
   412  	minApprovalTip := k.GetNetworkProperties(ctx).MinIdentityApprovalTip
   413  	if sdk.NewInt(int64(minApprovalTip)).GT(tip.Amount) {
   414  		return requestId, sdkerrors.Wrap(types.ErrInvalidApprovalTip, fmt.Sprintf("approval tip is lower than minimum tip configured by the network"))
   415  	}
   416  
   417  	k.SetIdentityRecordsVerifyRequest(ctx, request)
   418  	k.SetLastIdRecordVerifyRequestId(ctx, requestId)
   419  
   420  	if !tip.Amount.IsZero() {
   421  		if err := k.bk.SendCoinsFromAccountToModule(ctx, address, types.ModuleName, sdk.Coins{tip}); err != nil {
   422  			return 0, err
   423  		}
   424  	}
   425  	return requestId, nil
   426  }
   427  
   428  // GetIdRecordsVerifyRequest defines a method to get an identity records verify request by id
   429  func (k Keeper) GetIdRecordsVerifyRequest(ctx sdk.Context, requestId uint64) *types.IdentityRecordsVerify {
   430  	request := types.IdentityRecordsVerify{}
   431  
   432  	prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixIdRecordVerifyRequest)
   433  	bz := prefixStore.Get(sdk.Uint64ToBigEndian(requestId))
   434  	if bz == nil {
   435  		return nil
   436  	}
   437  	k.cdc.MustUnmarshal(bz, &request)
   438  	return &request
   439  }
   440  
   441  // DeleteIdRecordsVerifyRequest defines a method to get an identity records verify request by id
   442  func (k Keeper) DeleteIdRecordsVerifyRequest(ctx sdk.Context, requestId uint64) {
   443  	request := k.GetIdRecordsVerifyRequest(ctx, requestId)
   444  	if request == nil {
   445  		return
   446  	}
   447  	prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixIdRecordVerifyRequest).Delete(sdk.Uint64ToBigEndian(requestId))
   448  	prefix.NewStore(
   449  		ctx.KVStore(k.storeKey),
   450  		types.IdRecordVerifyRequestByRequesterPrefix(request.Address),
   451  	).Delete(sdk.Uint64ToBigEndian(requestId))
   452  	prefix.NewStore(
   453  		ctx.KVStore(k.storeKey),
   454  		types.IdRecordVerifyRequestByApproverPrefix(request.Verifier),
   455  	).Delete(sdk.Uint64ToBigEndian(requestId))
   456  }
   457  
   458  // ApproveIdentityRecords defines a method to accept or reject verification request
   459  func (k Keeper) HandleIdentityRecordsVerifyRequest(ctx sdk.Context, verifier sdk.AccAddress, requestId uint64, approve bool) error {
   460  	request := k.GetIdRecordsVerifyRequest(ctx, requestId)
   461  	if request == nil {
   462  		return sdkerrors.Wrap(types.ErrInvalidVerifyRequestId, fmt.Sprintf("specified identity record verify request does NOT exist: id=%d", requestId))
   463  	}
   464  	if verifier.String() != request.Verifier {
   465  		return errors.New("verifier does not match with requested")
   466  	}
   467  
   468  	// send the balance regardless approve or reject
   469  	if !request.Tip.Amount.IsZero() {
   470  		if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, verifier, sdk.Coins{request.Tip}); err != nil {
   471  			return err
   472  		}
   473  	}
   474  
   475  	// automatically reject if last record edit date is incorrect
   476  	for _, recordId := range request.RecordIds {
   477  		record := k.GetIdentityRecordById(ctx, recordId)
   478  		if record == nil {
   479  			return sdkerrors.Wrap(types.ErrInvalidIdentityRecordId, fmt.Sprintf("identity record with specified id does NOT exist: id=%d", recordId))
   480  		}
   481  
   482  		if record.Date.After(request.LastRecordEditDate) {
   483  			approve = false
   484  			break
   485  		}
   486  	}
   487  
   488  	if approve == false {
   489  		k.DeleteIdRecordsVerifyRequest(ctx, requestId)
   490  		return nil
   491  	}
   492  
   493  	for _, recordId := range request.RecordIds {
   494  		record := k.GetIdentityRecordById(ctx, recordId)
   495  		if record == nil {
   496  			return sdkerrors.Wrap(types.ErrInvalidIdentityRecordId, fmt.Sprintf("identity record with specified id does NOT exist: id=%d", recordId))
   497  		}
   498  
   499  		// if already exist, skip
   500  		if CheckIfWithinStringArray(verifier.String(), record.Verifiers) {
   501  			continue
   502  		}
   503  		record.Verifiers = append(record.Verifiers, verifier.String())
   504  		k.SetIdentityRecord(ctx, *record)
   505  	}
   506  
   507  	k.DeleteIdRecordsVerifyRequest(ctx, requestId)
   508  	return nil
   509  }
   510  
   511  // CancelIdentityRecordsVerifyRequest defines a method to cancel verification request
   512  func (k Keeper) CancelIdentityRecordsVerifyRequest(ctx sdk.Context, executor sdk.AccAddress, requestId uint64) error {
   513  	request := k.GetIdRecordsVerifyRequest(ctx, requestId)
   514  	if request == nil {
   515  		return sdkerrors.Wrap(types.ErrInvalidVerifyRequestId, fmt.Sprintf("specified identity record verify request does NOT exist: id=%d", requestId))
   516  	}
   517  	if executor.String() != request.Address {
   518  		return errors.New("executor is not identity record creator")
   519  	}
   520  
   521  	if !request.Tip.Amount.IsZero() {
   522  		requester, err := sdk.AccAddressFromBech32(request.Address)
   523  		if err != nil {
   524  			return err
   525  		}
   526  		if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, requester, sdk.Coins{request.Tip}); err != nil {
   527  			return err
   528  		}
   529  	}
   530  
   531  	k.DeleteIdRecordsVerifyRequest(ctx, requestId)
   532  	return nil
   533  }
   534  
   535  // GetIdRecordsVerifyRequestsByRequester query identity record verify requests by requester
   536  func (k Keeper) GetIdRecordsVerifyRequestsByRequester(ctx sdk.Context, requester sdk.AccAddress) []types.IdentityRecordsVerify {
   537  	requests := []types.IdentityRecordsVerify{}
   538  	store := ctx.KVStore(k.storeKey)
   539  	iterator := sdk.KVStorePrefixIterator(store, types.IdRecordVerifyRequestByRequesterPrefix(requester.String()))
   540  	defer iterator.Close()
   541  
   542  	for ; iterator.Valid(); iterator.Next() {
   543  		requestId := sdk.BigEndianToUint64(iterator.Value())
   544  		request := k.GetIdRecordsVerifyRequest(ctx, requestId)
   545  		if request == nil {
   546  			panic(fmt.Errorf("invalid id available on requests: %d", requestId))
   547  		}
   548  		requests = append(requests, *request)
   549  	}
   550  
   551  	return requests
   552  }
   553  
   554  // GetIdRecordsVerifyRequestsByApprover query identity records verify requests by approver
   555  func (k Keeper) GetIdRecordsVerifyRequestsByApprover(ctx sdk.Context, requester sdk.AccAddress) []types.IdentityRecordsVerify {
   556  	requests := []types.IdentityRecordsVerify{}
   557  	store := ctx.KVStore(k.storeKey)
   558  	iterator := sdk.KVStorePrefixIterator(store, types.IdRecordVerifyRequestByApproverPrefix(requester.String()))
   559  	defer iterator.Close()
   560  
   561  	for ; iterator.Valid(); iterator.Next() {
   562  		requestId := sdk.BigEndianToUint64(iterator.Value())
   563  		request := k.GetIdRecordsVerifyRequest(ctx, requestId)
   564  		if request == nil {
   565  			panic(fmt.Errorf("invalid id available on requests: %d", requestId))
   566  		}
   567  		requests = append(requests, *request)
   568  	}
   569  
   570  	return requests
   571  }
   572  
   573  // GetAllIdRecordsVerifyRequests query all identity records verify requests
   574  func (k Keeper) GetAllIdRecordsVerifyRequests(ctx sdk.Context) []types.IdentityRecordsVerify {
   575  	requests := []types.IdentityRecordsVerify{}
   576  	store := ctx.KVStore(k.storeKey)
   577  	iterator := sdk.KVStorePrefixIterator(store, types.KeyPrefixIdRecordVerifyRequest)
   578  	defer iterator.Close()
   579  
   580  	for ; iterator.Valid(); iterator.Next() {
   581  		request := types.IdentityRecordsVerify{}
   582  		k.cdc.MustUnmarshal(iterator.Value(), &request)
   583  		requests = append(requests, request)
   584  	}
   585  
   586  	return requests
   587  }