Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stargate msg and query #435

Merged
merged 7 commits into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,14 +346,12 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b
)
app.evidenceKeeper = *evidenceKeeper

// just re-use the full router - do we want to limit this more?
var wasmRouter = bApp.Router()
wasmDir := filepath.Join(homePath, "wasm")

wasmConfig, err := wasm.ReadWasmConfig(appOpts)
if err != nil {
panic("error while reading wasm config: " + err.Error())
}

// The last arguments can contain custom message handlers, and custom query handlers,
// if we want to allow any custom callbacks
supportedFeatures := "staking,stargate"
Expand All @@ -368,7 +366,8 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b
app.ibcKeeper.ChannelKeeper,
&app.ibcKeeper.PortKeeper,
scopedWasmKeeper,
wasmRouter,
app.Router(),
app.GRPCQueryRouter(),
wasmDir,
wasmConfig,
supportedFeatures,
Expand Down
2 changes: 1 addition & 1 deletion x/wasm/internal/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ func setupKeeper(t *testing.T) (*Keeper, sdk.Context, []sdk.StoreKey) {
wasmConfig := wasmTypes.DefaultWasmConfig()
pk := paramskeeper.NewKeeper(encodingConfig.Marshaler, encodingConfig.Amino, keyParams, tkeyParams)

srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures, nil, nil)
srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures, nil, nil)
return &srcKeeper, ctx, []sdk.StoreKey{keyWasm, keyParams}
}

Expand Down
63 changes: 45 additions & 18 deletions x/wasm/internal/keeper/handler_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package keeper

import (
"encoding/json"
"fmt"
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
Expand All @@ -20,8 +22,8 @@ type DefaultMessageHandler struct {
encoders MessageEncoders
}

func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, customEncoders *MessageEncoders) DefaultMessageHandler {
encoders := DefaultEncoders(channelKeeper, capabilityKeeper).Merge(customEncoders)
func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, customEncoders *MessageEncoders) DefaultMessageHandler {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good use of the minimal interface

encoders := DefaultEncoders(channelKeeper, capabilityKeeper, unpacker).Merge(customEncoders)
return DefaultMessageHandler{
router: router,
encoders: encoders,
Expand All @@ -31,24 +33,27 @@ func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeep
type BankEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.BankMsg) ([]sdk.Msg, error)
type CustomEncoder func(sender sdk.AccAddress, msg json.RawMessage) ([]sdk.Msg, error)
type StakingEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.StakingMsg) ([]sdk.Msg, error)
type StargateEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.StargateMsg) ([]sdk.Msg, error)
type WasmEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]sdk.Msg, error)
type IBCEncoder func(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]sdk.Msg, error)

type MessageEncoders struct {
Bank BankEncoder
Custom CustomEncoder
Staking StakingEncoder
Wasm WasmEncoder
IBC IBCEncoder
Bank BankEncoder
Custom CustomEncoder
IBC IBCEncoder
Staking StakingEncoder
Stargate StargateEncoder
Wasm WasmEncoder
}

func DefaultEncoders(channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper) MessageEncoders {
func DefaultEncoders(channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker) MessageEncoders {
return MessageEncoders{
Bank: EncodeBankMsg,
Custom: NoCustomMsg,
Staking: EncodeStakingMsg,
Wasm: EncodeWasmMsg,
IBC: EncodeIBCMsg(channelKeeper, capabilityKeeper),
Bank: EncodeBankMsg,
Custom: NoCustomMsg,
IBC: EncodeIBCMsg(channelKeeper, capabilityKeeper),
Staking: EncodeStakingMsg,
Stargate: EncodeStargateMsg(unpacker),
Wasm: EncodeWasmMsg,
}
}

Expand All @@ -62,15 +67,18 @@ func (e MessageEncoders) Merge(o *MessageEncoders) MessageEncoders {
if o.Custom != nil {
e.Custom = o.Custom
}
if o.IBC != nil {
e.IBC = o.IBC
}
if o.Staking != nil {
e.Staking = o.Staking
}
if o.Stargate != nil {
e.Stargate = o.Stargate
}
if o.Wasm != nil {
e.Wasm = o.Wasm
}
if o.IBC != nil {
e.IBC = o.IBC
}
return e
}

Expand All @@ -80,12 +88,14 @@ func (e MessageEncoders) Encode(ctx sdk.Context, contractAddr sdk.AccAddress, co
return e.Bank(contractAddr, msg.Bank)
case msg.Custom != nil:
return e.Custom(contractAddr, msg.Custom)
case msg.IBC != nil:
return e.IBC(ctx, contractAddr, contractIBCPortID, msg.IBC)
case msg.Staking != nil:
return e.Staking(contractAddr, msg.Staking)
case msg.Stargate != nil:
return e.Stargate(contractAddr, msg.Stargate)
case msg.Wasm != nil:
return e.Wasm(contractAddr, msg.Wasm)
case msg.IBC != nil:
return e.IBC(ctx, contractAddr, contractIBCPortID, msg.IBC)
}
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Unknown variant of Wasm")
}
Expand Down Expand Up @@ -170,6 +180,23 @@ func EncodeStakingMsg(sender sdk.AccAddress, msg *wasmvmtypes.StakingMsg) ([]sdk
}
}

