func (fes *APIServer) AdminRemoveVerificationBadge(ww http.ResponseWriter, req *http.Request) {
	requestData := AdminRemoveVerificationBadgeRequest{}
	decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes))
	if err := decoder.Decode(&requestData); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Problem parsing request body: %v", err))
		return
	}
	usernameToRemove := requestData.UsernameForWhomToRemoveVerification
	if len(usernameToRemove) == 0 || len(usernameToRemove) > lib.MaxUsernameLengthBytes || !lib.UsernameRegex.Match([]byte(usernameToRemove)) {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Must provide a valid username"))
		return
	}
	pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(usernameToRemove)
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Username has no associated underlying publickey"))
		return
	}
	utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView()
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Problem getting utxoView: %v", err))
		return
	}
	pkidEntryToUnverify := utxoView.GetPKIDForPublicKey(pubKey)
	if pkidEntryToUnverify == nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: PKID not found for username: %s", usernameToRemove))
		return
	}
	verifiedMapBytes, err := fes.GlobalStateGet(_GlobalStatePrefixForVerifiedMap)
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Failed fetching verified map from database."))
		return
	}
	verifiedMapStruct := VerifiedUsernameToPKID{}
	if verifiedMapBytes != nil {
		err = gob.NewDecoder(bytes.NewReader(verifiedMapBytes)).Decode(&verifiedMapStruct)
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Failed decoding verified map from database."))
			return
		}
	} else {
		res := AdminRemoveVerificationBadgeResponse{
			Message: "Couldn't find a verified username map in global state.  Nothing to delete.",
		}
		if err := json.NewEncoder(ww).Encode(res); err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Problem encoding response as "+
				"JSON: %v", err))
			return
		}
		return
	}
	err = fes.UpdateUsernameVerificationAuditLog(usernameToRemove, pkidEntryToUnverify, true, requestData.AdminPublicKey, utxoView)
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: error updating audit log of username verification: %v", err))
		return
	}
	delete(verifiedMapStruct.VerifiedUsernameToPKID, strings.ToLower(usernameToRemove))
	metadataDataBuf := bytes.NewBuffer([]byte{})
	gob.NewEncoder(metadataDataBuf).Encode(verifiedMapStruct)
	err = fes.GlobalStatePut(_GlobalStatePrefixForVerifiedMap, metadataDataBuf.Bytes())
	if err != nil {
		_AddBadRequestError(ww, "AdminRemoveVerificationBadge: Failed placing new verification map into the database.")
		return
	}
	res := AdminRemoveVerificationBadgeResponse{
		Message: "Successfully removed verification badge for: " + usernameToRemove,
	}
	if err := json.NewEncoder(ww).Encode(res); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminRemoveVerificationBadge: Problem encoding response as JSON: %v", err))
		return
	}
}
AdminRemoveVerificationBadge

