ibc-transfer: sims updates (#7123)
* ibc-transfer: sims updates * params and genesis * sim tests * update module.go * remove dontcover * Update x/ibc-transfer/simulation/decoder.go Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
This commit is contained in:
parent
a6defabb3d
commit
0234ad324e
|
@ -5,6 +5,7 @@ import (
|
|||
"math/big"
|
||||
"math/rand"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
@ -27,17 +28,15 @@ func RandStringOfLength(r *rand.Rand, n int) string {
|
|||
if remain == 0 {
|
||||
cache, remain = r.Int63(), letterIdxMax
|
||||
}
|
||||
|
||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
||||
b[i] = letterBytes[idx]
|
||||
i--
|
||||
}
|
||||
|
||||
cache >>= letterIdxBits
|
||||
remain--
|
||||
}
|
||||
|
||||
return string(b)
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
// RandPositiveInt get a rand positive sdk.Int
|
||||
|
|
|
@ -9,13 +9,14 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
type SupplyUnmarshaller interface {
|
||||
// SupplyUnmarshaler defines the expected encoding store functions.
|
||||
type SupplyUnmarshaler interface {
|
||||
UnmarshalSupply([]byte) (exported.SupplyI, error)
|
||||
}
|
||||
|
||||
// NewDecodeStore returns a function closure that unmarshals the KVPair's values
|
||||
// to the corresponding types.
|
||||
func NewDecodeStore(cdc SupplyUnmarshaller) func(kvA, kvB kv.Pair) string {
|
||||
func NewDecodeStore(cdc SupplyUnmarshaler) func(kvA, kvB kv.Pair) string {
|
||||
return func(kvA, kvB kv.Pair) string {
|
||||
switch {
|
||||
case bytes.Equal(kvA.Key[:1], types.SupplyKey):
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
|
||||
)
|
||||
|
||||
// UnmarshalDenomTrace attempts to decode and return an DenomTrace object from
|
||||
// raw encoded bytes.
|
||||
func (k Keeper) UnmarshalDenomTrace(bz []byte) (types.DenomTrace, error) {
|
||||
var denomTrace types.DenomTrace
|
||||
if err := k.cdc.UnmarshalBinaryBare(bz, &denomTrace); err != nil {
|
||||
return types.DenomTrace{}, err
|
||||
}
|
||||
return denomTrace, nil
|
||||
}
|
||||
|
||||
// MustUnmarshalDenomTrace attempts to decode and return an DenomTrace object from
|
||||
// raw encoded bytes. It panics on error.
|
||||
func (k Keeper) MustUnmarshalDenomTrace(bz []byte) types.DenomTrace {
|
||||
var denomTrace types.DenomTrace
|
||||
k.cdc.MustUnmarshalBinaryBare(bz, &denomTrace)
|
||||
return denomTrace
|
||||
}
|
||||
|
||||
// MarshalDenomTrace attempts to encode an DenomTrace object and returns the
|
||||
// raw encoded bytes.
|
||||
func (k Keeper) MarshalDenomTrace(denomTrace types.DenomTrace) ([]byte, error) {
|
||||
return k.cdc.MarshalBinaryBare(&denomTrace)
|
||||
}
|
||||
|
||||
// MustMarshalDenomTrace attempts to encode an DenomTrace object and returns the
|
||||
// raw encoded bytes. It panics on error.
|
||||
func (k Keeper) MustMarshalDenomTrace(denomTrace types.DenomTrace) []byte {
|
||||
return k.cdc.MustMarshalBinaryBare(&denomTrace)
|
||||
}
|
|
@ -53,8 +53,8 @@ func (q Keeper) DenomTraces(c context.Context, req *types.QueryDenomTracesReques
|
|||
store := prefix.NewStore(ctx.KVStore(q.storeKey), types.DenomTraceKey)
|
||||
|
||||
pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error {
|
||||
var result types.DenomTrace
|
||||
if err := q.cdc.UnmarshalBinaryBare(value, &result); err != nil {
|
||||
result, err := q.UnmarshalDenomTrace(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -127,8 +127,7 @@ func (k Keeper) GetDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes)
|
|||
return types.DenomTrace{}, false
|
||||
}
|
||||
|
||||
var denomTrace types.DenomTrace
|
||||
k.cdc.MustUnmarshalBinaryBare(bz, &denomTrace)
|
||||
denomTrace := k.MustUnmarshalDenomTrace(bz)
|
||||
return denomTrace, true
|
||||
}
|
||||
|
||||
|
@ -141,7 +140,7 @@ func (k Keeper) HasDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes)
|
|||
// SetDenomTrace sets a new {trace hash -> denom trace} pair to the store.
|
||||
func (k Keeper) SetDenomTrace(ctx sdk.Context, denomTrace types.DenomTrace) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.DenomTraceKey)
|
||||
bz := k.cdc.MustMarshalBinaryBare(&denomTrace)
|
||||
bz := k.MustMarshalDenomTrace(denomTrace)
|
||||
store.Set(denomTrace.Hash(), bz)
|
||||
}
|
||||
|
||||
|
@ -165,9 +164,7 @@ func (k Keeper) IterateDenomTraces(ctx sdk.Context, cb func(denomTrace types.Den
|
|||
defer iterator.Close()
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
|
||||
var denomTrace types.DenomTrace
|
||||
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &denomTrace)
|
||||
|
||||
denomTrace := k.MustUnmarshalDenomTrace(iterator.Value())
|
||||
if cb(denomTrace) {
|
||||
break
|
||||
}
|
||||
|
|
|
@ -159,13 +159,14 @@ func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedP
|
|||
return nil
|
||||
}
|
||||
|
||||
// RandomizedParams returns nil.
|
||||
func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange {
|
||||
return nil
|
||||
// RandomizedParams creates randomized ibc-transfer param changes for the simulator.
|
||||
func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange {
|
||||
return simulation.ParamChanges(r)
|
||||
}
|
||||
|
||||
// RegisterStoreDecoder registers a decoder for transfer module's types
|
||||
func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {
|
||||
func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
|
||||
sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper)
|
||||
}
|
||||
|
||||
// WeightedOperations returns the all the transfer module operations with their respective weights.
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package simulation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
|
||||
)
|
||||
|
||||
// TransferUnmarshaler defines the expected encoding store functions.
|
||||
type TransferUnmarshaler interface {
|
||||
MustUnmarshalDenomTrace([]byte) types.DenomTrace
|
||||
}
|
||||
|
||||
// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
|
||||
// Value to the corresponding DenomTrace type.
|
||||
func NewDecodeStore(cdc TransferUnmarshaler) func(kvA, kvB kv.Pair) string {
|
||||
return func(kvA, kvB kv.Pair) string {
|
||||
switch {
|
||||
case bytes.Equal(kvA.Key[:1], types.PortKey):
|
||||
return fmt.Sprintf("Port A: %s\nPort B: %s", string(kvA.Value), string(kvB.Value))
|
||||
|
||||
case bytes.Equal(kvA.Key[:1], types.DenomTraceKey):
|
||||
denomTraceA := cdc.MustUnmarshalDenomTrace(kvA.Value)
|
||||
denomTraceB := cdc.MustUnmarshalDenomTrace(kvB.Value)
|
||||
return fmt.Sprintf("DenomTrace A: %s\nDenomTrace B: %s", denomTraceA.IBCDenom(), denomTraceB.IBCDenom())
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid %s key prefix %X", types.ModuleName, kvA.Key[:1]))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package simulation_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc-transfer/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
|
||||
)
|
||||
|
||||
func TestDecodeStore(t *testing.T) {
|
||||
app := simapp.Setup(false)
|
||||
dec := simulation.NewDecodeStore(app.TransferKeeper)
|
||||
|
||||
trace := types.DenomTrace{
|
||||
BaseDenom: "uatom",
|
||||
Path: "transfer/channelToA",
|
||||
}
|
||||
|
||||
kvPairs := kv.Pairs{
|
||||
Pairs: []kv.Pair{
|
||||
{
|
||||
Key: types.PortKey,
|
||||
Value: []byte(types.PortID),
|
||||
},
|
||||
{
|
||||
Key: types.DenomTraceKey,
|
||||
Value: app.TransferKeeper.MustMarshalDenomTrace(trace),
|
||||
},
|
||||
{
|
||||
Key: []byte{0x99},
|
||||
Value: []byte{0x99},
|
||||
},
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedLog string
|
||||
}{
|
||||
{"PortID", fmt.Sprintf("Port A: %s\nPort B: %s", types.PortID, types.PortID)},
|
||||
{"DenomTrace", fmt.Sprintf("DenomTrace A: %s\nDenomTrace B: %s", trace.IBCDenom(), trace.IBCDenom())},
|
||||
{"other", ""},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
i, tt := i, tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if i == len(tests)-1 {
|
||||
require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name)
|
||||
} else {
|
||||
require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -14,6 +14,11 @@ import (
|
|||
// Simulation parameter constants
|
||||
const port = "port_id"
|
||||
|
||||
// RadomEnabled randomized send or receive enabled param with 75% prob of being true.
|
||||
func RadomEnabled(r *rand.Rand) bool {
|
||||
return r.Int63n(101) <= 75
|
||||
}
|
||||
|
||||
// RandomizedGenState generates a random GenesisState for transfer.
|
||||
func RandomizedGenState(simState *module.SimulationState) {
|
||||
var portID string
|
||||
|
@ -22,8 +27,22 @@ func RandomizedGenState(simState *module.SimulationState) {
|
|||
func(r *rand.Rand) { portID = strings.ToLower(simtypes.RandStringOfLength(r, 20)) },
|
||||
)
|
||||
|
||||
var sendEnabled bool
|
||||
simState.AppParams.GetOrGenerate(
|
||||
simState.Cdc, string(types.KeySendEnabled), &sendEnabled, simState.Rand,
|
||||
func(r *rand.Rand) { sendEnabled = RadomEnabled(r) },
|
||||
)
|
||||
|
||||
var receiveEnabled bool
|
||||
simState.AppParams.GetOrGenerate(
|
||||
simState.Cdc, string(types.KeyReceiveEnabled), &receiveEnabled, simState.Rand,
|
||||
func(r *rand.Rand) { receiveEnabled = RadomEnabled(r) },
|
||||
)
|
||||
|
||||
transferGenesis := types.GenesisState{
|
||||
PortId: portID,
|
||||
PortId: portID,
|
||||
DenomTraces: types.Traces{},
|
||||
Params: types.NewParams(sendEnabled, receiveEnabled),
|
||||
}
|
||||
|
||||
fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, &transferGenesis))
|
||||
|
|
|
@ -37,6 +37,9 @@ func TestRandomizedGenState(t *testing.T) {
|
|||
simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &ibcTransferGenesis)
|
||||
|
||||
require.Equal(t, "euzxpfgkqegqiqwixnku", ibcTransferGenesis.PortId)
|
||||
require.True(t, ibcTransferGenesis.Params.SendEnabled)
|
||||
require.True(t, ibcTransferGenesis.Params.ReceiveEnabled)
|
||||
require.Len(t, ibcTransferGenesis.DenomTraces, 0)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package simulation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
gogotypes "github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
|
||||
)
|
||||
|
||||
// ParamChanges defines the parameters that can be modified by param change proposals
|
||||
// on the simulation
|
||||
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
|
||||
return []simtypes.ParamChange{
|
||||
simulation.NewSimParamChange(types.ModuleName, string(types.KeySendEnabled),
|
||||
func(r *rand.Rand) string {
|
||||
sendEnabled := RadomEnabled(r)
|
||||
return fmt.Sprintf("%s", types.ModuleCdc.MustMarshalJSON(&gogotypes.BoolValue{Value: sendEnabled}))
|
||||
},
|
||||
),
|
||||
simulation.NewSimParamChange(types.ModuleName, string(types.KeyReceiveEnabled),
|
||||
func(r *rand.Rand) string {
|
||||
receiveEnabled := RadomEnabled(r)
|
||||
return fmt.Sprintf("%s", types.ModuleCdc.MustMarshalJSON(&gogotypes.BoolValue{Value: receiveEnabled}))
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package simulation_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc-transfer/simulation"
|
||||
)
|
||||
|
||||
func TestParamChanges(t *testing.T) {
|
||||
s := rand.NewSource(1)
|
||||
r := rand.New(s)
|
||||
|
||||
expected := []struct {
|
||||
composedKey string
|
||||
key string
|
||||
simValue string
|
||||
subspace string
|
||||
}{
|
||||
{"transfer/SendEnabled", "SendEnabled", "false", "transfer"},
|
||||
{"transfer/ReceiveEnabled", "ReceiveEnabled", "true", "transfer"},
|
||||
}
|
||||
|
||||
paramChanges := simulation.ParamChanges(r)
|
||||
|
||||
require.Len(t, paramChanges, 2)
|
||||
|
||||
for i, p := range paramChanges {
|
||||
require.Equal(t, expected[i].composedKey, p.ComposedKey())
|
||||
require.Equal(t, expected[i].key, p.Key())
|
||||
require.Equal(t, expected[i].simValue, p.SimValue()(r), p.Key())
|
||||
require.Equal(t, expected[i].subspace, p.Subspace())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue