Merge pull request #439 from CosmWasm/ibc-query-support

Ibc query support
This commit is contained in:
Ethan Frey
2021-03-09 23:50:13 +01:00
committed by GitHub
5 changed files with 115 additions and 46 deletions

View File

@@ -119,7 +119,7 @@ func NewKeeper(
authZPolicy: DefaultAuthorizationPolicy{},
paramSpace: paramSpace,
}
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, queryRouter, &keeper).Merge(customPlugins)
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, channelKeeper, queryRouter, &keeper).Merge(customPlugins)
for _, o := range opts {
o.apply(&keeper)
}
@@ -269,10 +269,7 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey)
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddress)
// instantiate wasm contract
gas := gasForContract(ctx)
@@ -343,10 +340,7 @@ func (k Keeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller
info := types.NewInfo(caller, coins)
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddress)
gas := gasForContract(ctx)
res, gasUsed, execErr := k.wasmer.Execute(codeInfo.CodeHash, env, info, msg, prefixStore, cosmwasmAPI, querier, gasMeter(ctx), gas)
consumeGas(ctx, gasUsed)
@@ -410,10 +404,7 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller
env := types.NewEnv(ctx, contractAddress)
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddress)
prefixStoreKey := types.GetContractStorePrefix(contractAddress)
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey)
@@ -461,10 +452,7 @@ func (k Keeper) Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte
env := types.NewEnv(ctx, contractAddress)
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddress)
gas := gasForContract(ctx)
res, gasUsed, execErr := k.wasmer.Sudo(codeInfo.CodeHash, env, msg, prefixStore, cosmwasmAPI, querier, gasMeter(ctx), gas)
consumeGas(ctx, gasUsed)
@@ -552,10 +540,7 @@ func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []b
}
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddr)
env := types.NewEnv(ctx, contractAddr)
queryResult, gasUsed, qErr := k.wasmer.Query(codeInfo.CodeHash, env, req, prefixStore, cosmwasmAPI, querier, gasMeter(ctx), gasForContract(ctx))

View File