A valid verification mapping will have an element where map[PKID] = username.
If the public key still has the same username, the user is considered verified.
In order to "delete" a user efficiently, we simply map their public key to an empty string.
Since their public key can never have an underlying username of "", it will never show up as verified.
package routes
import (
	"bytes"
	"encoding/gob"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/btcsuite/btcd/btcec"
	"github.com/deso-protocol/core/lib"
	"github.com/pkg/errors"
	"io"
	"net/http"
	"reflect"
	"strings"
	"time"
)
type AdminUpdateUserGlobalMetadataRequest struct {
	UserPublicKeyBase58Check string `safeForLogging:"true"`
	Username string `safeForLogging:"true"`
	IsBlacklistUpdate bool `safeForLogging:"true"`
	RemoveEverywhere bool `safeForLogging:"true"`
	RemoveFromLeaderboard bool `safeForLogging:"true"`
	IsWhitelistUpdate bool `safeForLogging:"true"`
	WhitelistPosts bool `safeForLogging:"true"`
	RemovePhoneNumberMetadata bool `safeForLogging:"true"`
	AdminPublicKey string
}
type AdminUpdateUserGlobalMetadataResponse struct{}
func (fes *APIServer) AdminUpdateUserGlobalMetadata(ww http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes))
	requestData := AdminUpdateUserGlobalMetadataRequest{}
	if err := decoder.Decode(&requestData); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem parsing request body: %v", err))
		return
	}
	if requestData.UserPublicKeyBase58Check == "" && requestData.Username == "" {
		_AddBadRequestError(ww,
			fmt.Sprintf("AdminUpdateUserGlobalMetadataRequest: Must provide a valid username or public key."))
		return
	}
	var userPublicKeyBytes []byte
	var err error
	if requestData.UserPublicKeyBase58Check != "" {
		userPublicKeyBytes, _, err = lib.Base58CheckDecode(requestData.UserPublicKeyBase58Check)
		if err != nil || len(userPublicKeyBytes) != btcec.PubKeyBytesLenCompressed {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem decoding updater public key %s: %v",
				requestData.UserPublicKeyBase58Check, err))
			return
		}
	}
	if userPublicKeyBytes == nil && requestData.Username != "" && requestData.Username[0] == '+' {
		phoneNumberMetadata, err := fes.getPhoneNumberMetadataFromGlobalState(requestData.Username)
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Error getting phone number metadata: %v", err))
			return
		}
		userPublicKeyBytes = phoneNumberMetadata.PublicKey
	}
	if userPublicKeyBytes == nil && requestData.Username != "" {
		utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView()
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem fetching utxoView: %v", err))
			return
		}
		profile := utxoView.GetProfileEntryForUsername([]byte(requestData.Username))
		if profile == nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem getting profile for username: %v : %s", err, requestData.Username))
			return
		}
		userPublicKeyBytes = profile.PublicKey
	}
	userMetadata, err := fes.getUserMetadataFromGlobalState(lib.PkToString(userPublicKeyBytes, fes.Params))
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem getting metadata from global state: %v", err))
		return
	}
	if requestData.RemovePhoneNumberMetadata {
		if len(userMetadata.PhoneNumber) == 0 {
			_AddBadRequestError(ww, "AdminUpdateUserGlobalMetadata: User does not have a phone number")
			return
		}
		phoneNumberMetadata, err := fes.getPhoneNumberMetadataFromGlobalState(userMetadata.PhoneNumber)
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Error getting phone number metadata: %v", err))
			return
		}
		phoneNumberMetadata.PublicKey = nil
		err = fes.putPhoneNumberMetadataInGlobalState(phoneNumberMetadata)
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Error saving phone number metadata: %v", err))
			return
		}
		res := AdminUpdateUserGlobalMetadataResponse{}
		if err := json.NewEncoder(ww).Encode(res); err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem encoding response as JSON: %v", err))
			return
		}
		return
	}
	utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView()
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem getting utxoView: %v", err))
		return
	}
	userPKIDEntry := utxoView.GetPKIDForPublicKey(userPublicKeyBytes)
	profileEntry := utxoView.GetProfileEntryForPKID(userPKIDEntry.PKID)
	if requestData.IsBlacklistUpdate {
		userMetadata.RemoveEverywhere = requestData.RemoveEverywhere
		blacklistKey := GlobalStateKeyForBlacklistedProfile(userPublicKeyBytes)
		if userMetadata.RemoveEverywhere {
			err = fes.GlobalStatePut(blacklistKey, lib.IsBlacklisted)
			if err != nil {
				_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem updating blacklist: %v", err))
			}
		} else {
			err = fes.GlobalStateDelete(blacklistKey)
			if err != nil {
				_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem deleting from blacklist: %v", err))
				return
			}
		}
		err = fes.UpdateFilterAuditLogs(string(profileEntry.Username), userPKIDEntry, Blacklist, !userMetadata.RemoveEverywhere, requestData.AdminPublicKey, utxoView)
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem updating blacklist logs: %v", err))
			return
		}
		userMetadata.RemoveFromLeaderboard = requestData.RemoveFromLeaderboard
		graylistkey := GlobalStateKeyForGraylistedProfile(userPublicKeyBytes)
		if userMetadata.RemoveFromLeaderboard {
			err = fes.GlobalStatePut(graylistkey, lib.IsGraylisted)
			if err != nil {
				_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem updating graylist: %v", err))
				return
			}
		} else {
			err = fes.GlobalStateDelete(graylistkey)
			if err != nil {
				_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem deleting from graylist: %v", err))
				return
			}
		}
		err = fes.UpdateFilterAuditLogs(string(profileEntry.Username), userPKIDEntry, Graylist, !userMetadata.RemoveFromLeaderboard, requestData.AdminPublicKey, utxoView)
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem updating graylist logs: %v", err))
			return
		}
	} else if requestData.IsWhitelistUpdate {
		userMetadata.WhitelistPosts = requestData.WhitelistPosts
		err = fes.UpdateFilterAuditLogs(string(profileEntry.Username), userPKIDEntry, Whitelist, !requestData.WhitelistPosts, requestData.AdminPublicKey, utxoView)
		if err != nil {
			_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem updating whitelist logs: %v", err))
			return
		}
	}
	err = fes.putUserMetadataInGlobalState(userMetadata)
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem putting updated user metadata: %v", err))
		return
	}
	res := AdminUpdateUserGlobalMetadataResponse{}
	if err := json.NewEncoder(ww).Encode(res); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminUpdateUserGlobalMetadata: Problem encoding response as JSON: %v", err))
		return
	}
}
type AdminGetAllUserGlobalMetadataRequest struct {
	NumToFetch int `safeForLogging:"true"`
}
type AdminGetAllUserGlobalMetadataResponse struct {
	PubKeyToUserGlobalMetadata map[string]*UserMetadata
	PubKeyToUsername           map[string]string
}
func (fes *APIServer) getUserMetadataUsernameMaps(numToFetch int) (_publicKeyToUserMetadata map[string]*UserMetadata,
	_publicKeyToUsername map[string]string, _err error) {
	seekKey := _GlobalStatePrefixPublicKeyToUserMetadata
	keys, vals, err := fes.GlobalStateSeek(seekKey, seekKey, 0, numToFetch, false, true)
	if err != nil {
		return nil, nil,
			errors.Wrapf(err, "getUserMetadataUsernameMaps: problem with GlobalStateSeek")
	}
	if len(keys) != len(vals) {
		return nil, nil,
			errors.Wrapf(err, "getUserMetadataUsernameMaps: GlobalState keys/vals length mismatch.")
	}
	utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView()
	if err != nil {
		return nil, nil,
			errors.Wrapf(err, "getUserMetadataUsernameMaps: problem with GetAugmentedUniversalView")
	}
	publicKeyToUserMetadata := make(map[string]*UserMetadata)
	publicKeyToUsername := make(map[string]string)
	for ii, dbKeyBytes := range keys {
		pkBytes := make([]byte, btcec.PubKeyBytesLenCompressed)
		copy(pkBytes[:], dbKeyBytes[1 : 1+btcec.PubKeyBytesLenCompressed][:])
		pubKeyString := lib.PkToString(pkBytes, fes.Params)
		userMetadata := UserMetadata{}
		err = gob.NewDecoder(bytes.NewReader(vals[ii])).Decode(&userMetadata)
		if err != nil {
			return nil, nil,
				errors.Wrapf(err, "getUserMetadataUsernameMaps: problem getting metadata from global state")
		}
		publicKeyToUserMetadata[pubKeyString] = &userMetadata
		profileEntry := utxoView.GetProfileEntryForPublicKey(pkBytes)
		if profileEntry != nil {
			publicKeyToUsername[pubKeyString] = string(profileEntry.Username)
		}
	}
	return publicKeyToUserMetadata, publicKeyToUsername, nil
}
func (fes *APIServer) AdminGetAllUserGlobalMetadata(ww http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes))
	requestData := AdminGetAllUserGlobalMetadataRequest{}
	if err := decoder.Decode(&requestData); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGetAllUserGlobalMetadata: Problem parsing request body: %v", err))
		return
	}
	publicKeyToUserMetadata, publicKeyToUsername, err := fes.getUserMetadataUsernameMaps(requestData.NumToFetch)
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGetAllUserGlobalMetadata: Problem with getUserMetadataUsernameMaps: %v", err))
		return
	}
	res := AdminGetAllUserGlobalMetadataResponse{
		PubKeyToUserGlobalMetadata: publicKeyToUserMetadata,
		PubKeyToUsername:           publicKeyToUsername,
	}
	if err = json.NewEncoder(ww).Encode(res); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGetAllUserGlobalMetadata: Problem encoding response as JSON: %v", err))
		return
	}
}
type AdminGetUserGlobalMetadataRequest struct {
	UserPublicKeyBase58Check string `safeForLogging:"true"`
}
type AdminGetUserGlobalMetadataResponse struct {
	UserMetadata UserMetadata
	UserProfileEntryResponse *ProfileEntryResponse
}
func (fes *APIServer) AdminGetUserGlobalMetadata(ww http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes))
	requestData := AdminGetUserGlobalMetadataRequest{}
	if err := decoder.Decode(&requestData); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGetAllUserGlobalMetadata: Problem parsing request body: %v", err))
		return
	}
	userPublicKeyBytes, _, err := lib.Base58CheckDecode(requestData.UserPublicKeyBase58Check)
	if err != nil || len(userPublicKeyBytes) != btcec.PubKeyBytesLenCompressed {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGetUserGlobalMetadata: Problem userPublicKeyBase58Check: %v", err))
		return
	}
	userMetadata, err := fes.getUserMetadataFromGlobalState(lib.PkToString(userPublicKeyBytes, fes.Params))
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGetUserGlobalMetadata: Problem obtaining userMetadata from global state: %v", err))
	}
	utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView()
	if err != nil {
		_AddInternalServerError(ww, fmt.Sprintf("AdminGetUserGlobalMetadata: problem with GetAugmentedUniversalView: %v", err))
		return
	}
	profileEntry := utxoView.GetProfileEntryForPublicKey(userPublicKeyBytes)
	res := AdminGetUserGlobalMetadataResponse{
		UserMetadata:             *userMetadata,
		UserProfileEntryResponse: _profileEntryToResponse(profileEntry, fes.Params, nil, utxoView),
	}
	if err = json.NewEncoder(ww).Encode(res); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGetUserGlobalMetadata: Problem encoding response as JSON: %v", err))
		return
	}
}
func (fes *APIServer) UpdateUsernameVerificationAuditLog(usernameToVerify string, pkidEntryToVerify *lib.PKIDEntry,
	isRemoval bool, verifierPublicKeyBase58Check string, utxoView *lib.UtxoView) (_err error) {
	verificationAuditLogs := []VerificationUsernameAuditLog{}
	verificationAuditLogKey := GlobalStateKeyForUsernameVerificationAuditLogs(usernameToVerify)
	verificationAuditLogBytes, err := fes.GlobalStateGet(verificationAuditLogKey)
	if err != nil {
		return errors.Wrap(fmt.Errorf("UpdateUsernameVerificationAuditLog: Failed to log verification to audit log"), "")
	}
	if verificationAuditLogBytes != nil {
		err = gob.NewDecoder(bytes.NewReader(verificationAuditLogBytes)).Decode(&verificationAuditLogs)
		if err != nil {
			return errors.Wrap(fmt.Errorf("UpdateUsernameVerificationAuditLog: Failed decoding verification audit log"), "")
		}
	}
	verifierPublicKeyBytes, _, err := lib.Base58CheckDecode(verifierPublicKeyBase58Check)
	if err != nil || len(verifierPublicKeyBytes) != btcec.PubKeyBytesLenCompressed {
		return errors.Wrap(fmt.Errorf("UpdateUsernameVerificationAuditLog: Failed to decode verifier public key bytes"), "")
	}
	verifierPKID := utxoView.GetPKIDForPublicKey(verifierPublicKeyBytes)
	verifierProfileEntry := utxoView.GetProfileEntryForPKID(verifierPKID.PKID)
	verifierUsername := ""
	if verifierProfileEntry != nil {
		verifierUsername = string(verifierProfileEntry.Username)
	}
	tstamp := uint64(time.Now().UnixNano())
	newVerificationAuditLog := VerificationUsernameAuditLog{
		TimestampNanos:   tstamp,
		VerifierUsername: verifierUsername,
		VerifierPKID:     verifierPKID.PKID,
		VerifiedUsername: usernameToVerify,
		VerifiedPKID:     pkidEntryToVerify.PKID,
		IsRemoval:        isRemoval,
	}
	verificationAuditLogs = append([]VerificationUsernameAuditLog{newVerificationAuditLog}, verificationAuditLogs...)
	verificationDataBuf := bytes.NewBuffer([]byte{})
	gob.NewEncoder(verificationDataBuf).Encode(verificationAuditLogs)
	err = fes.GlobalStatePut(verificationAuditLogKey, verificationDataBuf.Bytes())
	if err != nil {
		return errors.Wrap(fmt.Errorf("AdminGrantVerificationBadge: Failed to update verification audit logs"), "")
	}
	return nil
}
func (fes *APIServer) UpdateFilterAuditLogs(usernameToUpdate string, pkidEntryToUpdate *lib.PKIDEntry, filterType FilterType,
	isRemoval bool, updaterPublicKeyBase58Check string, utxoView *lib.UtxoView) (_err error) {
	filterLogs, err := fes.GetFilterAuditLogs(usernameToUpdate, filterType)
	if err != nil {
		return errors.Wrap(err, "UpdateFilterAuditLogs: Failed to call GetFilterAuditLogs")
	}
	updaterPublicKeyBytes, _, err := lib.Base58CheckDecode(updaterPublicKeyBase58Check)
	if err != nil || len(updaterPublicKeyBytes) != btcec.PubKeyBytesLenCompressed {
		return errors.Wrap(fmt.Errorf("UpdateFilterAuditLogs: Failed to decode verifier public key bytes"), "")
	}
	updaterPKID := utxoView.GetPKIDForPublicKey(updaterPublicKeyBytes)
	updaterProfileEntry := utxoView.GetProfileEntryForPKID(updaterPKID.PKID)
	updaterUsername := ""
	if updaterProfileEntry != nil {
		updaterUsername = string(updaterProfileEntry.Username)
	}
	tstamp := uint64(time.Now().UnixNano())
	newFilterLog := FilterAuditLog{
		TimestampNanos:  tstamp,
		Filter:          filterType,
		UpdaterUsername: updaterUsername,
		UpdaterPKID:     updaterPKID.PKID,
		UpdatedUsername: usernameToUpdate,
		UpdatedPKID:     pkidEntryToUpdate.PKID,
		IsRemoval:       isRemoval,
	}
	filterLogs = append([]FilterAuditLog{newFilterLog}, filterLogs...)
	filterLogsBuf := bytes.NewBuffer([]byte{})
	err = gob.NewEncoder(filterLogsBuf).Encode(filterLogs)
	if err != nil {
		return errors.Wrap(err, "UpdateFilterAuditLogs: Failed to gob encode filter logs")
	}
	filterLogsKey, err := GetFilterLogsKey(usernameToUpdate, filterType)
	if err != nil {
		return errors.Wrap(err, "UpdateFilterAuditLogs: Failed to get filter logs")
	}
	err = fes.GlobalStatePut(filterLogsKey, filterLogsBuf.Bytes())
	if err != nil {
		return errors.Wrap(fmt.Errorf("UpdateFilterAuditLogs: Failed to update filter logs"), "")
	}
	return nil
}
func GetFilterLogsKey(username string, filterType FilterType) (_filterLogsKey []byte, _err error) {
	var filterLogsKey []byte
	switch filterType {
	case Blacklist:
		filterLogsKey = GlobalStateKeyForBlacklistAuditLogs(username)
	case Graylist:
		filterLogsKey = GlobalStateKeyForGraylistAuditLogs(username)
	case Whitelist:
		filterLogsKey = GlobalStateKeyForWhitelistAuditLogs(username)
	default:
		return nil, fmt.Errorf("GetFilterLogsKey: Invalid filter type: %v", filterType)
	}
	return filterLogsKey, nil
}
func (fes *APIServer) GetFilterAuditLogs(username string, filterType FilterType) (_logs []FilterAuditLog, _err error) {
	filterLogs := []FilterAuditLog{}
	filterLogsKey, err := GetFilterLogsKey(username, filterType)
	if err != nil {
		return nil, errors.Wrap(err, "GetFilterAuditLogs: Failed to get filter logs")
	}
	filterLogsBytes, err := fes.GlobalStateGet(filterLogsKey)
	if err != nil {
		return nil, errors.Wrap(fmt.Errorf("GetFilterAuditLogs: Failed to fetch filter audit logs from globalstate"), "")
	}
	if filterLogsBytes != nil {
		err = gob.NewDecoder(bytes.NewReader(filterLogsBytes)).Decode(&filterLogs)
		if err != nil {
			return nil, errors.Wrap(fmt.Errorf("GetFilterAuditLogs: Failed decoding filter audit logs"), "")
		}
	}
	return filterLogs, nil
}
type VerifiedUsernameToPKID struct {
	VerifiedUsernameToPKID map[string]*lib.PKID
}
type VerificationUsernameAuditLog struct {
	TimestampNanos uint64
	VerifierUsername string
	VerifierPKID     *lib.PKID
	VerifiedUsername string
	VerifiedPKID     *lib.PKID
	IsRemoval bool
}
type FilterType uint32
const (
	Whitelist FilterType = iota
	Graylist
	Blacklist
)
type FilterAuditLog struct {
	TimestampNanos uint64
	Filter FilterType
	UpdaterUsername string
	UpdaterPKID     *lib.PKID
	UpdatedUsername string
	UpdatedPKID     *lib.PKID
	IsRemoval bool
}
type AdminGrantVerificationBadgeRequest struct {
	UsernameToVerify string `safeForLogging:"true"`
	AdminPublicKey   string
}
type AdminGrantVerificationBadgeResponse struct {
	Message string
}
func (fes *APIServer) AdminGrantVerificationBadge(ww http.ResponseWriter, req *http.Request) {
	requestData := AdminGrantVerificationBadgeRequest{}
	decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes))
	if err := decoder.Decode(&requestData); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGrantVerificationBadge: Problem parsing request body: %v", err))
		return
	}
	usernameToVerify := requestData.UsernameToVerify
	if len(usernameToVerify) == 0 || len(usernameToVerify) > lib.MaxUsernameLengthBytes || !lib.UsernameRegex.Match([]byte(usernameToVerify)) {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGrantVerificationBadge: Must provide a valid username"))
		return
	}
	pubKey, err := fes.getPublicKeyFromUsernameOrPublicKeyString(usernameToVerify)
	if err != nil {
		_AddBadRequestError(ww,
			fmt.Sprintf("AdminGrantVerificationBadge: Username %s has no associated underlying publickey.", usernameToVerify))
		return
	}
	utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView()
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGrantVerificationBadge: Problem getting utxoView: %v", err))
		return
	}
	pkidEntryToVerify := utxoView.GetPKIDForPublicKey(pubKey)
	if pkidEntryToVerify == nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGrantVerificationBadge: PKID not found for username: %s", usernameToVerify))
		return
	}
	verifiedMap, err := fes.GetVerifiedUsernameToPKIDMap()
	if err != nil {
		_AddInternalServerError(ww, fmt.Sprintf("AdminGrantVerificationBadge: Failed fetching verified map from database: %v", err))
		return
	}
	verifiedMapStruct := VerifiedUsernameToPKID{}
	if verifiedMap != nil {
		verifiedMapStruct.VerifiedUsernameToPKID = verifiedMap
	} else {
		verifiedMapStruct.VerifiedUsernameToPKID = make(map[string]*lib.PKID)
	}
	err = fes.UpdateUsernameVerificationAuditLog(usernameToVerify, pkidEntryToVerify, false, requestData.AdminPublicKey, utxoView)
	if err != nil {
		_AddBadRequestError(ww, fmt.Sprintf("AdminGrantVerificationBadge: error updating audit log of username verification: %v", err))
		return
	}
	verifiedMapStruct.VerifiedUsernameToPKID[strings.ToLower(usernameToVerify)] = pkidEntryToVerify.PKID
	metadataDataBuf := bytes.NewBuffer([]byte{})
	gob.NewEncoder(metadataDataBuf).Encode(verifiedMapStruct)
	err = fes.GlobalStatePut(_GlobalStatePrefixForVerifiedMap, metadataDataBuf.Bytes())
	if err != nil {
		_AddBadRequestError(ww, "AdminGrantVerificationBadge: Failed placing new verification map into the database.")
		return
	}
	res := AdminGrantVerificationBadgeResponse{
		Message: "Successfully added verification badge for: " + usernameToVerify,
	}
	if err = json.NewEncoder(ww).Encode(res); err != nil {
		_AddBadRequestError(ww, fmt.Sprintf(
			"AdminGrantVerificationBadge: Problem encoding response as JSON: %v", err))
		return
	}
}
type AdminRemoveVerificationBadgeRequest struct {
	UsernameForWhomToRemoveVerification string `safeForLogging:"true"`
	AdminPublicKey                      string
}
type AdminRemoveVerificationBadgeResponse struct {
	Message string
}