Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

imp(dymns): persist EIP-155 part only, for RollApp-related configs, to avoid migration when RollApp chain-id changed #1285

Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion proto/dymensionxyz/dymension/dymns/dym_name.proto
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ message DymNameConfig {
DymNameConfigType type = 1;

// chain_id is the chain-id of the Dym-Name configuration (equals to top-level-domain).
// If empty, the configuration is for host chain (Dymension Hub).
// There are 3 format types:
// - If empty, the configuration is for host chain (Dymension Hub).
// - If not empty and numeric only, then it is EIP-155 chain-id of RollApp.
// - Otherwise, it's external chains.
string chain_id = 2;

// path of the Dym-Name configuration (equals to Host in DNS).
Expand Down
86 changes: 63 additions & 23 deletions x/dymns/keeper/alias.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package keeper

import (
"fmt"
"slices"
"strconv"

rollapptypes "github.com/dymensionxyz/dymension/v3/x/rollapp/types"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -17,10 +21,17 @@ func (k Keeper) GetRollAppIdByAlias(ctx sdk.Context, alias string) (rollAppId st
}()

store := ctx.KVStore(k.storeKey)
key := dymnstypes.AliasToRollAppIdRvlKey(alias)
key := dymnstypes.AliasToRollAppEip155IdRvlKey(alias)
bz := store.Get(key)
if bz != nil {
rollAppId = string(bz)
rollAppEip155Id := string(bz)
eip155, _ := strconv.ParseUint(rollAppEip155Id, 10, 64)
var foundRollApp bool
rollAppId, foundRollApp = k.rollappKeeper.GetRollAppIdByEIP155(ctx, eip155)
if !foundRollApp {
// this should not happen as validated before
panic(fmt.Sprintf("rollapp not found by EIP155 of alias '%s': %s", alias, rollAppEip155Id))
}
}

return
Expand Down Expand Up @@ -59,23 +70,25 @@ func (k Keeper) SetAliasForRollAppId(ctx sdk.Context, rollAppId, alias string) e
}

store := ctx.KVStore(k.storeKey)
keyR2A := dymnstypes.RollAppIdToAliasesKey(rollAppId)
keyA2R := dymnstypes.AliasToRollAppIdRvlKey(alias)
keyRE155toA := dymnstypes.RollAppIdToAliasesKey(rollAppId)
keyAtoRE155 := dymnstypes.AliasToRollAppEip155IdRvlKey(alias)

// ensure the alias is not being used by another RollApp
if bz := store.Get(keyA2R); bz != nil {
return errorsmod.Wrapf(gerrc.ErrAlreadyExists, "alias currently being in used by: %s", string(bz))
if bz := store.Get(keyAtoRE155); bz != nil {
eip155, _ := strconv.ParseUint(string(bz), 10, 64)
usedByRollAppId, _ := k.rollappKeeper.GetRollAppIdByEIP155(ctx, eip155)
return errorsmod.Wrapf(gerrc.ErrAlreadyExists, "alias currently being in used by: %s", usedByRollAppId)
}

// one RollApp can have multiple aliases, append to the existing list
var multipleAliases dymnstypes.MultipleAliases
if bz := store.Get(keyR2A); bz != nil {
if bz := store.Get(keyRE155toA); bz != nil {
k.cdc.MustUnmarshal(bz, &multipleAliases)
}
multipleAliases.Aliases = append(multipleAliases.Aliases, alias)

store.Set(keyR2A, k.cdc.MustMarshal(&multipleAliases))
store.Set(keyA2R, []byte(rollAppId))
store.Set(keyRE155toA, k.cdc.MustMarshal(&multipleAliases))
store.Set(keyAtoRE155, []byte(dymnsutils.MustGetEIP155ChainIdFromRollAppId(rollAppId)))

return nil
}
Expand Down Expand Up @@ -136,20 +149,24 @@ func (k Keeper) RemoveAliasFromRollAppId(ctx sdk.Context, rollAppId, alias strin
}

store := ctx.KVStore(k.storeKey)
keyR2A := dymnstypes.RollAppIdToAliasesKey(rollAppId)
keyA2R := dymnstypes.AliasToRollAppIdRvlKey(alias)
keyRE155toA := dymnstypes.RollAppIdToAliasesKey(rollAppId)
keyAtoRE155 := dymnstypes.AliasToRollAppEip155IdRvlKey(alias)

// ensure the alias is being used by the RollApp
bzRollAppId := store.Get(keyA2R)
if bzRollAppId == nil {
bzRollAppEip155Id := store.Get(keyAtoRE155)
if bzRollAppEip155Id == nil {
return errorsmod.Wrapf(gerrc.ErrNotFound, "alias not found: %s", alias)
} else if string(bzRollAppId) != rollAppId {
return errorsmod.Wrapf(gerrc.ErrPermissionDenied, "alias currently being in used by: %s", string(bzRollAppId))
}

if string(bzRollAppEip155Id) != dymnsutils.MustGetEIP155ChainIdFromRollAppId(rollAppId) {
eip155, _ := strconv.ParseUint(string(bzRollAppEip155Id), 10, 64)
usedByRollAppId, _ := k.rollappKeeper.GetRollAppIdByEIP155(ctx, eip155)
return errorsmod.Wrapf(gerrc.ErrPermissionDenied, "alias currently being in used by: %s", usedByRollAppId)
}

// load the existing aliases of the RollApp
var multipleAliases dymnstypes.MultipleAliases
if bz := store.Get(keyR2A); bz != nil {
if bz := store.Get(keyRE155toA); bz != nil {
k.cdc.MustUnmarshal(bz, &multipleAliases)
}

Expand All @@ -166,13 +183,13 @@ func (k Keeper) RemoveAliasFromRollAppId(ctx sdk.Context, rollAppId, alias strin

// if no alias left, remove the key, otherwise update new list
if len(multipleAliases.Aliases) == 0 {
store.Delete(keyR2A)
store.Delete(keyRE155toA)
} else {
store.Set(keyR2A, k.cdc.MustMarshal(&multipleAliases))
store.Set(keyRE155toA, k.cdc.MustMarshal(&multipleAliases))
}

// remove the alias to RollAppId mapping
store.Delete(keyA2R)
store.Delete(keyAtoRE155)

return nil
}
Expand Down Expand Up @@ -235,6 +252,10 @@ func (k Keeper) IsAliasPresentsInParamsAsAliasOrChainId(ctx sdk.Context, alias s

// SetDefaultAliasForRollApp move the alias into the first place, so it can be used as default alias in resolution.
func (k Keeper) SetDefaultAliasForRollApp(ctx sdk.Context, rollAppId, alias string) error {
if _, err := rollapptypes.NewChainID(rollAppId); err != nil {
return errorsmod.Wrapf(gerrc.ErrInvalidArgument, "invalid RollApp chain-id: %s", rollAppId)
}

// load the existing aliases of the RollApp from store
existingAliases := k.GetAliasesOfRollAppId(ctx, rollAppId)

Expand All @@ -260,8 +281,8 @@ func (k Keeper) SetDefaultAliasForRollApp(ctx sdk.Context, rollAppId, alias stri
// update the new list into store

store := ctx.KVStore(k.storeKey)
keyR2A := dymnstypes.RollAppIdToAliasesKey(rollAppId)
store.Set(keyR2A, k.cdc.MustMarshal(&dymnstypes.MultipleAliases{Aliases: existingAliases}))
keyRE155toA := dymnstypes.RollAppIdToAliasesKey(rollAppId)
store.Set(keyRE155toA, k.cdc.MustMarshal(&dymnstypes.MultipleAliases{Aliases: existingAliases}))

return nil
}
Expand All @@ -270,16 +291,35 @@ func (k Keeper) SetDefaultAliasForRollApp(ctx sdk.Context, rollAppId, alias stri
func (k Keeper) GetAllRollAppsWithAliases(ctx sdk.Context) (list []dymnstypes.AliasesOfChainId) {
store := ctx.KVStore(k.storeKey)

iterator := sdk.KVStorePrefixIterator(store, dymnstypes.KeyPrefixRollAppIdToAliases)
iterator := sdk.KVStorePrefixIterator(store, dymnstypes.KeyPrefixRollAppEip155IdToAliases)
defer func() {
_ = iterator.Close()
}()

eip155ToRollAppIdCache := make(map[string]string)
// Describe usage of Go Map: used for caching purpose, no iteration.

for ; iterator.Valid(); iterator.Next() {
var multipleAliases dymnstypes.MultipleAliases
k.cdc.MustUnmarshal(iterator.Value(), &multipleAliases)

var rollAppId string
eip155Id := string(iterator.Key()[len(dymnstypes.KeyPrefixRollAppEip155IdToAliases):])
if cachedRollAppId, found := eip155ToRollAppIdCache[eip155Id]; found {
rollAppId = cachedRollAppId
} else {
eip155, _ := strconv.ParseUint(eip155Id, 10, 64)
var foundRollApp bool
rollAppId, foundRollApp = k.rollappKeeper.GetRollAppIdByEIP155(ctx, eip155)
if !foundRollApp {
// this should not happen as validated before
panic(fmt.Sprintf("rollapp not found by EIP155: %s", eip155Id))
}
eip155ToRollAppIdCache[eip155Id] = rollAppId // cache the result
}

list = append(list, dymnstypes.AliasesOfChainId{
ChainId: string(iterator.Key()[len(dymnstypes.KeyPrefixRollAppIdToAliases):]),
ChainId: rollAppId,
Aliases: multipleAliases.Aliases,
})
}
Expand Down
5 changes: 4 additions & 1 deletion x/dymns/keeper/alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@ func (s *KeeperTestSuite) TestKeeper_SetDefaultAliasForRollApp() {
existingAliases: nil,
moveAlias: "default",
wantErr: true,
wantErrContains: "alias is not linked to the RollApp",
wantErrContains: "invalid RollApp chain-id",
wantAliases: nil,
},
{
Expand Down Expand Up @@ -1045,6 +1045,9 @@ func (s *KeeperTestSuite) TestKeeper_SetDefaultAliasForRollApp() {
if tt.rollAppId == "" || s.T().Failed() {
return
}
if _, err := rollapptypes.NewChainID(tt.rollAppId); err != nil {
return
}
aliasesAfter := s.dymNsKeeper.GetAliasesOfRollAppId(s.ctx, tt.rollAppId)
if len(tt.wantAliases) == 0 {
s.Empty(aliasesAfter)
Expand Down
45 changes: 40 additions & 5 deletions x/dymns/keeper/dym_name.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package keeper

import (
"fmt"
"strconv"
"strings"

errorsmod "cosmossdk.io/errors"
Expand Down Expand Up @@ -297,6 +299,9 @@
if lookupChainIdConfig == ctx.ChainID() {
// Dym-Name configuration in store does not persist the chain-id if it is the host chain
lookupChainIdConfig = ""
} else if k.IsRollAppId(ctx, lookupChainIdConfig) {
// Dym-Name configuration in store only persist EIP-155 chain id for RollApp
lookupChainIdConfig = dymnsutils.MustGetEIP155ChainIdFromRollAppId(lookupChainIdConfig)
}

// do filter
Expand Down Expand Up @@ -721,6 +726,7 @@
ctx,
inputAddress,
workingChainId,
workingChainIdIsRollApp,
)
if err != nil {
return nil, err
Expand Down Expand Up @@ -765,23 +771,27 @@

// reverseResolveDymNameAddressUsingConfiguredAddress resolves the input address into a Dym-Name-Address
// which points to it.
func (k Keeper) reverseResolveDymNameAddressUsingConfiguredAddress(
ctx sdk.Context,
inputAddress,
workingChainId string,
) (outputDymNameAddresses dymnstypes.ReverseResolvedDymNameAddresses, err error) {
func (k Keeper) reverseResolveDymNameAddressUsingConfiguredAddress(ctx sdk.Context, inputAddress, workingChainId string, workingChainIdIsRollApp bool) (outputDymNameAddresses dymnstypes.ReverseResolvedDymNameAddresses, err error) {
// find all the Dym-Names those contain the input address in configuration,
// iterate through the configuration records to find out the Dym-Name-Address
dymNames, err1 := k.GetDymNamesContainsConfiguredAddress(ctx, inputAddress)
if err1 != nil {
return nil, err1
}

var eip155WorkingChainId string // only available if is RollApp
if workingChainIdIsRollApp {
eip155WorkingChainId = dymnsutils.MustGetEIP155ChainIdFromRollAppId(workingChainId)
}

for _, dymName := range dymNames {
configuredAddresses, _ := dymName.GetAddressesForReverseMapping()
configs := configuredAddresses[inputAddress]
outputDymNameAddresses = outputDymNameAddresses.AppendConfigs(ctx, dymName,
configs, func(address dymnstypes.ReverseResolvedDymNameAddress) bool {
if workingChainIdIsRollApp {
return address.ChainIdOrAlias == eip155WorkingChainId
}
return address.ChainIdOrAlias == workingChainId
},
)
Expand Down Expand Up @@ -829,11 +839,19 @@
return nil, err1
}

var eip155WorkingChainId string // only available if is RollApp
if workingChainIdIsRollApp {
eip155WorkingChainId = dymnsutils.MustGetEIP155ChainIdFromRollAppId(workingChainId)
}

for _, dymName := range dymNames {
configuredAddresses, _ := dymName.GetAddressesForReverseMapping()
configs := configuredAddresses[lookupKey]
outputDymNameAddresses = outputDymNameAddresses.AppendConfigs(ctx, dymName,
configs, func(address dymnstypes.ReverseResolvedDymNameAddress) bool {
if workingChainIdIsRollApp {
return address.ChainIdOrAlias == eip155WorkingChainId
}
return address.ChainIdOrAlias == workingChainId
},
)
Expand Down Expand Up @@ -909,6 +927,8 @@

resolvedCache := make(map[string]string)
// Describe usage of Go Map: used for caching purpose, no iteration.
eip155ToRollAppIdCache := make(map[string]string)
// Describe usage of Go Map: used for caching purpose, no iteration.

for i, reverseResolvedRecord := range reverseResolvedRecords {
chainIdOrAlias := reverseResolvedRecord.ChainIdOrAlias
Expand All @@ -919,6 +939,21 @@
// then at this place, we put it back
chainIdOrAlias = ctx.ChainID()
reverseResolvedRecords[i].ChainIdOrAlias = chainIdOrAlias
} else if dymnsutils.IsValidEIP155ChainId(chainIdOrAlias) {
fullRollAppId, found := eip155ToRollAppIdCache[chainIdOrAlias]
if !found {
rollAppEip155ChainId, _ := strconv.ParseUint(chainIdOrAlias, 10, 64)
var foundRA bool
fullRollAppId, foundRA = k.rollappKeeper.GetRollAppIdByEIP155(ctx, rollAppEip155ChainId)
if !foundRA {
// this should not happen because we have checked the existence of RollApp before
panic(fmt.Sprintf("RollApp by EIP-155 not found"))

Check failure on line 950 in x/dymns/keeper/dym_name.go

View workflow job for this annotation

GitHub Actions / golangci-lint

S1039: unnecessary use of fmt.Sprintf (gosimple)
}
eip155ToRollAppIdCache[chainIdOrAlias] = fullRollAppId // cache result
}

chainIdOrAlias = fullRollAppId
reverseResolvedRecords[i].ChainIdOrAlias = chainIdOrAlias
}

// check cache first
Expand Down
Loading
Loading