diff --git a/CHANGELOG.md b/CHANGELOG.md index 90678e23..afe8a087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,9 @@ Contains all the PRs that improved the code without changing the behaviors. ### Fixed - validator rewards payout +### Fixed +- fix non deterministic map iteration to sorted iteration + # v1.0.5-Prerelease ### Added - Arkeo testnet validator addresses to airdrop diff --git a/x/arkeo/configs/config.go b/x/arkeo/configs/config.go index d3fd35a4..cc86e9c3 100644 --- a/x/arkeo/configs/config.go +++ b/x/arkeo/configs/config.go @@ -4,9 +4,9 @@ import ( "encoding/json" "fmt" "regexp" + "sort" "strconv" "strings" - "time" ) var ( @@ -20,7 +20,7 @@ var ( stringOverrides = map[ConfigName]string{} ) -var BlockTime = 5 * time.Second +// var BlockTime = 5 * time.Second // ConfigVals implement ConfigValues interface type ConfigVals struct { @@ -71,23 +71,40 @@ func (cv *ConfigVals) GetStringValue(name ConfigName) string { } func (cv *ConfigVals) String() string { + // get all the keys + int64Keys := make([]ConfigName, 0, len(cv.int64values)) + for k := range cv.int64values { + int64Keys = append(int64Keys, k) + } + sort.Slice(int64Keys, func(i, j int) bool { + return int64Keys[i].String() < int64Keys[j].String() + }) + + boolKeys := make([]ConfigName, 0, len(cv.boolValues)) + for k := range cv.boolValues { + boolKeys = append(boolKeys, k) + } + sort.Slice(boolKeys, func(i, j int) bool { + return boolKeys[i].String() < boolKeys[j].String() + }) + sb := strings.Builder{} - // analyze-ignore(map-iteration) - for k, v := range cv.int64values { + for _, k := range int64Keys { if overrideValue, ok := int64Overrides[k]; ok { sb.WriteString(fmt.Sprintf("%s:%d\n", k, overrideValue)) continue } - sb.WriteString(fmt.Sprintf("%s:%d\n", k, v)) + sb.WriteString(fmt.Sprintf("%s:%d\n", k, cv.int64values[k])) } - // analyze-ignore(map-iteration) - for k, v := range cv.boolValues { + + for _, k := range boolKeys { if overrideValue, ok := boolOverrides[k]; ok { sb.WriteString(fmt.Sprintf("%s:%v\n", k, overrideValue)) continue } - sb.WriteString(fmt.Sprintf("%s:%v\n", k, v)) + sb.WriteString(fmt.Sprintf("%s:%v\n", k, cv.boolValues[k])) } + return sb.String() } @@ -101,29 +118,70 @@ func (cv ConfigVals) MarshalJSON() ([]byte, error) { result.Int64Values = make(map[string]int64) result.BoolValues = make(map[string]bool) result.StringValues = make(map[string]string) - // analyze-ignore(map-iteration) - for k, v := range cv.int64values { - result.Int64Values[k.String()] = v + + // get and sort all keys including overrides + int64Keys := make([]ConfigName, 0, len(cv.int64values)+len(int64Overrides)) + for k := range cv.int64values { + int64Keys = append(int64Keys, k) + } + for k := range int64Overrides { + if _, exists := cv.int64values[k]; !exists { + int64Keys = append(int64Keys, k) + } + } + sort.Slice(int64Keys, func(i, j int) bool { + return int64Keys[i].String() < int64Keys[j].String() + }) + + // Same for bool and string keys + boolKeys := make([]ConfigName, 0, len(cv.boolValues)+len(boolOverrides)) + for k := range cv.boolValues { + boolKeys = append(boolKeys, k) + } + for k := range boolOverrides { + if _, exists := cv.boolValues[k]; !exists { + boolKeys = append(boolKeys, k) + } } - // analyze-ignore(map-iteration) - for k, v := range int64Overrides { - result.Int64Values[k.String()] = v + sort.Slice(boolKeys, func(i, j int) bool { + return boolKeys[i].String() < boolKeys[j].String() + }) + + stringKeys := make([]ConfigName, 0, len(cv.stringValues)+len(stringOverrides)) + for k := range cv.stringValues { + stringKeys = append(stringKeys, k) } - // analyze-ignore(map-iteration) - for k, v := range cv.boolValues { - result.BoolValues[k.String()] = v + for k := range stringOverrides { + if _, exists := cv.stringValues[k]; !exists { + stringKeys = append(stringKeys, k) + } } - // analyze-ignore(map-iteration) - for k, v := range boolOverrides { - result.BoolValues[k.String()] = v + sort.Slice(stringKeys, func(i, j int) bool { + return stringKeys[i].String() < stringKeys[j].String() + }) + + for _, k := range int64Keys { + if override, ok := int64Overrides[k]; ok { + result.Int64Values[k.String()] = override + } else { + result.Int64Values[k.String()] = cv.int64values[k] + } } - // analyze-ignore(map-iteration) - for k, v := range cv.stringValues { - result.StringValues[k.String()] = v + + for _, k := range boolKeys { + if override, ok := boolOverrides[k]; ok { + result.BoolValues[k.String()] = override + } else { + result.BoolValues[k.String()] = cv.boolValues[k] + } } - // analyze-ignore(map-iteration) - for k, v := range stringOverrides { - result.StringValues[k.String()] = v + + for _, k := range stringKeys { + if override, ok := stringOverrides[k]; ok { + result.StringValues[k.String()] = override + } else { + result.StringValues[k.String()] = cv.stringValues[k] + } } return json.MarshalIndent(result, "", " ") diff --git a/x/arkeo/genesis_test.go b/x/arkeo/genesis_test.go index 5272c783..efb88ae2 100644 --- a/x/arkeo/genesis_test.go +++ b/x/arkeo/genesis_test.go @@ -15,7 +15,6 @@ import ( ) func TestGenesis(t *testing.T) { - ctx, k := keepertest.ArkeoKeeper(t) genesisState := types.GenesisState{ diff --git a/x/arkeo/keeper/msg_server_close_contract.go b/x/arkeo/keeper/msg_server_close_contract.go index 3d77bfc5..f000725d 100644 --- a/x/arkeo/keeper/msg_server_close_contract.go +++ b/x/arkeo/keeper/msg_server_close_contract.go @@ -90,7 +90,6 @@ func (k msgServer) CloseContractHandle(ctx cosmos.Context, msg *types.MsgCloseCo } if contract.IsPayAsYouGo() { - k.RemoveContractExpirationSet(ctx, contract.Expiration()) // add a new expiration return deposit to user newHeight := ctx.BlockHeight() + contract.SettlementDuration diff --git a/x/arkeo/keeper/msg_server_open_contract.go b/x/arkeo/keeper/msg_server_open_contract.go index e9e08bc9..6d6115d1 100644 --- a/x/arkeo/keeper/msg_server_open_contract.go +++ b/x/arkeo/keeper/msg_server_open_contract.go @@ -126,7 +126,6 @@ func (k msgServer) OpenContractValidate(ctx cosmos.Context, msg *types.MsgOpenCo } func (k msgServer) OpenContractHandle(ctx cosmos.Context, msg *types.MsgOpenContract) error { - // set back client as delegate if delegate is empty if msg.Delegate == "" { msg.Delegate = msg.Client diff --git a/x/claim/keeper/claim.go b/x/claim/keeper/claim.go index 9a8f47e2..752f2fbd 100644 --- a/x/claim/keeper/claim.go +++ b/x/claim/keeper/claim.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "sort" "strings" sdkerror "cosmossdk.io/errors" @@ -96,13 +97,24 @@ func (k Keeper) GetClaimRecords(ctx sdk.Context, chain types.Chain) ([]types.Cla func (k Keeper) GetAllClaimRecords(ctx sdk.Context) ([]types.ClaimRecord, error) { claimRecords := []types.ClaimRecord{} + + chains := make([]types.Chain, 0, len(types.Chain_name)) for chain := range types.Chain_name { - records, err := k.GetClaimRecords(ctx, types.Chain(chain)) + chains = append(chains, types.Chain(chain)) + } + + sort.Slice(chains, func(i, j int) bool { + return int32(chains[i]) < int32(chains[j]) + }) + + for _, chain := range chains { + records, err := k.GetClaimRecords(ctx, chain) if err != nil { return nil, err } claimRecords = append(claimRecords, records...) } + return claimRecords, nil } @@ -135,9 +147,19 @@ func (k Keeper) GetUserTotalClaimable(ctx sdk.Context, addr string, chain types. return sdk.Coin{}, nil } - totalClaimable := sdk.NewCoin(claimRecord.AmountClaim.Denom, cosmos.ZeroInt()) + actions := make([]types.Action, 0, len(types.Action_name)) for action := range types.Action_name { - claimableForAction, err := k.GetClaimableAmountForAction(ctx, addr, types.Action(action), chain) + actions = append(actions, types.Action(action)) + } + + sort.Slice(actions, func(i, j int) bool { + return int32(actions[i]) < int32(actions[j]) + }) + + totalClaimable := sdk.NewCoin(claimRecord.AmountClaim.Denom, cosmos.ZeroInt()) + + for _, action := range actions { + claimableForAction, err := k.GetClaimableAmountForAction(ctx, addr, action, chain) if err != nil { return sdk.Coin{}, err } diff --git a/x/claim/keeper/msg_server_claim_thorchain_test.go b/x/claim/keeper/msg_server_claim_thorchain_test.go index f9b18393..b6a3f0b6 100644 --- a/x/claim/keeper/msg_server_claim_thorchain_test.go +++ b/x/claim/keeper/msg_server_claim_thorchain_test.go @@ -17,7 +17,7 @@ func TestClaimThorchainTestnetAddress(t *testing.T) { config := sdk.GetConfig() config.SetBech32PrefixForAccount("tarkeo", "tarkeopub") - arkeoServerAddress, err := sdk.AccAddressFromBech32("tarkeo1z02ke8639m47g9dfrheegr2u9zecegt5qvtj00") + arkeoServerAddress, err := sdk.AccAddressFromBech32("tarkeo1zsafqx0qk6rp2vvs97n9udylquj7mfkt8mfypq") require.NoError(t, err) fromAddr := utils.GetRandomArkeoAddress() @@ -92,7 +92,7 @@ func TestClaimThorchainMainnetAddress(t *testing.T) { config := sdk.GetConfig() config.SetBech32PrefixForAccount("arkeo", "arkeopub") - arkeoServerAddress, err := sdk.AccAddressFromBech32("arkeo1z02ke8639m47g9dfrheegr2u9zecegt50fjg7v") + arkeoServerAddress, err := sdk.AccAddressFromBech32("arkeo1zsafqx0qk6rp2vvs97n9udylquj7mfktg7s7sr") require.NoError(t, err) fromAddr := utils.GetRandomArkeoAddress() @@ -167,7 +167,7 @@ func TestClaimThorchainFailureCases(t *testing.T) { config := sdk.GetConfig() config.SetBech32PrefixForAccount("arkeo", "arkeopub") - arkeoServerAddress, err := sdk.AccAddressFromBech32("arkeo1z02ke8639m47g9dfrheegr2u9zecegt50fjg7v") + arkeoServerAddress, err := sdk.AccAddressFromBech32("arkeo1zsafqx0qk6rp2vvs97n9udylquj7mfktg7s7sr") require.NoError(t, err) fromAddr := utils.GetRandomArkeoAddress() diff --git a/x/claim/types/params.go b/x/claim/types/params.go index 2f77d328..e520b417 100644 --- a/x/claim/types/params.go +++ b/x/claim/types/params.go @@ -24,7 +24,7 @@ var ( var ( KeyAirdropStartTime = []byte("AirdropStartTime") - DeafultAirdropStartTime time.Time = time.Now().UTC() + DefaultAirdropStartTime time.Time = time.Date(2025, 5, 1, 0, 0, 0, 0, time.UTC) ) var _ paramtypes.ParamSet = (*Params)(nil) @@ -50,7 +50,7 @@ func DefaultParams() Params { ClaimDenom: DefaultClaimDenom, DurationUntilDecay: DefaultDurationUntilDecay, DurationOfDecay: DefaultDurationOfDecay, - AirdropStartTime: DeafultAirdropStartTime, + AirdropStartTime: DefaultAirdropStartTime, } }