diff --git a/precompiles/assets/tx.go b/precompiles/assets/tx.go index ac70d2c3d..0ea1a3994 100644 --- a/precompiles/assets/tx.go +++ b/precompiles/assets/tx.go @@ -143,7 +143,7 @@ func (p Precompile) RegisterToken( } stakingAsset := &assetstypes.StakingAssetInfo{ - AssetBasicInfo: &asset, + AssetBasicInfo: asset, StakingTotalAmount: sdkmath.NewInt(0), } diff --git a/proto/exocore/operator/v1/genesis.proto b/proto/exocore/operator/v1/genesis.proto index c307c3763..1a304efe3 100644 --- a/proto/exocore/operator/v1/genesis.proto +++ b/proto/exocore/operator/v1/genesis.proto @@ -100,7 +100,7 @@ message OperatorSlashState { // it's corresponding to the kvStore `BytePrefixForOperatorAndChainIDToPrevConsKey` message PrevConsKey { // key is used for storing the previous consensus key, - // which is the combination of keystore prefix,chainID, and operator address. + // which is the combination of chainID and operator address. string key = 1; // consensus_key is the consensus key of the operator on the chain. // the length of this key should be exactly 32 bytes, and must be enforced @@ -112,7 +112,7 @@ message PrevConsKey { // is in the process of unbonding their key for the given chainID. // it's corresponding to the kvStore `BytePrefixForOperatorKeyRemovalForChainID` message OperatorKeyRemoval { - // key is the combination of keystore prefix, operator address, and chainID. + // key is the combination of operator address and chainID. string key = 1; } diff --git a/x/assets/keeper/genesis.go b/x/assets/keeper/genesis.go index 22b5265e6..d1dcb536c 100644 --- a/x/assets/keeper/genesis.go +++ b/x/assets/keeper/genesis.go @@ -1,6 +1,7 @@ package keeper import ( + errorsmod "cosmossdk.io/errors" "github.com/ExocoreNetwork/exocore/x/assets/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -15,14 +16,14 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) { for i := range data.ClientChains { info := data.ClientChains[i] if err := k.SetClientChainInfo(ctx, &info); err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set client chain info")) } } // client_chain_asset.go for i := range data.Tokens { info := data.Tokens[i] if err := k.SetStakingAssetInfo(ctx, &info); err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set staking asset info")) } } // staker_asset.go (deposits) @@ -40,7 +41,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) { if err := k.UpdateStakerAssetState( ctx, stakerID, assetID, infoAsChange, ); err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set deposit info")) } } } @@ -52,7 +53,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) { infoAsChange := types.DeltaOperatorSingleAsset(assetInfo.Info) err := k.UpdateOperatorAssetState(ctx, accAddress, assetInfo.AssetID, infoAsChange) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set operator asset info")) } } } @@ -63,31 +64,31 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { res := types.GenesisState{} params, err := k.GetParams(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get parameter").Error()) } res.Params = *params allClientChains, err := k.GetAllClientChainInfo(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all client chains").Error()) } res.ClientChains = allClientChains allAssets, err := k.GetAllStakingAssetsInfo(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all staking assets info").Error()) } res.Tokens = allAssets allDeposits, err := k.AllDeposits(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all deposits").Error()) } res.Deposits = allDeposits operatorAssets, err := k.AllOperatorAssets(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all assets info for the operators").Error()) } res.OperatorAssets = operatorAssets return &res diff --git a/x/delegation/keeper/genesis.go b/x/delegation/keeper/genesis.go index a6bde1de8..fd459e227 100644 --- a/x/delegation/keeper/genesis.go +++ b/x/delegation/keeper/genesis.go @@ -35,15 +35,15 @@ func (k Keeper) InitGenesis( // init the state from the general exporting genesis file err := k.SetAllDelegationStates(ctx, gs.DelegationStates) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all delegation states")) } err = k.SetAllStakerList(ctx, gs.StakersByOperator) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all staker list")) } err = k.SetUndelegationRecords(ctx, gs.Undelegations) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all undelegation records")) } return []abci.ValidatorUpdate{} } @@ -53,25 +53,25 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *delegationtype.GenesisState { res := delegationtype.GenesisState{} associations, err := k.GetAllAssociations(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all associations").Error()) } res.Associations = associations delegationStates, err := k.AllDelegationStates(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all delegation states").Error()) } res.DelegationStates = delegationStates stakerList, err := k.AllStakerList(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all staker list").Error()) } res.StakersByOperator = stakerList undelegations, err := k.AllUndelegations(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all undelegations").Error()) } res.Undelegations = undelegations return &res diff --git a/x/delegation/types/genesis.go b/x/delegation/types/genesis.go index d6adbbcf6..8f91a27e2 100644 --- a/x/delegation/types/genesis.go +++ b/x/delegation/types/genesis.go @@ -35,26 +35,26 @@ func ValidateIDAndOperator(stakerID, assetID, operator string) error { // validate the operator address if _, err := sdk.AccAddressFromBech32(operator); err != nil { return xerrors.Errorf( - "invalid operator address for operator %s", operator, + "ValidateIDAndOperator: invalid operator address for operator %s", operator, ) } _, stakerClientChainID, err := assetstypes.ValidateID(stakerID, true, false) if err != nil { return xerrors.Errorf( - "invalid stakerID: %s", + "ValidateIDAndOperator: invalid stakerID: %s", stakerID, ) } _, assetClientChainID, err := assetstypes.ValidateID(assetID, true, false) if err != nil { return xerrors.Errorf( - "invalid assetID: %s", + "ValidateIDAndOperator: invalid assetID: %s", assetID, ) } if stakerClientChainID != assetClientChainID { return xerrors.Errorf( - "the client chain layerZero IDs of the staker and asset are different, stakerID:%s, assetID:%s", + "ValidateIDAndOperator: the client chain layerZero IDs of the staker and asset are different, stakerID:%s, assetID:%s", stakerID, assetID) } return nil diff --git a/x/operator/keeper/consensus_keys.go b/x/operator/keeper/consensus_keys.go index 8e5d79beb..203d823e7 100644 --- a/x/operator/keeper/consensus_keys.go +++ b/x/operator/keeper/consensus_keys.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" "github.com/cosmos/cosmos-sdk/store/prefix" "github.com/ethereum/go-ethereum/common/hexutil" @@ -446,28 +447,38 @@ func (k *Keeper) SetAllPrevConsKeys(ctx sdk.Context, prevConsKeys []types.PrevCo store := ctx.KVStore(k.storeKey) for i := range prevConsKeys { prevKey := prevConsKeys[i] - keyBytes, err := hexutil.Decode(prevKey.Key) + keys, err := assetstypes.ParseJoinedStoreKey([]byte(prevKey.Key), 2) if err != nil { - return nil + return err + } + chainID := keys[0] + opAccAddr, err := sdk.AccAddressFromBech32(keys[1]) + if err != nil { + return err } wrappedKey := types.NewWrappedConsKeyFromHex(prevKey.ConsensusKey) bz := k.cdc.MustMarshal(wrappedKey.ToTmProtoKey()) - store.Set(keyBytes, bz) + + store.Set(types.KeyForChainIDAndOperatorToPrevConsKey(chainID, opAccAddr), bz) } return nil } func (k *Keeper) GetAllPrevConsKeys(ctx sdk.Context) ([]types.PrevConsKey, error) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte{types.BytePrefixForOperatorAndChainIDToPrevConsKey}) + store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte{types.BytePrefixForOperatorAndChainIDToPrevConsKey}) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) defer iterator.Close() ret := make([]types.PrevConsKey, 0) for ; iterator.Valid(); iterator.Next() { var consKey tmprotocrypto.PublicKey k.cdc.MustUnmarshal(iterator.Value(), &consKey) + chainID, operatorAddr, err := types.ParsePrevConsKey(iterator.Key()) + if err != nil { + return nil, err + } ret = append(ret, types.PrevConsKey{ - Key: hexutil.Encode(iterator.Key()), + Key: string(assetstypes.GetJoinedStoreKey(chainID, operatorAddr.String())), ConsensusKey: hexutil.Encode(consKey.GetEd25519()), }) } @@ -478,24 +489,34 @@ func (k *Keeper) SetAllOperatorKeyRemovals(ctx sdk.Context, operatorKeyRemoval [ store := ctx.KVStore(k.storeKey) for i := range operatorKeyRemoval { keyRemoval := operatorKeyRemoval[i] - keyBytes, err := hexutil.Decode(keyRemoval.Key) + keys, err := assetstypes.ParseJoinedStoreKey([]byte(keyRemoval.Key), 2) if err != nil { - return nil + return err + } + chainID := keys[1] + opAccAddr, err := sdk.AccAddressFromBech32(keys[0]) + if err != nil { + return err } - store.Set(keyBytes, []byte{}) + store.Set(types.KeyForOperatorKeyRemovalForChainID(opAccAddr, chainID), []byte{}) } return nil } func (k *Keeper) GetAllOperatorKeyRemovals(ctx sdk.Context) ([]types.OperatorKeyRemoval, error) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte{types.BytePrefixForOperatorKeyRemovalForChainID}) + store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte{types.BytePrefixForOperatorKeyRemovalForChainID}) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) defer iterator.Close() ret := make([]types.OperatorKeyRemoval, 0) for ; iterator.Valid(); iterator.Next() { + operatorAddr, chainID, err := types.ParseKeyForOperatorKeyRemoval(iterator.Key()) + if err != nil { + return nil, err + } + ret = append(ret, types.OperatorKeyRemoval{ - Key: hexutil.Encode(iterator.Key()), + Key: string(assetstypes.GetJoinedStoreKey(operatorAddr.String(), chainID)), }) } return ret, nil diff --git a/x/operator/keeper/genesis.go b/x/operator/keeper/genesis.go index 659eead8d..d04829712 100644 --- a/x/operator/keeper/genesis.go +++ b/x/operator/keeper/genesis.go @@ -1,6 +1,7 @@ package keeper import ( + errorsmod "cosmossdk.io/errors" "github.com/ExocoreNetwork/exocore/x/operator/types" abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,7 +14,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) []abci.Va op.OperatorInfo.EarningsAddr = op.OperatorAddress } if err := k.SetOperatorInfo(ctx, op.OperatorAddress, &op.OperatorInfo); err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set operator info")) } } for _, record := range state.OperatorRecords { @@ -29,27 +30,27 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) []abci.Va // init the state from the general exporting genesis file err := k.SetAllOptedInfo(ctx, state.OptStates) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all opted info")) } err = k.SetAllOperatorUSDValues(ctx, state.OperatorUSDValues) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all operator USD values")) } err = k.SetAllAVSUSDValues(ctx, state.AVSUSDValues) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all AVS USD values")) } err = k.SetAllSlashInfo(ctx, state.SlashStates) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all slash info")) } err = k.SetAllPrevConsKeys(ctx, state.PreConsKeys) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all previous consensus keys")) } err = k.SetAllOperatorKeyRemovals(ctx, state.OperatorKeyRemovals) if err != nil { - panic(err) + panic(errorsmod.Wrap(err, "failed to set all key removals for operators")) } return []abci.ValidatorUpdate{} } @@ -60,43 +61,43 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { operatorRecords, err := k.GetAllOperatorConsKeyRecords(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all consensus keys for operators").Error()) } res.OperatorRecords = operatorRecords optedInfos, err := k.GetAllOptedInfo(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all opted info").Error()) } res.OptStates = optedInfos allAVSUSDValues, err := k.GetAllAVSUSDValues(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all AVS USD values").Error()) } res.AVSUSDValues = allAVSUSDValues allOperatorUSDValues, err := k.GetAllOperatorUSDValues(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all operator USD values").Error()) } res.OperatorUSDValues = allOperatorUSDValues slashingInfos, err := k.GetAllSlashInfo(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to set all slashing info").Error()) } res.SlashStates = slashingInfos prevConsKeys, err := k.GetAllPrevConsKeys(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all previous consensus keys").Error()) } res.PreConsKeys = prevConsKeys operatorKeyRemovals, err := k.GetAllOperatorKeyRemovals(ctx) if err != nil { - panic(err) + ctx.Logger().Error(errorsmod.Wrap(err, "failed to get all key removals for operators").Error()) } res.OperatorKeyRemovals = operatorKeyRemovals diff --git a/x/operator/keeper/operator.go b/x/operator/keeper/operator.go index 6d3c22fd5..a8e747c94 100644 --- a/x/operator/keeper/operator.go +++ b/x/operator/keeper/operator.go @@ -22,7 +22,10 @@ func (k *Keeper) SetOperatorInfo( ctx sdk.Context, addr string, info *operatortypes.OperatorInfo, ) (err error) { // #nosec G703 // already validated in `ValidateBasic` - opAccAddr, _ := sdk.AccAddressFromBech32(addr) + opAccAddr, err := sdk.AccAddressFromBech32(addr) + if err != nil { + return errorsmod.Wrap(err, "SetOperatorInfo: error occurred when parse acc address from Bech32") + } // if already registered, this request should go to EditOperator. if k.IsOperator(ctx, opAccAddr) { return errorsmod.Wrap( diff --git a/x/operator/keeper/slash.go b/x/operator/keeper/slash.go index 3cbae5fa2..cf3cf9d0f 100644 --- a/x/operator/keeper/slash.go +++ b/x/operator/keeper/slash.go @@ -43,7 +43,7 @@ func SlashFromUndelegation(undelegation *delegationtype.UndelegationRecord, slas func (k *Keeper) CheckSlashParameter(ctx sdk.Context, parameter *types.SlashInputInfo) error { if parameter.SlashProportion.IsNil() || parameter.SlashProportion.IsNegative() { - return errorsmod.Wrapf(types.ErrValueIsNilOrZero, "SlashProportion: %+v", parameter.SlashProportion) + return errorsmod.Wrapf(types.ErrValueIsNilOrZero, "Invalid SlashProportion; expected non-nil and non-negative, got: %+v", parameter.SlashProportion) } height := ctx.BlockHeight() if parameter.SlashEventHeight > height { diff --git a/x/operator/types/genesis.go b/x/operator/types/genesis.go index d55911a17..d9d961709 100644 --- a/x/operator/types/genesis.go +++ b/x/operator/types/genesis.go @@ -6,7 +6,6 @@ import ( assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" ) func NewGenesisState( @@ -430,24 +429,17 @@ func (gs GenesisState) ValidateSlashStates(operators, avs map[string]struct{}) e func (gs GenesisState) ValidatePrevConsKeys(operators map[string]struct{}) error { validationFunc := func(_ int, prevConsKey PrevConsKey) error { - keyBytes, err := hexutil.Decode(prevConsKey.Key) + keys, err := assetstypes.ParseJoinedStoreKey([]byte(prevConsKey.Key), 2) if err != nil { return errorsmod.Wrapf( ErrInvalidGenesisData, - "ValidatePrevConsKeys can't decode the key with hexutil.Decode, %+v", - prevConsKey, - ) - } - _, operatorAddr, err := ParsePrevConsKey(keyBytes) - if err != nil { - return errorsmod.Wrapf( - ErrInvalidGenesisData, - "ValidatePrevConsKeys can't parse the key, %+v", + "ValidatePrevConsKeys can't parse the combined key, %+v", prevConsKey, ) } + operator := keys[1] // check that the operator is registered - if _, ok := operators[operatorAddr.String()]; !ok { + if _, ok := operators[operator]; !ok { return errorsmod.Wrapf( ErrInvalidGenesisData, "unknown operator address for the previous consensus key, %+v", @@ -477,24 +469,13 @@ func (gs GenesisState) ValidatePrevConsKeys(operators map[string]struct{}) error func (gs GenesisState) ValidateOperatorKeyRemovals(operators map[string]struct{}) error { validationFunc := func(_ int, operatorKeyRemoval OperatorKeyRemoval) error { - keyBytes, err := hexutil.Decode(operatorKeyRemoval.Key) + keys, err := assetstypes.ParseJoinedStoreKey([]byte(operatorKeyRemoval.Key), 2) if err != nil { - return errorsmod.Wrapf( - ErrInvalidGenesisData, - "ValidateOperatorKeyRemovals can't decode the key with hexutil.Decode, %+v", - operatorKeyRemoval, - ) - } - operatorAddr, _, err := ParseKeyForOperatorKeyRemoval(keyBytes) - if err != nil { - return errorsmod.Wrapf( - ErrInvalidGenesisData, - "ValidateOperatorKeyRemovals can't parse the key, %+v", - operatorKeyRemoval, - ) + return err } + operator := keys[0] // check that the operator is registered - if _, ok := operators[operatorAddr.String()]; !ok { + if _, ok := operators[operator]; !ok { return errorsmod.Wrapf( ErrInvalidGenesisData, "unknown operator address for the operator key removal, %+v", diff --git a/x/operator/types/keys.go b/x/operator/types/keys.go index f68bec3e1..ef5e96986 100644 --- a/x/operator/types/keys.go +++ b/x/operator/types/keys.go @@ -133,6 +133,9 @@ func KeyForOperatorAndChainIDToConsKey(addr sdk.AccAddress, chainID string) []by } func ParseKeyForOperatorAndChainIDToConsKey(key []byte) (addr sdk.AccAddress, chainID string, err error) { + if len(key) < AccAddressLength+8 { + return nil, "", xerrors.New("key length is too short to contain address and chainID length") + } // Extract the address addr = key[0:AccAddressLength] if len(addr) == 0 { @@ -160,29 +163,23 @@ func KeyForChainIDAndOperatorToPrevConsKey(chainID string, addr sdk.AccAddress) } func ParsePrevConsKey(key []byte) (chainID string, addr sdk.AccAddress, err error) { - // Check if the key has at least one byte for the prefix and one byte for the chainID length - if len(key) < 2 { - return "", nil, xerrors.New("key too short") - } - - // Extract and validate the prefix - prefix := key[0] - if prefix != BytePrefixForOperatorAndChainIDToPrevConsKey { - return "", nil, xerrors.Errorf("invalid prefix: expected %x, got %x", BytePrefixForOperatorAndChainIDToPrevConsKey, prefix) + // Check if the key has at least eight byte for the chainID length + if len(key) < 8 { + return "", nil, xerrors.New("key length is too short to contain chainID length") } // Extract the chainID length - chainIDLen := sdk.BigEndianToUint64(key[1:9]) - if len(key) < int(9+chainIDLen) { + chainIDLen := sdk.BigEndianToUint64(key[0:8]) + if len(key) < int(8+chainIDLen) { return "", nil, xerrors.New("key too short for chainID length") } // Extract the chainID - chainIDBytes := key[9 : 9+chainIDLen] + chainIDBytes := key[8 : 8+chainIDLen] chainID = string(chainIDBytes) // Extract the address - addr = key[9+chainIDLen:] + addr = key[8+chainIDLen:] if len(addr) == 0 { return "", nil, xerrors.New("missing address") } @@ -213,31 +210,25 @@ func KeyForOperatorKeyRemovalForChainID(addr sdk.AccAddress, chainID string) []b } func ParseKeyForOperatorKeyRemoval(key []byte) (addr sdk.AccAddress, chainID string, err error) { - // Check if the key has at least one byte for the prefix and one byte for the chainID length - if len(key) < 2 { - return nil, "", xerrors.New("key too short") - } - - // Extract and validate the prefix - prefix := key[0] - if prefix != BytePrefixForOperatorKeyRemovalForChainID { - return nil, "", xerrors.Errorf("invalid prefix: expected %x, got %x", BytePrefixForOperatorKeyRemovalForChainID, prefix) + // Check if the key has at least 20 byte for the operator and eight byte for the chainID length + if len(key) < AccAddressLength+8 { + return nil, "", xerrors.New("key length is too short to contain operator address and chainID length") } // Extract the address - addr = key[1 : AccAddressLength+1] + addr = key[0:AccAddressLength] if len(addr) == 0 { return nil, "", xerrors.New("missing address") } // Extract the chainID length - chainIDLen := sdk.BigEndianToUint64(key[AccAddressLength+1 : AccAddressLength+9]) - if len(key) != int(AccAddressLength+9+chainIDLen) { - return nil, "", xerrors.Errorf("invalid key length,expected:%d,got:%d", AccAddressLength+9+chainIDLen, len(key)) + chainIDLen := sdk.BigEndianToUint64(key[AccAddressLength : AccAddressLength+8]) + if len(key) != int(AccAddressLength+8+chainIDLen) { + return nil, "", xerrors.Errorf("invalid key length,expected:%d,got:%d", AccAddressLength+8+chainIDLen, len(key)) } // Extract the chainID - chainIDBytes := key[AccAddressLength+9 : AccAddressLength+9+chainIDLen] + chainIDBytes := key[AccAddressLength+8 : AccAddressLength+8+chainIDLen] chainID = string(chainIDBytes) return addr, chainID, nil