From c0b7072aec5dd65dbfac697cdee18a85e4985c84 Mon Sep 17 00:00:00 2001 From: Dan Kanefsky <56059752+boojamya@users.noreply.github.com> Date: Tue, 23 May 2023 12:34:01 -0700 Subject: [PATCH] Merge #86: Backports #78, #80, #81 into `v6` * Fix same bool being used for all 3 (#81) * fix: middleware panic upon receiving amount that is not int64; added test (#78) resolves https://github.com/strangelove-ventures/packet-forward-middleware/issues/77 * Fix: Allows timeout field to accept both uint64 and string durations (#80) * timeout accetps both string and time.duration * feedback * handle invalid unmarshalls * Update router/ibc_middleware.go Co-authored-by: Andrew Gouin * add test case for empty valid json --------- Co-authored-by: Andrew Gouin * make compliant with ibc-go version and fix lint * remove unused make test command * regen protos * add lint check to CI --------- Co-authored-by: Andrew Gouin Co-authored-by: Max Kupriianov --- .github/workflows/golangci.yaml | 27 +++++++ Makefile | 2 +- go.mod | 2 +- router/ibc_middleware.go | 58 +++++++------- router/keeper/keeper.go | 27 ++++--- router/module_test.go | 129 +++++++++++++++++++++++++++++++- router/types/forward.go | 38 ++++++++-- router/types/forward_test.go | 26 +++++++ router/types/genesis.pb.go | 44 +++++------ 9 files changed, 281 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/golangci.yaml diff --git a/.github/workflows/golangci.yaml b/.github/workflows/golangci.yaml new file mode 100644 index 0000000..d49ad4f --- /dev/null +++ b/.github/workflows/golangci.yaml @@ -0,0 +1,27 @@ +name: golangci-lint +on: + push: + tags: + - v* + branches: + - master + - main + pull_request: +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + # pull-requests: read +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v3 + with: + go-version: 1.19 + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version + version: latest \ No newline at end of file diff --git a/Makefile b/Makefile index eb556ce..37fc8c3 100644 --- a/Makefile +++ b/Makefile @@ -176,7 +176,7 @@ go.sum: go.mod ############################################################################### test: test-unit -test-all: test-unit test-ledger-mock test-race test-cover +test-all: test-unit test-ledger-mock test-race TEST_PACKAGES=./... TEST_TARGETS := test-unit test-unit-amino test-unit-proto test-ledger-mock test-race test-ledger test-race diff --git a/go.mod b/go.mod index 1b9f160..2fac56c 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ replace ( ) require ( + cosmossdk.io/errors v1.0.0-beta.7 github.com/armon/go-metrics v0.4.1 github.com/cosmos/cosmos-sdk v0.46.9 github.com/cosmos/ibc-go/v6 v6.1.0 @@ -26,7 +27,6 @@ require ( ) require ( - cosmossdk.io/errors v1.0.0-beta.7 // indirect cosmossdk.io/math v1.0.0-beta.4 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect diff --git a/router/ibc_middleware.go b/router/ibc_middleware.go index 145d5a4..748a0f6 100644 --- a/router/ibc_middleware.go +++ b/router/ibc_middleware.go @@ -6,6 +6,7 @@ import ( "strings" "time" + errorsmod "cosmossdk.io/errors" "github.com/armon/go-metrics" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -119,6 +120,18 @@ func getDenomForThisChain(port, channel, counterpartyPort, counterpartyChannel, return transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom() } +// getBoolFromAny returns the bool value is any is a valid bool, otherwise false. +func getBoolFromAny(value any) bool { + if value == nil { + return false + } + boolVal, ok := value.(bool) + if !ok { + return false + } + return boolVal +} + // OnRecvPacket checks the memo field on this packet and if the metadata inside's root key indicates this packet // should be handled by the swap middleware it attempts to perform a swap. If the swap is successful // the underlying application's OnRecvPacket callback is invoked, an ack error is returned otherwise. @@ -136,40 +149,28 @@ func (im IBCMiddleware) OnRecvPacket( "sequence", packet.Sequence, "src-channel", packet.SourceChannel, "src-port", packet.SourcePort, "dst-channel", packet.DestinationChannel, "dst-port", packet.DestinationPort, - "amount", data.Amount, "denom", data.Denom, + "amount", data.Amount, "denom", data.Denom, "memo", data.Memo, ) - m := &types.PacketMetadata{} - err := json.Unmarshal([]byte(data.Memo), m) - if err != nil || m.Forward == nil { + d := make(map[string]interface{}) + err := json.Unmarshal([]byte(data.Memo), &d) + if err != nil || d["forward"] == nil { // not a packet that should be forwarded im.keeper.Logger(ctx).Debug("packetForwardMiddleware OnRecvPacket forward metadata does not exist") return im.app.OnRecvPacket(ctx, packet, relayer) } + m := &types.PacketMetadata{} + err = json.Unmarshal([]byte(data.Memo), m) + if err != nil { + return channeltypes.NewErrorAcknowledgement(fmt.Errorf("packetForwardMiddleware error parsing forward metadata, %s", err)) + } metadata := m.Forward - var processed, nonrefundable, disableDenomComposition bool goCtx := ctx.Context() - p := goCtx.Value(types.ProcessedKey{}) - nr := goCtx.Value(types.NonrefundableKey{}) - ddc := goCtx.Value(types.DisableDenomCompositionKey{}) - - if p != nil { - if pb, ok := p.(bool); ok { - processed = pb - } - } - if nr != nil { - if nrb, ok := p.(bool); ok { - nonrefundable = nrb - } - } - if ddc != nil { - if ddcb, ok := p.(bool); ok { - disableDenomComposition = ddcb - } - } + processed := getBoolFromAny(goCtx.Value(types.ProcessedKey{})) + nonrefundable := getBoolFromAny(goCtx.Value(types.NonrefundableKey{})) + disableDenomComposition := getBoolFromAny(goCtx.Value(types.DisableDenomCompositionKey{})) if err := metadata.Validate(); err != nil { return channeltypes.NewErrorAcknowledgement(err) @@ -203,10 +204,9 @@ func (im IBCMiddleware) OnRecvPacket( token := sdk.NewCoin(denomOnThisChain, amountInt) - var timeout time.Duration - if metadata.Timeout.Nanoseconds() > 0 { - timeout = metadata.Timeout - } else { + timeout := time.Duration(metadata.Timeout) + + if timeout.Nanoseconds() <= 0 { timeout = im.forwardTimeout } @@ -254,7 +254,7 @@ func (im IBCMiddleware) OnAcknowledgementPacket( var ack channeltypes.Acknowledgement if err := channeltypes.SubModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) + return errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) } inFlightPacket := im.keeper.GetAndClearInFlightPacket(ctx, packet.SourceChannel, packet.SourcePort, packet.Sequence) diff --git a/router/keeper/keeper.go b/router/keeper/keeper.go index 3da7b7f..936a41b 100644 --- a/router/keeper/keeper.go +++ b/router/keeper/keeper.go @@ -6,6 +6,7 @@ import ( "strings" "time" + errorsmod "cosmossdk.io/errors" "github.com/armon/go-metrics" "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" @@ -98,9 +99,9 @@ func (k *Keeper) WriteAcknowledgementForForwardedPacket( ack channeltypes.Acknowledgement, ) error { // Lookup module by channel capability - _, cap, err := k.channelKeeper.LookupModuleByChannel(ctx, inFlightPacket.RefundPortId, inFlightPacket.RefundChannelId) + _, chanCap, err := k.channelKeeper.LookupModuleByChannel(ctx, inFlightPacket.RefundPortId, inFlightPacket.RefundChannelId) if err != nil { - return sdkerrors.Wrap(err, "could not retrieve module from port-id") + return errorsmod.Wrap(err, "could not retrieve module from port-id") } // for forwarded packets, the funds were moved into an escrow account if the denom originated on this chain. @@ -113,7 +114,7 @@ func (k *Keeper) WriteAcknowledgementForForwardedPacket( ackResult := fmt.Sprintf("packet forward failed after point of no return: %s", ack.GetError()) newAck := channeltypes.NewResultAcknowledgement([]byte(ackResult)) - return k.ics4Wrapper.WriteAcknowledgement(ctx, cap, channeltypes.Packet{ + return k.ics4Wrapper.WriteAcknowledgement(ctx, chanCap, channeltypes.Packet{ Data: inFlightPacket.PacketData, Sequence: inFlightPacket.RefundSequence, SourcePort: inFlightPacket.PacketSrcPortId, @@ -181,7 +182,7 @@ func (k *Keeper) WriteAcknowledgementForForwardedPacket( } } - return k.ics4Wrapper.WriteAcknowledgement(ctx, cap, channeltypes.Packet{ + return k.ics4Wrapper.WriteAcknowledgement(ctx, chanCap, channeltypes.Packet{ Data: inFlightPacket.PacketData, Sequence: inFlightPacket.RefundSequence, SourcePort: inFlightPacket.PacketSrcPortId, @@ -223,7 +224,7 @@ func (k *Keeper) ForwardTransferPacket( k.Logger(ctx).Error("packetForwardMiddleware error funding community pool", "error", err, ) - return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) + return errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) } } @@ -236,7 +237,7 @@ func (k *Keeper) ForwardTransferPacket( k.Logger(ctx).Error("packetForwardMiddleware error marshaling next as JSON", "error", err, ) - return sdkerrors.Wrapf(sdkerrors.ErrJSONMarshal, err.Error()) + return errorsmod.Wrapf(sdkerrors.ErrJSONMarshal, err.Error()) } memo = string(memoBz) } @@ -270,7 +271,7 @@ func (k *Keeper) ForwardTransferPacket( "amount", packetCoin.Amount.String(), "denom", packetCoin.Denom, "error", err, ) - return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) + return errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) } // Store the following information in keeper: @@ -304,11 +305,13 @@ func (k *Keeper) ForwardTransferPacket( store.Set(key, bz) defer func() { - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", "ibc", "transfer"}, - float32(token.Amount.Int64()), - []metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, token.Denom)}, - ) + if token.Amount.IsInt64() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "ibc", "transfer"}, + float32(token.Amount.Int64()), + []metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, token.Denom)}, + ) + } telemetry.IncrCounterWithLabels( []string{"ibc", types.ModuleName, "send"}, diff --git a/router/module_test.go b/router/module_test.go index ebf07d8..101c1bd 100644 --- a/router/module_test.go +++ b/router/module_test.go @@ -18,8 +18,9 @@ import ( ) var ( - testDenom = "uatom" - testAmount = "100" + testDenom = "uatom" + testAmount = "100" + testAmount256 = "100000000000000000000" testSourcePort = "transfer" testSourceChannel = "channel-10" @@ -65,6 +66,36 @@ func transferPacket(t *testing.T, receiver string, metadata any) channeltypes.Pa } } +func transferPacket256(t *testing.T, receiver string, metadata any) channeltypes.Packet { + t.Helper() + transferPacket := transfertypes.FungibleTokenPacketData{ + Denom: testDenom, + Amount: testAmount256, + Receiver: receiver, + } + + if metadata != nil { + if mStr, ok := metadata.(string); ok { + transferPacket.Memo = mStr + } else { + memo, err := json.Marshal(metadata) + require.NoError(t, err) + transferPacket.Memo = string(memo) + } + } + + transferData, err := transfertypes.ModuleCdc.MarshalJSON(&transferPacket) + require.NoError(t, err) + + return channeltypes.Packet{ + SourcePort: testSourcePort, + SourceChannel: testSourceChannel, + DestinationPort: testDestinationPort, + DestinationChannel: testDestinationChannel, + Data: transferData, + } +} + func TestOnRecvPacket_EmptyPacket(t *testing.T) { ctl := gomock.NewController(t) defer ctl.Finish() @@ -139,6 +170,33 @@ func TestOnRecvPacket_NoForward(t *testing.T) { require.Equal(t, "test", string(expectedAck.GetResult())) } +func TestOnRecvPacket_NoMemo(t *testing.T) { + ctl := gomock.NewController(t) + defer ctl.Finish() + setup := test.NewTestSetup(t, ctl) + ctx := setup.Initializer.Ctx + cdc := setup.Initializer.Marshaler + forwardMiddleware := setup.ForwardMiddleware + + // Test data + senderAccAddr := test.AccAddress() + packet := transferPacket(t, "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k", "{}") + + // Expected mocks + gomock.InOrder( + setup.Mocks.IBCModuleMock.EXPECT().OnRecvPacket(ctx, packet, senderAccAddr). + Return(channeltypes.NewResultAcknowledgement([]byte("test"))), + ) + + ack := forwardMiddleware.OnRecvPacket(ctx, packet, senderAccAddr) + require.True(t, ack.Success()) + + expectedAck := &channeltypes.Acknowledgement{} + err := cdc.UnmarshalJSON(ack.Acknowledgement(), expectedAck) + require.NoError(t, err) + require.Equal(t, "test", string(expectedAck.GetResult())) +} + func TestOnRecvPacket_RecvPacketFailed(t *testing.T) { ctl := gomock.NewController(t) defer ctl.Finish() @@ -229,6 +287,73 @@ func TestOnRecvPacket_ForwardNoFee(t *testing.T) { require.NoError(t, err) } +func TestOnRecvPacket_ForwardAmountInt256(t *testing.T) { + var err error + ctl := gomock.NewController(t) + defer ctl.Finish() + setup := test.NewTestSetup(t, ctl) + ctx := setup.Initializer.Ctx + cdc := setup.Initializer.Marshaler + forwardMiddleware := setup.ForwardMiddleware + + // Test data + const ( + hostAddr = "cosmos1vzxkv3lxccnttr9rs0002s93sgw72h7ghukuhs" + destAddr = "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k" + port = "transfer" + channel = "channel-0" + ) + denom := makeIBCDenom(testDestinationPort, testDestinationChannel, testDenom) + senderAccAddr := test.AccAddress() + + amount256, ok := sdk.NewIntFromString(testAmount256) + require.True(t, ok) + + testCoin := sdk.NewCoin(denom, amount256) + packetOrig := transferPacket256(t, hostAddr, &types.PacketMetadata{ + Forward: &types.ForwardMetadata{ + Receiver: destAddr, + Port: port, + Channel: channel, + }, + }) + packetFwd := transferPacket256(t, destAddr, nil) + + acknowledgement := channeltypes.NewResultAcknowledgement([]byte("test")) + successAck := cdc.MustMarshalJSON(&acknowledgement) + + // Expected mocks + gomock.InOrder( + setup.Mocks.IBCModuleMock.EXPECT().OnRecvPacket(ctx, packetOrig, senderAccAddr). + Return(acknowledgement), + + setup.Mocks.TransferKeeperMock.EXPECT().Transfer( + sdk.WrapSDKContext(ctx), + transfertypes.NewMsgTransfer( + port, + channel, + testCoin, + hostAddr, + destAddr, + keeper.DefaultTransferPacketTimeoutHeight, + uint64(ctx.BlockTime().UnixNano())+uint64(keeper.DefaultForwardTransferPacketTimeoutTimestamp.Nanoseconds()), + "", + ), + ).Return(&transfertypes.MsgTransferResponse{Sequence: 0}, nil), + + setup.Mocks.IBCModuleMock.EXPECT().OnAcknowledgementPacket(ctx, packetFwd, successAck, senderAccAddr). + Return(nil), + ) + + // chain B with router module receives packet and forwards. ack should be nil so that it is not written yet. + ack := forwardMiddleware.OnRecvPacket(ctx, packetOrig, senderAccAddr) + require.Nil(t, ack) + + // ack returned from chain C + err = forwardMiddleware.OnAcknowledgementPacket(ctx, packetFwd, successAck, senderAccAddr) + require.NoError(t, err) +} + func TestOnRecvPacket_ForwardWithFee(t *testing.T) { var err error ctl := gomock.NewController(t) diff --git a/router/types/forward.go b/router/types/forward.go index cd49845..87b3edd 100644 --- a/router/types/forward.go +++ b/router/types/forward.go @@ -2,6 +2,7 @@ package types import ( "encoding/json" + "errors" "fmt" "time" @@ -14,17 +15,19 @@ type PacketMetadata struct { } type ForwardMetadata struct { - Receiver string `json:"receiver,omitempty"` - Port string `json:"port,omitempty"` - Channel string `json:"channel,omitempty"` - Timeout time.Duration `json:"timeout,omitempty"` - Retries *uint8 `json:"retries,omitempty"` + Receiver string `json:"receiver,omitempty"` + Port string `json:"port,omitempty"` + Channel string `json:"channel,omitempty"` + Timeout Duration `json:"timeout,omitempty"` + Retries *uint8 `json:"retries,omitempty"` // Using JSONObject so that objects for next property will not be mutated by golang's lexicographic key sort on map keys during Marshal. // Supports primitives for Unmarshal/Marshal so that an escaped JSON-marshaled string is also valid. Next *JSONObject `json:"next,omitempty"` } +type Duration time.Duration + func (m *ForwardMetadata) Validate() error { if m.Receiver == "" { return fmt.Errorf("failed to validate forward metadata. receiver cannot be empty") @@ -86,3 +89,28 @@ func (o JSONObject) MarshalJSON() ([]byte, error) { // primitive, return raw bytes. return o.primitive, nil } + +func (d Duration) MarshalJSON() ([]byte, error) { + return json.Marshal(time.Duration(d).Nanoseconds()) +} + +func (d *Duration) UnmarshalJSON(b []byte) error { + var v interface{} + if err := json.Unmarshal(b, &v); err != nil { + return err + } + switch value := v.(type) { + case float64: + *d = Duration(time.Duration(value)) + return nil + case string: + tmp, err := time.ParseDuration(value) + if err != nil { + return err + } + *d = Duration(tmp) + return nil + default: + return errors.New("invalid duration") + } +} diff --git a/router/types/forward_test.go b/router/types/forward_test.go index 40a6677..a3b29b7 100644 --- a/router/types/forward_test.go +++ b/router/types/forward_test.go @@ -31,3 +31,29 @@ func TestForwardMetadataUnmarshalJSONNext(t *testing.T) { require.NoError(t, err) require.Equal(t, `{"forward":{"receiver":"noble1l505zhahp24v5jsmps9vs5asah759fdce06sfp","port":"transfer","channel":"channel-0","timeout":0}}`, string(nextBz)) } + +func TestTimeoutUnmarshalString(t *testing.T) { + const memo = "{\"forward\":{\"receiver\":\"noble1f4cur2krsua2th9kkp7n0zje4stea4p9tu70u8\",\"port\":\"transfer\",\"channel\":\"channel-0\",\"timeout\":\"60s\"}}" + var packetMetadata types.PacketMetadata + + err := json.Unmarshal([]byte(memo), &packetMetadata) + require.NoError(t, err) + + timeoutBz, err := json.Marshal(packetMetadata.Forward.Timeout) + require.NoError(t, err) + + require.Equal(t, "60000000000", string(timeoutBz)) +} + +func TestTimeoutUnmarshalJSON(t *testing.T) { + const memo = "{\"forward\":{\"receiver\":\"noble1f4cur2krsua2th9kkp7n0zje4stea4p9tu70u8\",\"port\":\"transfer\",\"channel\":\"channel-0\",\"timeout\": 60000000000}}" + var packetMetadata types.PacketMetadata + + err := json.Unmarshal([]byte(memo), &packetMetadata) + require.NoError(t, err) + + timeoutBz, err := json.Marshal(packetMetadata.Forward.Timeout) + require.NoError(t, err) + + require.Equal(t, "60000000000", string(timeoutBz)) +} diff --git a/router/types/genesis.pb.go b/router/types/genesis.pb.go index 2201c4d..de0bbe2 100644 --- a/router/types/genesis.pb.go +++ b/router/types/genesis.pb.go @@ -266,7 +266,7 @@ var fileDescriptor_4940b763c55c4e0b = []byte{ // 646 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x54, 0x4d, 0x4f, 0xdb, 0x3e, 0x18, 0x6f, 0x4a, 0x29, 0xd4, 0x2d, 0x6f, 0xfe, 0xc3, 0x9f, 0x8c, 0x43, 0x5b, 0x55, 0x68, 0xab, - 0xc6, 0x9a, 0x08, 0x90, 0x26, 0xc4, 0x6d, 0x1d, 0x1b, 0xeb, 0xad, 0x4a, 0x39, 0x4d, 0x9a, 0x22, + 0xc6, 0x9a, 0x08, 0x26, 0x21, 0xc4, 0x6d, 0x1d, 0x1b, 0xeb, 0xad, 0x4a, 0x39, 0x4d, 0x9a, 0x22, 0x93, 0x3c, 0x4d, 0x23, 0x12, 0x3b, 0xb3, 0x9d, 0xb2, 0xee, 0x53, 0xec, 0xbc, 0xcb, 0xbe, 0x0e, 0x47, 0x8e, 0xd3, 0x0e, 0xd5, 0x04, 0xdf, 0x80, 0x4f, 0x30, 0xc5, 0x4e, 0xa1, 0xd5, 0x76, 0x8a, 0xfd, 0xfc, 0x5e, 0xfc, 0x7b, 0x9e, 0x58, 0x46, 0xbb, 0x9c, 0xa5, 0x12, 0xb8, 0x3d, 0x3e, 0xb4, @@ -284,27 +284,27 @@ var fileDescriptor_4940b763c55c4e0b = []byte{ 0xdd, 0xf3, 0x2c, 0xf3, 0xaf, 0x69, 0xe3, 0x79, 0x10, 0xca, 0x51, 0x7a, 0x69, 0x79, 0x2c, 0xb6, 0x3d, 0x26, 0x62, 0x26, 0xf2, 0x4f, 0x47, 0xf8, 0x57, 0xb6, 0x9c, 0x24, 0x20, 0xac, 0x33, 0xf0, 0x1e, 0xa6, 0x8d, 0x1d, 0xdd, 0xdd, 0xa2, 0x5b, 0xcb, 0x59, 0x1b, 0x02, 0xf4, 0x9f, 0xf6, 0x3f, - 0x4a, 0x68, 0x7d, 0x31, 0x17, 0x7e, 0x8d, 0x76, 0x19, 0x0f, 0x83, 0x90, 0x92, 0xc8, 0x15, 0x40, - 0x7d, 0xe0, 0x2e, 0xf1, 0x7d, 0x0e, 0x42, 0xe4, 0x7d, 0xee, 0xcc, 0xe0, 0x81, 0x42, 0xdf, 0x68, - 0x10, 0xbf, 0x44, 0x5b, 0x1c, 0x86, 0x29, 0xf5, 0x5d, 0x6f, 0x44, 0x28, 0x85, 0xc8, 0x0d, 0x7d, - 0x35, 0x85, 0x8a, 0xb3, 0xa1, 0x81, 0xb7, 0xba, 0xde, 0xf3, 0xf1, 0x3e, 0x5a, 0xcf, 0xb9, 0x09, - 0xe3, 0x32, 0x23, 0x2e, 0x29, 0x62, 0x4d, 0x57, 0xfb, 0x8c, 0xcb, 0x9e, 0x8f, 0x0f, 0xd1, 0x8e, - 0xfe, 0x25, 0xae, 0xe0, 0xde, 0xbc, 0x6b, 0x49, 0x91, 0xb1, 0x06, 0x07, 0xdc, 0x7b, 0x32, 0x3e, - 0x40, 0x78, 0x4e, 0x32, 0x33, 0x5f, 0xd6, 0x29, 0x1e, 0xf9, 0xb9, 0xff, 0x09, 0x32, 0x73, 0xb2, - 0x0c, 0x63, 0x60, 0xa9, 0xfe, 0x0a, 0x49, 0xe2, 0xc4, 0x2c, 0x37, 0x8d, 0x76, 0xc9, 0xf9, 0x5f, - 0xe3, 0x17, 0x1a, 0xbe, 0x98, 0xa1, 0xf8, 0xe8, 0x31, 0xd9, 0x4c, 0x39, 0x82, 0x6c, 0x84, 0xe6, - 0x8a, 0x3a, 0xe9, 0xbf, 0x05, 0xd9, 0x07, 0x05, 0xe1, 0x06, 0xaa, 0xe6, 0x1a, 0x9f, 0x48, 0x62, - 0xae, 0x36, 0x8d, 0x76, 0xcd, 0x41, 0xba, 0x74, 0x46, 0x24, 0xc1, 0x2f, 0x50, 0x3e, 0x27, 0x57, - 0xc0, 0xe7, 0x14, 0xa8, 0x07, 0x66, 0x45, 0xa5, 0xc8, 0x67, 0x35, 0xc8, 0xab, 0xf8, 0x20, 0x9b, - 0xb4, 0xe4, 0x21, 0x08, 0x97, 0x43, 0x4c, 0x42, 0x1a, 0xd2, 0xc0, 0x44, 0x4d, 0xa3, 0xbd, 0xec, - 0x6c, 0xe6, 0x80, 0x33, 0xab, 0x63, 0x13, 0xad, 0xe4, 0x19, 0xcd, 0xaa, 0x72, 0x9b, 0x6d, 0xf1, - 0x3e, 0x5a, 0xa3, 0x8c, 0x6a, 0x6f, 0x72, 0x19, 0x81, 0x59, 0x6b, 0x1a, 0xed, 0x55, 0x67, 0xb1, - 0xd8, 0xf5, 0x6e, 0xee, 0xea, 0xc6, 0xed, 0x5d, 0xdd, 0xf8, 0x7d, 0x57, 0x37, 0xbe, 0xdd, 0xd7, - 0x0b, 0xb7, 0xf7, 0xf5, 0xc2, 0xcf, 0xfb, 0x7a, 0xe1, 0x63, 0x6f, 0xee, 0x2e, 0x0a, 0xc9, 0x09, - 0x0d, 0x20, 0x62, 0x63, 0xe8, 0x8c, 0x81, 0xca, 0x94, 0x83, 0xb0, 0x75, 0x6f, 0x9d, 0x21, 0xe3, - 0xd7, 0x84, 0xfb, 0x9d, 0x38, 0xf4, 0xfd, 0x08, 0xae, 0x09, 0x07, 0x7b, 0x7c, 0x6c, 0xe7, 0x2f, - 0x89, 0xba, 0xb2, 0x97, 0x65, 0xf5, 0x48, 0x1c, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x70, 0xb8, - 0x71, 0x32, 0x60, 0x04, 0x00, 0x00, + 0x4a, 0x68, 0x7d, 0x31, 0x17, 0x3e, 0x46, 0xbb, 0x8c, 0x87, 0x41, 0x48, 0x49, 0xe4, 0x0a, 0xa0, + 0x3e, 0x70, 0x97, 0xf8, 0x3e, 0x07, 0x21, 0xf2, 0x3e, 0x77, 0x66, 0xf0, 0x40, 0xa1, 0x6f, 0x34, + 0x88, 0x5f, 0xa2, 0x2d, 0x0e, 0xc3, 0x94, 0xfa, 0xae, 0x37, 0x22, 0x94, 0x42, 0xe4, 0x86, 0xbe, + 0x9a, 0x42, 0xc5, 0xd9, 0xd0, 0xc0, 0x5b, 0x5d, 0xef, 0xf9, 0x78, 0x1f, 0xad, 0xe7, 0xdc, 0x84, + 0x71, 0x99, 0x11, 0x97, 0x14, 0xb1, 0xa6, 0xab, 0x7d, 0xc6, 0x65, 0xcf, 0xc7, 0x87, 0x68, 0x47, + 0xff, 0x12, 0x57, 0x70, 0x6f, 0xde, 0xb5, 0xa4, 0xc8, 0x58, 0x83, 0x03, 0xee, 0x3d, 0x19, 0x1f, + 0x20, 0x3c, 0x27, 0x99, 0x99, 0x2f, 0xeb, 0x14, 0x8f, 0xfc, 0xdc, 0xff, 0x04, 0x99, 0x39, 0x59, + 0x86, 0x31, 0xb0, 0x54, 0x7f, 0x85, 0x24, 0x71, 0x62, 0x96, 0x9b, 0x46, 0xbb, 0xe4, 0xfc, 0xaf, + 0xf1, 0x0b, 0x0d, 0x5f, 0xcc, 0x50, 0x7c, 0xf4, 0x98, 0x6c, 0xa6, 0x1c, 0x41, 0x36, 0x42, 0x73, + 0x45, 0x9d, 0xf4, 0xdf, 0x82, 0xec, 0x83, 0x82, 0x70, 0x03, 0x55, 0x73, 0x8d, 0x4f, 0x24, 0x31, + 0x57, 0x9b, 0x46, 0xbb, 0xe6, 0x20, 0x5d, 0x3a, 0x23, 0x92, 0xe0, 0x17, 0x28, 0x9f, 0x93, 0x2b, + 0xe0, 0x73, 0x0a, 0xd4, 0x03, 0xb3, 0xa2, 0x52, 0xe4, 0xb3, 0x1a, 0xe4, 0x55, 0x7c, 0x90, 0x4d, + 0x5a, 0xf2, 0x10, 0x84, 0xcb, 0x21, 0x26, 0x21, 0x0d, 0x69, 0x60, 0xa2, 0xa6, 0xd1, 0x5e, 0x76, + 0x36, 0x73, 0xc0, 0x99, 0xd5, 0xb1, 0x89, 0x56, 0xf2, 0x8c, 0x66, 0x55, 0xb9, 0xcd, 0xb6, 0x78, + 0x1f, 0xad, 0x51, 0x46, 0xb5, 0x37, 0xb9, 0x8c, 0xc0, 0xac, 0x35, 0x8d, 0xf6, 0xaa, 0xb3, 0x58, + 0xec, 0x7a, 0x37, 0x77, 0x75, 0xe3, 0xf6, 0xae, 0x6e, 0xfc, 0xbe, 0xab, 0x1b, 0xdf, 0xee, 0xeb, + 0x85, 0xdb, 0xfb, 0x7a, 0xe1, 0xe7, 0x7d, 0xbd, 0xf0, 0xb1, 0x37, 0x77, 0x17, 0x85, 0xe4, 0x84, + 0x06, 0x10, 0xb1, 0x31, 0x74, 0xc6, 0x40, 0x65, 0xca, 0x41, 0xd8, 0xba, 0xb7, 0xce, 0x90, 0xf1, + 0x6b, 0xc2, 0xfd, 0x4e, 0x1c, 0xfa, 0x7e, 0x04, 0xd7, 0x84, 0x83, 0x3d, 0x3e, 0xb6, 0xf3, 0x97, + 0x44, 0x5d, 0xd9, 0xcb, 0xb2, 0x7a, 0x24, 0x5e, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x4f, + 0xf8, 0x79, 0x60, 0x04, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) {