func EncodeStargateMsg(unpacker codectypes.AnyUnpacker) StargateEncoder {
return func(sender sdk.AccAddress, msg *wasmvmtypes.StargateMsg) ([]sdk.Msg, error) {
any := codectypes.Any{
TypeUrl: msg.TypeURL,
Value: msg.Value,
}
var sdkMsg sdk.Msg
if err := unpacker.UnpackAny(&any, &sdkMsg); err != nil {
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, fmt.Sprintf("Cannot unpack proto message with type URL: %s", msg.TypeURL))
}
if err := codectypes.UnpackInterfaces(sdkMsg, unpacker); err != nil {
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, fmt.Sprintf("UnpackInterfaces inside msg: %s", err))
}
return []sdk.Msg{sdkMsg}, nil
alpe marked this conversation as resolved.
Show resolved Hide resolved
}
}

func EncodeWasmMsg(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]sdk.Msg, error) {
switch {
case msg.Execute != nil:
Expand Down
36 changes: 35 additions & 1 deletion x/wasm/internal/keeper/handler_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported"
"github.com/golang/protobuf/proto"
"testing"

"github.com/CosmWasm/wasmd/x/wasm/internal/types"
Expand All @@ -32,6 +33,17 @@ func TestEncoding(t *testing.T) {

jsonMsg := json.RawMessage(`{"foo": 123}`)

bankMsg := &banktypes.MsgSend{
FromAddress: addr2.String(),
ToAddress: addr1.String(),
Amount: sdk.Coins{
sdk.NewInt64Coin("uatom", 12345),
sdk.NewInt64Coin("utgd", 54321),
},
}
bankMsgBin, err := proto.Marshal(bankMsg)
require.NoError(t, err)

cases := map[string]struct {
sender sdk.AccAddress
srcMsg wasmvmtypes.CosmosMsg
Expand Down Expand Up @@ -276,6 +288,27 @@ func TestEncoding(t *testing.T) {
},
},
},
// TODO: alpe? can you add an example with sub-interfaces (where the UnpackInterfaces call would be needed)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure how to create such a case. (I also think we only have bank, staking, and distribution registered here in the tests).

If you could add such a test to trigger this that would be great. Or if it is a pain, please open up an issue on it and explain more or less what is needed. I can put that down lower on the priority list

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found Any types in sdk (master).

  • MsgGrantAuthorizationRequest
  • MsgGrantFeeAllowance
  • MsgSubmitProposal
  • MsgCreateValidator
    I guess MsgSubmitProposal would be a good candidate. I can add a test.

"stargate encoded bank msg": {
sender: addr2,
srcMsg: wasmvmtypes.CosmosMsg{
Stargate: &wasmvmtypes.StargateMsg{
TypeURL: "/cosmos.bank.v1beta1.MsgSend",
Value: bankMsgBin,
},
},
output: []sdk.Msg{bankMsg},
},
"stargate encoded invalid typeUrl": {
sender: addr2,
srcMsg: wasmvmtypes.CosmosMsg{
Stargate: &wasmvmtypes.StargateMsg{
TypeURL: "/cosmos.bank.v2.MsgSend",
Value: bankMsgBin,
},
},
isError: true,
},
"IBC transfer with block timeout": {
sender: addr1,
srcIBCPort: "myIBCPort",
Expand Down Expand Up @@ -355,7 +388,8 @@ func TestEncoding(t *testing.T) {
},
},
}
encoder := DefaultEncoders(nil, nil)
encodingConfig := MakeEncodingConfig(t)
encoder := DefaultEncoders(nil, nil, encodingConfig.Marshaler)
for name, tc := range cases {
tc := tc
t.Run(name, func(t *testing.T) {
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/internal/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func NewKeeper(
portKeeper types.PortKeeper,
capabilityKeeper types.CapabilityKeeper,
router sdk.Router,
queryRouter GRPCQueryRouter,
homeDir string,
wasmConfig types.WasmConfig,
supportedFeatures string,
Expand All @@ -105,7 +106,6 @@ func NewKeeper(
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
}

messageEncoders := DefaultEncoders(channelKeeper, capabilityKeeper).Merge(customEncoders)
keeper := Keeper{
storeKey: storeKey,
cdc: cdc,
Expand All @@ -115,12 +115,12 @@ func NewKeeper(
ChannelKeeper: channelKeeper,
portKeeper: portKeeper,
capabilityKeeper: capabilityKeeper,
messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, &messageEncoders),
messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, cdc, customEncoders),
queryGasLimit: wasmConfig.SmartQueryGasLimit,
authZPolicy: DefaultAuthorizationPolicy{},
paramSpace: paramSpace,
}
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, &keeper).Merge(customPlugins)
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, queryRouter, &keeper).Merge(customPlugins)
for _, o := range opts {
o.apply(&keeper)
}
Expand Down
1 change: 1 addition & 0 deletions x/wasm/internal/keeper/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func TestConstructorOptions(t *testing.T) {
nil,
nil,
nil,
nil,
"tempDir",
types.DefaultWasmConfig(),
SupportedFeatures,
Expand Down
58 changes: 49 additions & 9 deletions x/wasm/internal/keeper/query_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"encoding/json"
"fmt"

wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -11,13 +12,26 @@ import (
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
abci "github.com/tendermint/tendermint/abci/types"
)

type QueryHandler struct {
Ctx sdk.Context
Plugins QueryPlugins
}

// -- interfaces from baseapp - so we can use the GPRQueryRouter --

// GRPCQueryHandler defines a function type which handles ABCI Query requests
// using gRPC
type GRPCQueryHandler = func(ctx sdk.Context, req abci.RequestQuery) (abci.ResponseQuery, error)

type GRPCQueryRouter interface {
Route(path string) GRPCQueryHandler
}

// -- end baseapp interfaces --

var _ wasmvmtypes.Querier = QueryHandler{}

func (q QueryHandler) Query(request wasmvmtypes.QueryRequest, gasLimit uint64) ([]byte, error) {
Expand All @@ -40,6 +54,9 @@ func (q QueryHandler) Query(request wasmvmtypes.QueryRequest, gasLimit uint64) (
if request.Staking != nil {
return q.Plugins.Staking(subctx, request.Staking)
}
if request.Stargate != nil {
return q.Plugins.Stargate(subctx, request.Stargate)
}
if request.Wasm != nil {
return q.Plugins.Wasm(subctx, request.Wasm)
}
Expand All @@ -53,18 +70,20 @@ func (q QueryHandler) GasConsumed() uint64 {
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
Staking func(ctx sdk.Context, request *wasmvmtypes.StakingQuery) ([]byte, error)
Wasm func(ctx sdk.Context, request *wasmvmtypes.WasmQuery) ([]byte, error)
Bank func(ctx sdk.Context, request *wasmvmtypes.BankQuery) ([]byte, error)
Custom CustomQuerier
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, wasm *Keeper) QueryPlugins {
func DefaultQueryPlugins(bank bankkeeper.ViewKeeper, staking stakingkeeper.Keeper, distKeeper distributionkeeper.Keeper, queryRouter GRPCQueryRouter, wasm *Keeper) QueryPlugins {
return QueryPlugins{
Bank: BankQuerier(bank),
Custom: NoCustomQuerier,
Staking: StakingQuerier(staking, distKeeper),
Wasm: WasmQuerier(wasm),
Bank: BankQuerier(bank),
Custom: NoCustomQuerier,
Staking: StakingQuerier(staking, distKeeper),
Stargate: StargateQuerier(queryRouter),
Wasm: WasmQuerier(wasm),
}
}

Expand All @@ -82,6 +101,9 @@ func (e QueryPlugins) Merge(o *QueryPlugins) QueryPlugins {
if o.Staking != nil {
e.Staking = o.Staking
}
if o.Stargate != nil {
e.Stargate = o.Stargate
}
if o.Wasm != nil {
e.Wasm = o.Wasm
}
Expand Down Expand Up @@ -124,6 +146,24 @@ func NoCustomQuerier(sdk.Context, json.RawMessage) ([]byte, error) {
return nil, wasmvmtypes.UnsupportedRequest{Kind: "custom"}
}

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)
if route == nil {
return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("No route to query '%s'", msg.Path)}
}
req := abci.RequestQuery{
Data: msg.Data,
Path: msg.Path,
}
res, err := route(ctx, req)
if err != nil {
return nil, err
}
return res.Value, nil
}
}

func StakingQuerier(keeper stakingkeeper.Keeper, distKeeper distributionkeeper.Keeper) func(ctx sdk.Context, request *wasmvmtypes.StakingQuery) ([]byte, error) {
return func(ctx sdk.Context, request *wasmvmtypes.StakingQuery) ([]byte, error) {
if request.BondedDenom != nil {
Expand Down
Loading