@@ -3,6 +3,7 @@ package keeper
import (
"encoding/json"
"fmt"
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -18,6 +19,15 @@ import (
type QueryHandler struct {
Ctx sdk.Context
Plugins QueryPlugins
Caller sdk.AccAddress
}
func NewQueryHandler(ctx sdk.Context, plugins QueryPlugins, caller sdk.AccAddress) QueryHandler {
return QueryHandler{
Ctx: ctx,
Plugins: plugins,
Caller: caller,
}
}
// -- interfaces from baseapp - so we can use the GPRQueryRouter --
@@ -51,6 +61,9 @@ func (q QueryHandler) Query(request wasmvmtypes.QueryRequest, gasLimit uint64) (
if request.Custom != nil {
return q.Plugins.Custom(subctx, request.Custom)
}
if request.IBC != nil {
return q.Plugins.IBC(subctx, q.Caller, request.IBC)
}
if request.Staking != nil {
return q.Plugins.Staking(subctx, request.Staking)
}
@@ -72,15 +85,17 @@ type CustomQuerier func(ctx sdk.Context, request json.RawMessage) ([]byte, error
type QueryPlugins struct {
Bank func(ctx sdk.Context, request *wasmvmtypes.BankQuery) ([]byte, error)
Custom CustomQuerier
IBC func(ctx sdk.Context, caller sdk.AccAddress, request *wasmvmtypes.IBCQuery) ([]byte, error)
Staking func(ctx sdk.Context, request *wasmvmtypes.StakingQuery) ([]byte, error)
Stargate func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error)
Wasm func(ctx sdk.Context, request *wasmvmtypes.WasmQuery) ([]byte, error)
}
func DefaultQueryPlugins(bank bankkeeper.ViewKeeper, staking stakingkeeper.Keeper, distKeeper distributionkeeper.Keeper, queryRouter GRPCQueryRouter, wasm *Keeper) QueryPlugins {
func DefaultQueryPlugins(bank bankkeeper.ViewKeeper, staking stakingkeeper.Keeper, distKeeper distributionkeeper.Keeper, channelKeeper types.ChannelKeeper, queryRouter GRPCQueryRouter, wasm *Keeper) QueryPlugins {
return QueryPlugins{
Bank: BankQuerier(bank),
Custom: NoCustomQuerier,
IBC: IBCQuerier(wasm, channelKeeper),
Staking: StakingQuerier(staking, distKeeper),
Stargate: StargateQuerier(queryRouter),
Wasm: WasmQuerier(wasm),
@@ -98,6 +113,9 @@ func (e QueryPlugins) Merge(o *QueryPlugins) QueryPlugins {
if o.Custom != nil {
e.Custom = o.Custom
}
if o.IBC != nil {
e.IBC = o.IBC
}
if o.Staking != nil {
e.Staking = o.Staking
}
@@ -146,6 +164,67 @@ func NoCustomQuerier(sdk.Context, json.RawMessage) ([]byte, error) {
return nil, wasmvmtypes.UnsupportedRequest{Kind: "custom"}
}
func IBCQuerier(wasm *Keeper, channelKeeper types.ChannelKeeper) func(ctx sdk.Context, caller sdk.AccAddress, request *wasmvmtypes.IBCQuery) ([]byte, error) {
return func(ctx sdk.Context, caller sdk.AccAddress, request *wasmvmtypes.IBCQuery) ([]byte, error) {
if request.PortID != nil {
contractInfo := wasm.GetContractInfo(ctx, caller)
res := wasmvmtypes.PortIDResponse{
PortID: contractInfo.IBCPortID,
}
return json.Marshal(res)
}
if request.ListChannels != nil {
portID := request.ListChannels.PortID
var channels wasmvmtypes.IBCEndpoints
channelKeeper.IterateChannels(ctx, func(ch types.IdentifiedChannel) bool {
if portID == "" || portID == ch.PortId {
newChan := wasmvmtypes.IBCEndpoint{
PortID: ch.PortId,
ChannelID: ch.ChannelId,
}
channels = append(channels, newChan)
}
return false
})
res := wasmvmtypes.ListChannelsResponse{
Channels: channels,
}
return json.Marshal(res)
}
if request.Channel != nil {
channelID := request.Channel.ChannelID
portID := request.Channel.PortID
if portID == "" {
contractInfo := wasm.GetContractInfo(ctx, caller)
portID = contractInfo.IBCPortID
}
got, found := channelKeeper.GetChannel(ctx, portID, channelID)
var channel *wasmvmtypes.IBCChannel
if found {
channel = &wasmvmtypes.IBCChannel{
Endpoint: wasmvmtypes.IBCEndpoint{
PortID: portID,
ChannelID: channelID,
},
CounterpartyEndpoint: wasmvmtypes.IBCEndpoint{
PortID: got.Counterparty.PortId,
ChannelID: got.Counterparty.ChannelId,
},
Order: got.Ordering.String(),
Version: got.Version,
CounterpartyVersion: "",
ConnectionID: got.ConnectionHops[0],
}
}
res := wasmvmtypes.ChannelResponse{
Channel: channel,
}
return json.Marshal(res)
}
return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown IBCQuery variant"}
}
}
func StargateQuerier(queryRouter GRPCQueryRouter) func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
return func(ctx sdk.Context, msg *wasmvmtypes.StargateQuery) ([]byte, error) {
route := queryRouter.Route(msg.Path)

View File

@@ -23,10 +23,7 @@ func (k Keeper) OnOpenChannel(
}
env := types.NewEnv(ctx, contractAddr)
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddr)
gas := gasForContract(ctx)
gasUsed, execErr := k.wasmer.IBCChannelOpen(codeInfo.CodeHash, env, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
@@ -56,10 +53,7 @@ func (k Keeper) OnConnectChannel(
}
env := types.NewEnv(ctx, contractAddr)
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddr)
gas := gasForContract(ctx)
res, gasUsed, execErr := k.wasmer.IBCChannelConnect(codeInfo.CodeHash, env, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
@@ -95,10 +89,7 @@ func (k Keeper) OnCloseChannel(
}
params := types.NewEnv(ctx, contractAddr)
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddr)
gas := gasForContract(ctx)
res, gasUsed, execErr := k.wasmer.IBCChannelClose(codeInfo.CodeHash, params, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
@@ -134,10 +125,7 @@ func (k Keeper) OnRecvPacket(
}
env := types.NewEnv(ctx, contractAddr)
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddr)
gas := gasForContract(ctx)
res, gasUsed, execErr := k.wasmer.IBCPacketReceive(codeInfo.CodeHash, env, packet, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
@@ -174,10 +162,7 @@ func (k Keeper) OnAckPacket(
}
env := types.NewEnv(ctx, contractAddr)
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddr)
gas := gasForContract(ctx)
res, gasUsed, execErr := k.wasmer.IBCPacketAck(codeInfo.CodeHash, env, acknowledgement, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
@@ -210,10 +195,7 @@ func (k Keeper) OnTimeoutPacket(
}
env := types.NewEnv(ctx, contractAddr)
querier := QueryHandler{
Ctx: ctx,
Plugins: k.queryPlugins,
}
querier := NewQueryHandler(ctx, k.queryPlugins, contractAddr)
gas := gasForContract(ctx)
res, gasUsed, execErr := k.wasmer.IBCPacketTimeout(codeInfo.CodeHash, env, packet, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)

View File

@@ -12,6 +12,7 @@ type MockChannelKeeper struct {
GetNextSequenceSendFn func(ctx sdk.Context, portID, channelID string) (uint64, bool)
SendPacketFn func(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error
ChanCloseInitFn func(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error
GetAllChannelsFn func(ctx sdk.Context) []channeltypes.IdentifiedChannel
}
func (m *MockChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) {
@@ -21,6 +22,24 @@ func (m *MockChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string)
return m.GetChannelFn(ctx, srcPort, srcChan)
}
func (m *MockChannelKeeper) GetAllChannels(ctx sdk.Context) []channeltypes.IdentifiedChannel {
if m.GetAllChannelsFn == nil {
panic("not supposed to be called!")
}
return m.GetAllChannelsFn(ctx)
}
// Auto-implemented from GetAllChannels data
func (m *MockChannelKeeper) IterateChannels(ctx sdk.Context, cb func(channeltypes.IdentifiedChannel) bool) {
channels := m.GetAllChannels(ctx)
for _, channel := range channels {
stop := cb(channel)
if stop {
break
}
}
}
func (m *MockChannelKeeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) {
if m.GetNextSequenceSendFn == nil {
panic("not supposed to be called!")

View File

@@ -16,8 +16,12 @@ type ChannelKeeper interface {
GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool)
SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error
ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error
GetAllChannels(ctx sdk.Context) (channels []channeltypes.IdentifiedChannel)
IterateChannels(ctx sdk.Context, cb func(channeltypes.IdentifiedChannel) bool)
}
type IdentifiedChannel = channeltypes.IdentifiedChannel
// ClientKeeper defines the expected IBC client keeper
type ClientKeeper interface {
GetClientConsensusState(ctx sdk.Context, clientID string) (connection ibcexported.ConsensusState, found bool)