Skip to content

Commit e0bfaa5

Browse files
authored
Merge pull request #1620 from CosmWasm/channel_query
Start rework channel query
2 parents dd22204 + d5fa278 commit e0bfaa5

File tree

5 files changed

+213
-148
lines changed

5 files changed

+213
-148
lines changed

x/wasm/keeper/query_plugin_integration_test.go

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
1111
"github.com/cosmos/gogoproto/proto"
12+
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
1213
"github.com/stretchr/testify/assert"
1314
"github.com/stretchr/testify/require"
1415

@@ -642,6 +643,194 @@ func TestDistributionQuery(t *testing.T) {
642643
}
643644
}
644645

646+
func TestIBCListChannelsQuery(t *testing.T) {
647+
cdc := MakeEncodingConfig(t).Codec
648+
pCtx, keepers := CreateTestInput(t, false, ReflectFeatures, WithMessageEncoders(reflectEncoders(cdc)), WithQueryPlugins(reflectPlugins()))
649+
keeper := keepers.WasmKeeper
650+
nonIbcExample := InstantiateReflectExampleContract(t, pCtx, keepers)
651+
ibcExample := InstantiateReflectExampleContract(t, pCtx, keepers)
652+
// add an ibc port for testing
653+
myIBCPortID := "myValidPortID"
654+
cInfo := keeper.GetContractInfo(pCtx, ibcExample.Contract)
655+
cInfo.IBCPortID = myIBCPortID
656+
keeper.storeContractInfo(pCtx, ibcExample.Contract, cInfo)
657+
// store a random channel to be ignored in queries
658+
unusedChan := channeltypes.Channel{
659+
State: channeltypes.OPEN,
660+
Ordering: channeltypes.UNORDERED,
661+
Counterparty: channeltypes.Counterparty{
662+
PortId: "counterPartyPortID",
663+
ChannelId: "counterPartyChannelID",
664+
},
665+
ConnectionHops: []string{"any"},
666+
Version: "any",
667+
}
668+
keepers.IBCKeeper.ChannelKeeper.SetChannel(pCtx, "nonContractPortID", "channel-99", unusedChan)
669+
670+
// mixed channel examples for testing
671+
myExampleChannels := []channeltypes.Channel{
672+
{
673+
State: channeltypes.OPEN,
674+
Ordering: channeltypes.ORDERED,
675+
Counterparty: channeltypes.Counterparty{
676+
PortId: "counterPartyPortID",
677+
ChannelId: "counterPartyChannelID",
678+
},
679+
ConnectionHops: []string{"one"},
680+
Version: "v1",
681+
},
682+
{
683+
State: channeltypes.INIT,
684+
Ordering: channeltypes.UNORDERED,
685+
Counterparty: channeltypes.Counterparty{
686+
PortId: "foobar",
687+
},
688+
ConnectionHops: []string{"one"},
689+
Version: "initversion",
690+
},
691+
{
692+
State: channeltypes.OPEN,
693+
Ordering: channeltypes.UNORDERED,
694+
Counterparty: channeltypes.Counterparty{
695+
PortId: "otherCounterPartyPortID",
696+
ChannelId: "otherCounterPartyChannelID",
697+
},
698+
ConnectionHops: []string{"other", "second"},
699+
Version: "otherVersion",
700+
},
701+
{
702+
State: channeltypes.CLOSED,
703+
Ordering: channeltypes.ORDERED,
704+
Counterparty: channeltypes.Counterparty{
705+
PortId: "super",
706+
ChannelId: "duper",
707+
},
708+
ConnectionHops: []string{"no-more"},
709+
Version: "closedVersion",
710+
},
711+
}
712+
713+
withChannelsStored := func(portID string, channels ...channeltypes.Channel) func(t *testing.T, ctx sdk.Context) sdk.Context {
714+
return func(t *testing.T, ctx sdk.Context) sdk.Context {
715+
for i, v := range channels {
716+
keepers.IBCKeeper.ChannelKeeper.SetChannel(ctx, portID, fmt.Sprintf("channel-%d", i), v)
717+
}
718+
return ctx
719+
}
720+
}
721+
noopSetup := func(t *testing.T, ctx sdk.Context) sdk.Context { return ctx }
722+
723+
specs := map[string]struct {
724+
setup func(t *testing.T, ctx sdk.Context) sdk.Context
725+
contract sdk.AccAddress
726+
query *wasmvmtypes.IBCQuery
727+
expErr bool
728+
assert func(t *testing.T, d []byte)
729+
}{
730+
"open channels - with query portID empty": {
731+
contract: ibcExample.Contract,
732+
setup: withChannelsStored(myIBCPortID, myExampleChannels...),
733+
query: &wasmvmtypes.IBCQuery{ListChannels: &wasmvmtypes.ListChannelsQuery{}},
734+
assert: func(t *testing.T, d []byte) {
735+
rsp := unmarshalReflect[wasmvmtypes.ListChannelsResponse](t, d)
736+
exp := wasmvmtypes.ListChannelsResponse{Channels: []wasmvmtypes.IBCChannel{
737+
{
738+
Endpoint: wasmvmtypes.IBCEndpoint{PortID: myIBCPortID, ChannelID: "channel-0"},
739+
CounterpartyEndpoint: wasmvmtypes.IBCEndpoint{
740+
PortID: "counterPartyPortID",
741+
ChannelID: "counterPartyChannelID",
742+
},
743+
Order: channeltypes.ORDERED.String(),
744+
Version: "v1",
745+
ConnectionID: "one",
746+
}, {
747+
Endpoint: wasmvmtypes.IBCEndpoint{PortID: myIBCPortID, ChannelID: "channel-2"},
748+
CounterpartyEndpoint: wasmvmtypes.IBCEndpoint{
749+
PortID: "otherCounterPartyPortID",
750+
ChannelID: "otherCounterPartyChannelID",
751+
},
752+
Order: channeltypes.UNORDERED.String(),
753+
Version: "otherVersion",
754+
ConnectionID: "other",
755+
},
756+
}}
757+
assert.Equal(t, exp, rsp)
758+
},
759+
},
760+
"open channels - with query portID passed": {
761+
contract: ibcExample.Contract,
762+
setup: withChannelsStored("OtherPortID", myExampleChannels...),
763+
query: &wasmvmtypes.IBCQuery{ListChannels: &wasmvmtypes.ListChannelsQuery{PortID: "OtherPortID"}},
764+
assert: func(t *testing.T, d []byte) {
765+
rsp := unmarshalReflect[wasmvmtypes.ListChannelsResponse](t, d)
766+
exp := wasmvmtypes.ListChannelsResponse{Channels: []wasmvmtypes.IBCChannel{
767+
{
768+
Endpoint: wasmvmtypes.IBCEndpoint{PortID: "OtherPortID", ChannelID: "channel-0"},
769+
CounterpartyEndpoint: wasmvmtypes.IBCEndpoint{
770+
PortID: "counterPartyPortID",
771+
ChannelID: "counterPartyChannelID",
772+
},
773+
Order: channeltypes.ORDERED.String(),
774+
Version: "v1",
775+
ConnectionID: "one",
776+
}, {
777+
Endpoint: wasmvmtypes.IBCEndpoint{PortID: "OtherPortID", ChannelID: "channel-2"},
778+
CounterpartyEndpoint: wasmvmtypes.IBCEndpoint{
779+
PortID: "otherCounterPartyPortID",
780+
ChannelID: "otherCounterPartyChannelID",
781+
},
782+
Order: channeltypes.UNORDERED.String(),
783+
Version: "otherVersion",
784+
ConnectionID: "other",
785+
},
786+
}}
787+
assert.Equal(t, exp, rsp)
788+
},
789+
},
790+
"non ibc contract - with query portID empty": {
791+
contract: nonIbcExample.Contract,
792+
setup: withChannelsStored(myIBCPortID, myExampleChannels...),
793+
query: &wasmvmtypes.IBCQuery{ListChannels: &wasmvmtypes.ListChannelsQuery{}},
794+
assert: func(t *testing.T, d []byte) {
795+
rsp := unmarshalReflect[wasmvmtypes.ListChannelsResponse](t, d)
796+
assert.Nil(t, rsp.Channels)
797+
},
798+
},
799+
"no matching channels": {
800+
contract: ibcExample.Contract,
801+
setup: noopSetup,
802+
query: &wasmvmtypes.IBCQuery{ListChannels: &wasmvmtypes.ListChannelsQuery{}},
803+
assert: func(t *testing.T, d []byte) {
804+
rsp := unmarshalReflect[wasmvmtypes.ListChannelsResponse](t, d)
805+
assert.Empty(t, rsp.Channels)
806+
},
807+
},
808+
}
809+
for name, spec := range specs {
810+
t.Run(name, func(t *testing.T) {
811+
ctx, _ := pCtx.CacheContext()
812+
ctx = spec.setup(t, ctx)
813+
814+
// when
815+
queryBz := mustMarshal(t, testdata.ReflectQueryMsg{
816+
Chain: &testdata.ChainQuery{
817+
Request: &wasmvmtypes.QueryRequest{IBC: spec.query},
818+
},
819+
})
820+
simpleRes, gotErr := keeper.QuerySmart(ctx, spec.contract, queryBz)
821+
if spec.expErr {
822+
require.Error(t, gotErr)
823+
return
824+
}
825+
// then
826+
require.NoError(t, gotErr)
827+
var rsp testdata.ChainResponse
828+
mustUnmarshal(t, simpleRes, &rsp)
829+
spec.assert(t, rsp.Data)
830+
})
831+
}
832+
}
833+
645834
func unmarshalReflect[T any](t *testing.T, d []byte) T {
646835
var v T
647836
mustUnmarshal(t, d, &v)

x/wasm/keeper/query_plugins.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,18 @@ func IBCQuerier(wasm contractMetaDataSource, channelKeeper types.ChannelKeeper)
249249
}
250250
if request.ListChannels != nil {
251251
portID := request.ListChannels.PortID
252-
channels := make(wasmvmtypes.IBCChannels, 0)
253-
channelKeeper.IterateChannels(ctx, func(ch channeltypes.IdentifiedChannel) bool {
254-
// it must match the port and be in open state
255-
if (portID == "" || portID == ch.PortId) && ch.State == channeltypes.OPEN {
256-
newChan := wasmvmtypes.IBCChannel{
252+
if portID == "" { // then fallback to contract port address
253+
portID = wasm.GetContractInfo(ctx, caller).IBCPortID
254+
}
255+
var channels wasmvmtypes.IBCChannels
256+
if portID != "" { // then return empty list for non ibc contracts; no channels possible
257+
gotChannels := channelKeeper.GetAllChannelsWithPortPrefix(ctx, portID)
258+
channels = make(wasmvmtypes.IBCChannels, 0, len(gotChannels))
259+
for _, ch := range gotChannels {
260+
if ch.State != channeltypes.OPEN {
261+
continue
262+
}
263+
channels = append(channels, wasmvmtypes.IBCChannel{
257264
Endpoint: wasmvmtypes.IBCEndpoint{
258265
PortID: ch.PortId,
259266
ChannelID: ch.ChannelId,
@@ -265,11 +272,9 @@ func IBCQuerier(wasm contractMetaDataSource, channelKeeper types.ChannelKeeper)
265272
Order: ch.Ordering.String(),
266273
Version: ch.Version,
267274
ConnectionID: ch.ConnectionHops[0],
268-
}
269-
channels = append(channels, newChan)
275+
})
270276
}
271-
return false
272-
})
277+
}
273278
res := wasmvmtypes.ListChannelsResponse{
274279
Channels: channels,
275280
}

x/wasm/keeper/query_plugins_test.go

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -40,59 +40,6 @@ import (
4040
)
4141

4242
func TestIBCQuerier(t *testing.T) {
43-
myExampleChannels := []channeltypes.IdentifiedChannel{
44-
// this is returned
45-
{
46-
State: channeltypes.OPEN,
47-
Ordering: channeltypes.ORDERED,
48-
Counterparty: channeltypes.Counterparty{
49-
PortId: "counterPartyPortID",
50-
ChannelId: "counterPartyChannelID",
51-
},
52-
ConnectionHops: []string{"one"},
53-
Version: "v1",
54-
PortId: "myPortID",
55-
ChannelId: "myChannelID",
56-
},
57-
// this is filtered out
58-
{
59-
State: channeltypes.INIT,
60-
Ordering: channeltypes.UNORDERED,
61-
Counterparty: channeltypes.Counterparty{
62-
PortId: "foobar",
63-
},
64-
ConnectionHops: []string{"one"},
65-
Version: "initversion",
66-
PortId: "initPortID",
67-
ChannelId: "initChannelID",
68-
},
69-
// this is returned
70-
{
71-
State: channeltypes.OPEN,
72-
Ordering: channeltypes.UNORDERED,
73-
Counterparty: channeltypes.Counterparty{
74-
PortId: "otherCounterPartyPortID",
75-
ChannelId: "otherCounterPartyChannelID",
76-
},
77-
ConnectionHops: []string{"other", "second"},
78-
Version: "otherVersion",
79-
PortId: "otherPortID",
80-
ChannelId: "otherChannelID",
81-
},
82-
// this is filtered out
83-
{
84-
State: channeltypes.CLOSED,
85-
Ordering: channeltypes.ORDERED,
86-
Counterparty: channeltypes.Counterparty{
87-
PortId: "super",
88-
ChannelId: "duper",
89-
},
90-
ConnectionHops: []string{"no-more"},
91-
Version: "closedVersion",
92-
PortId: "closedPortID",
93-
ChannelId: "closedChannelID",
94-
},
95-
}
9643
specs := map[string]struct {
9744
srcQuery *wasmvmtypes.IBCQuery
9845
wasmKeeper *mockWasmQueryKeeper
@@ -112,82 +59,6 @@ func TestIBCQuerier(t *testing.T) {
11259
channelKeeper: &wasmtesting.MockChannelKeeper{},
11360
expJSONResult: `{"port_id":"myIBCPortID"}`,
11461
},
115-
"query list channels - all": {
116-
srcQuery: &wasmvmtypes.IBCQuery{
117-
ListChannels: &wasmvmtypes.ListChannelsQuery{},
118-
},
119-
channelKeeper: &wasmtesting.MockChannelKeeper{
120-
IterateChannelsFn: wasmtesting.MockChannelKeeperIterator(myExampleChannels),
121-
},
122-
expJSONResult: `{
123-
"channels": [
124-
{
125-
"endpoint": {
126-
"port_id": "myPortID",
127-
"channel_id": "myChannelID"
128-
},
129-
"counterparty_endpoint": {
130-
"port_id": "counterPartyPortID",
131-
"channel_id": "counterPartyChannelID"
132-
},
133-
"order": "ORDER_ORDERED",
134-
"version": "v1",
135-
"connection_id": "one"
136-
},
137-
{
138-
"endpoint": {
139-
"port_id": "otherPortID",
140-
"channel_id": "otherChannelID"
141-
},
142-
"counterparty_endpoint": {
143-
"port_id": "otherCounterPartyPortID",
144-
"channel_id": "otherCounterPartyChannelID"
145-
},
146-
"order": "ORDER_UNORDERED",
147-
"version": "otherVersion",
148-
"connection_id": "other"
149-
}
150-
]
151-
}`,
152-
},
153-
"query list channels - filtered": {
154-
srcQuery: &wasmvmtypes.IBCQuery{
155-
ListChannels: &wasmvmtypes.ListChannelsQuery{
156-
PortID: "otherPortID",
157-
},
158-
},
159-
channelKeeper: &wasmtesting.MockChannelKeeper{
160-
IterateChannelsFn: wasmtesting.MockChannelKeeperIterator(myExampleChannels),
161-
},
162-
expJSONResult: `{
163-
"channels": [
164-
{
165-
"endpoint": {
166-
"port_id": "otherPortID",
167-
"channel_id": "otherChannelID"
168-
},
169-
"counterparty_endpoint": {
170-
"port_id": "otherCounterPartyPortID",
171-
"channel_id": "otherCounterPartyChannelID"
172-
},
173-
"order": "ORDER_UNORDERED",
174-
"version": "otherVersion",
175-
"connection_id": "other"
176-
}
177-
]
178-
}`,
179-
},
180-
"query list channels - filtered empty": {
181-
srcQuery: &wasmvmtypes.IBCQuery{
182-
ListChannels: &wasmvmtypes.ListChannelsQuery{
183-
PortID: "none-existing",
184-
},
185-
},
186-
channelKeeper: &wasmtesting.MockChannelKeeper{
187-
IterateChannelsFn: wasmtesting.MockChannelKeeperIterator(myExampleChannels),
188-
},
189-
expJSONResult: `{"channels": []}`,
190-
},
19162
"query channel": {
19263
srcQuery: &wasmvmtypes.IBCQuery{
19364
Channel: &wasmvmtypes.ChannelQuery{

0 commit comments

Comments
 (0)