diff --git a/app/app.go b/app/app.go index 32d633330f..bb32d3c531 100644 --- a/app/app.go +++ b/app/app.go @@ -379,7 +379,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b if len(enabledProposals) != 0 { govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(app.wasmKeeper, enabledProposals)) } - ibcRouter.AddRoute(wasm.ModuleName, wasm.NewIBCHandler(app.wasmKeeper)) + ibcRouter.AddRoute(wasm.ModuleName, wasm.NewIBCHandler(app.wasmKeeper, app.ibcKeeper.ChannelKeeper)) app.ibcKeeper.SetRouter(ibcRouter) app.govKeeper = govkeeper.NewKeeper( diff --git a/x/wasm/alias.go b/x/wasm/alias.go index 50129990a8..59ff271023 100644 --- a/x/wasm/alias.go +++ b/x/wasm/alias.go @@ -1,8 +1,8 @@ // nolint // autogenerated code using github.com/rigelrozanski/multitool // aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmwasm/wasmd/x/wasm/types -// ALIASGEN: github.com/cosmwasm/wasmd/x/wasm/keeper +// ALIASGEN: github.com/Cosmwasm/wasmd/x/wasm/types +// ALIASGEN: github.com/CosmWasm/wasmd/x/wasm/keeper package wasm import ( @@ -76,7 +76,7 @@ var ( CreateTestInput = keeper.CreateTestInput TestHandler = keeper.TestHandler NewWasmProposalHandler = keeper.NewWasmProposalHandler - NewQuerier = keeper.NewQuerier + NewQuerier = keeper.Querier ContractFromPortID = keeper.ContractFromPortID WithWasmEngine = keeper.WithWasmEngine diff --git a/x/wasm/handler.go b/x/wasm/handler.go index a3190cdd2f..34ae264330 100644 --- a/x/wasm/handler.go +++ b/x/wasm/handler.go @@ -12,7 +12,7 @@ import ( ) // NewHandler returns a handler for "bank" type messages. -func NewHandler(k *Keeper) sdk.Handler { +func NewHandler(k types.MsgOpsKeeper) sdk.Handler { msgServer := keeper.NewMsgServerImpl(k) return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index 6529aac67a..f9b45d72df 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -1,7 +1,7 @@ package wasm import ( - wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" + types "github.com/CosmWasm/wasmd/x/wasm/types" wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -15,12 +15,12 @@ import ( var _ porttypes.IBCModule = IBCHandler{} type IBCHandler struct { - keeper Keeper - channelKeeper wasmTypes.ChannelKeeper + keeper types.IBCContractKeeper + channelKeeper types.ChannelKeeper } -func NewIBCHandler(keeper Keeper) IBCHandler { - return IBCHandler{keeper: keeper, channelKeeper: keeper.ChannelKeeper} +func NewIBCHandler(k types.IBCContractKeeper, ck types.ChannelKeeper) IBCHandler { + return IBCHandler{keeper: k, channelKeeper: ck} } // OnChanOpenInit implements the IBCModule interface @@ -265,7 +265,7 @@ func ValidateChannelParams(channelID string) error { return err } if channelSequence > math.MaxUint32 { - return sdkerrors.Wrapf(wasmTypes.ErrMaxIBCChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32) + return sdkerrors.Wrapf(types.ErrMaxIBCChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32) } return nil } diff --git a/x/wasm/keeper/handler_plugin.go b/x/wasm/keeper/handler_plugin.go index cc8c5b3ccd..daf38339eb 100644 --- a/x/wasm/keeper/handler_plugin.go +++ b/x/wasm/keeper/handler_plugin.go @@ -24,7 +24,7 @@ type SDKMessageHandler struct { encoders msgEncoder } -func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource, customEncoders ...*MessageEncoders) messenger { +func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource, customEncoders ...*MessageEncoders) Messenger { encoders := DefaultEncoders(unpacker, portSource) for _, e := range customEncoders { encoders = encoders.Merge(e) @@ -89,11 +89,11 @@ func (h SDKMessageHandler) handleSdkMessage(ctx sdk.Context, contractAddr sdk.Ad // MessageHandlerChain defines a chain of handlers that are called one by one until it can be handled. type MessageHandlerChain struct { - handlers []messenger + handlers []Messenger } -func NewMessageHandlerChain(first messenger, others ...messenger) *MessageHandlerChain { - r := &MessageHandlerChain{handlers: append([]messenger{first}, others...)} +func NewMessageHandlerChain(first Messenger, others ...Messenger) *MessageHandlerChain { + r := &MessageHandlerChain{handlers: append([]Messenger{first}, others...)} for i := range r.handlers { if r.handlers[i] == nil { panic(fmt.Sprintf("handler must not be nil at position : %d", i)) diff --git a/x/wasm/keeper/handler_plugin_test.go b/x/wasm/keeper/handler_plugin_test.go index f8cbe9c8b5..e46989f0f7 100644 --- a/x/wasm/keeper/handler_plugin_test.go +++ b/x/wasm/keeper/handler_plugin_test.go @@ -33,28 +33,28 @@ func TestMessageHandlerChainDispatch(t *testing.T) { myMsg := wasmvmtypes.CosmosMsg{Custom: []byte(`{}`)} specs := map[string]struct { - handlers []messenger + handlers []Messenger expErr *sdkerrors.Error expEvents []sdk.Event }{ "single handler": { - handlers: []messenger{capturingHandler}, + handlers: []Messenger{capturingHandler}, }, "passed to next handler": { - handlers: []messenger{alwaysUnknownMsgHandler, capturingHandler}, + handlers: []Messenger{alwaysUnknownMsgHandler, capturingHandler}, }, "stops iteration when handled": { - handlers: []messenger{capturingHandler, assertNotCalledHandler}, + handlers: []Messenger{capturingHandler, assertNotCalledHandler}, }, "stops iteration on handler error": { - handlers: []messenger{&wasmtesting.MockMessageHandler{ + handlers: []Messenger{&wasmtesting.MockMessageHandler{ DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { return nil, nil, types.ErrInvalidMsg }}, assertNotCalledHandler}, expErr: types.ErrInvalidMsg, }, "return events when handle": { - handlers: []messenger{&wasmtesting.MockMessageHandler{ + handlers: []Messenger{&wasmtesting.MockMessageHandler{ DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { _, data, _ = capturingHandler.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg) return []sdk.Event{sdk.NewEvent("myEvent", sdk.NewAttribute("foo", "bar"))}, data, nil @@ -63,7 +63,7 @@ func TestMessageHandlerChainDispatch(t *testing.T) { expEvents: []sdk.Event{sdk.NewEvent("myEvent", sdk.NewAttribute("foo", "bar"))}, }, "return error when none can handle": { - handlers: []messenger{alwaysUnknownMsgHandler}, + handlers: []Messenger{alwaysUnknownMsgHandler}, expErr: types.ErrUnknownMsg, }, } diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index ef487004bb..3fbb973211 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -51,13 +51,13 @@ type Option interface { } // WasmVMQueryHandler is an extension point for custom query handler implementations -type wasmVMQueryHandler interface { +type WASMVMQueryHandler interface { // HandleQuery executes the requested query HandleQuery(ctx sdk.Context, caller sdk.AccAddress, request wasmvmtypes.QueryRequest) ([]byte, error) } -// messenger is an extension point for custom wasmVM message handling -type messenger interface { +// Messenger is an extension point for custom wasmVM message handling +type Messenger interface { // DispatchMsg encodes the wasmVM message and dispatches it. DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) } @@ -73,12 +73,11 @@ type Keeper struct { cdc codec.Marshaler accountKeeper types.AccountKeeper bank coinTransferrer - ChannelKeeper types.ChannelKeeper portKeeper types.PortKeeper capabilityKeeper types.CapabilityKeeper wasmVM types.WasmerEngine - wasmVMQueryHandler wasmVMQueryHandler - messenger messenger + wasmVMQueryHandler WASMVMQueryHandler + messenger Messenger // queryGasLimit is the max wasmvm gas that can be spent on executing a query with a contract queryGasLimit uint64 authZPolicy AuthorizationPolicy @@ -121,7 +120,6 @@ func NewKeeper( wasmVM: wasmer, accountKeeper: accountKeeper, bank: NewBankCoinTransferrer(bankKeeper), - ChannelKeeper: channelKeeper, portKeeper: portKeeper, capabilityKeeper: capabilityKeeper, messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, cdc, portSource), @@ -647,7 +645,7 @@ func (k Keeper) GetContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) return &contract } -func (k Keeper) containsContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) bool { +func (k Keeper) HasContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) bool { store := ctx.KVStore(k.storeKey) return store.Has(types.GetContractAddressKey(contractAddress)) } @@ -1003,7 +1001,7 @@ func (k Keeper) importContract(ctx sdk.Context, contractAddr sdk.AccAddress, c * if !k.containsCodeInfo(ctx, c.CodeID) { return sdkerrors.Wrapf(types.ErrNotFound, "code id: %d", c.CodeID) } - if k.containsContractInfo(ctx, contractAddr) { + if k.HasContractInfo(ctx, contractAddr) { return sdkerrors.Wrapf(types.ErrDuplicate, "contract: %s", contractAddr) } @@ -1039,9 +1037,23 @@ func gasMeter(ctx sdk.Context) MultipliedGasMeter { // Logger returns a module-specific logger. func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return moduleLogger(ctx) +} + +func moduleLogger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) } +// Querier creates a new grpc querier instance +func Querier(k *Keeper) *grpcQuerier { + return NewGrpcQuerier(k.cdc, k.storeKey, k, k.queryGasLimit) +} + +// QueryGasLimit returns the gas limit for smart queries. +func (k Keeper) QueryGasLimit() sdk.Gas { + return k.queryGasLimit +} + // CoinTransferrer replicates the cosmos-sdk behaviour as in // https://github.com/cosmos/cosmos-sdk/blob/v0.41.4/x/bank/keeper/msg_server.go#L26 type CoinTransferrer struct { diff --git a/x/wasm/keeper/legacy_querier.go b/x/wasm/keeper/legacy_querier.go index ac66f2236f..6dc9debdef 100644 --- a/x/wasm/keeper/legacy_querier.go +++ b/x/wasm/keeper/legacy_querier.go @@ -29,7 +29,7 @@ const ( ) // NewLegacyQuerier creates a new querier -func NewLegacyQuerier(keeper *Keeper) sdk.Querier { +func NewLegacyQuerier(keeper types.ViewKeeper, gasLimit sdk.Gas) sdk.Querier { return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { var ( rsp interface{} @@ -41,18 +41,18 @@ func NewLegacyQuerier(keeper *Keeper) sdk.Querier { if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, err.Error()) } - rsp, err = queryContractInfo(ctx, addr, *keeper) + rsp, err = queryContractInfo(ctx, addr, keeper) case QueryListContractByCode: codeID, err := strconv.ParseUint(path[1], 10, 64) if err != nil { return nil, sdkerrors.Wrapf(types.ErrInvalid, "code id: %s", err.Error()) } - rsp, err = queryContractListByCode(ctx, codeID, *keeper) + rsp, err = queryContractListByCode(ctx, codeID, keeper) case QueryGetContractState: if len(path) < 3 { return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown data query endpoint") } - return queryContractState(ctx, path[1], path[2], req.Data, keeper) + return queryContractState(ctx, path[1], path[2], req.Data, gasLimit, keeper) case QueryGetCode: codeID, err := strconv.ParseUint(path[1], 10, 64) if err != nil { @@ -60,13 +60,13 @@ func NewLegacyQuerier(keeper *Keeper) sdk.Querier { } rsp, err = queryCode(ctx, codeID, keeper) case QueryListCode: - rsp, err = queryCodeList(ctx, *keeper) + rsp, err = queryCodeList(ctx, keeper) case QueryContractHistory: contractAddr, err := sdk.AccAddressFromBech32(path[1]) if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, err.Error()) } - rsp, err = queryContractHistory(ctx, contractAddr, *keeper) + rsp, err = queryContractHistory(ctx, contractAddr, keeper) default: return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown data query endpoint") } @@ -84,7 +84,7 @@ func NewLegacyQuerier(keeper *Keeper) sdk.Querier { } } -func queryContractState(ctx sdk.Context, bech, queryMethod string, data []byte, keeper *Keeper) (json.RawMessage, error) { +func queryContractState(ctx sdk.Context, bech, queryMethod string, data []byte, gasLimit sdk.Gas, keeper types.ViewKeeper) (json.RawMessage, error) { contractAddr, err := sdk.AccAddressFromBech32(bech) if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, bech) @@ -108,7 +108,7 @@ func queryContractState(ctx sdk.Context, bech, queryMethod string, data []byte, return keeper.QueryRaw(ctx, contractAddr, data), nil case QueryMethodContractStateSmart: // we enforce a subjective gas limit on all queries to avoid infinite loops - ctx = ctx.WithGasMeter(sdk.NewGasMeter(keeper.queryGasLimit)) + ctx = ctx.WithGasMeter(sdk.NewGasMeter(gasLimit)) // this returns raw bytes (must be base64-encoded) return keeper.QuerySmart(ctx, contractAddr, data) default: @@ -121,7 +121,7 @@ func queryContractState(ctx sdk.Context, bech, queryMethod string, data []byte, return bz, nil } -func queryCodeList(ctx sdk.Context, keeper Keeper) ([]types.CodeInfoResponse, error) { +func queryCodeList(ctx sdk.Context, keeper types.ViewKeeper) ([]types.CodeInfoResponse, error) { var info []types.CodeInfoResponse keeper.IterateCodeInfos(ctx, func(i uint64, res types.CodeInfo) bool { info = append(info, types.CodeInfoResponse{ @@ -136,7 +136,7 @@ func queryCodeList(ctx sdk.Context, keeper Keeper) ([]types.CodeInfoResponse, er return info, nil } -func queryContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress, keeper Keeper) ([]types.ContractCodeHistoryEntry, error) { +func queryContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress, keeper types.ViewKeeper) ([]types.ContractCodeHistoryEntry, error) { history := keeper.GetContractHistory(ctx, contractAddr) // redact response for i := range history { @@ -145,7 +145,7 @@ func queryContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress, keeper K return history, nil } -func queryContractListByCode(ctx sdk.Context, codeID uint64, keeper Keeper) ([]types.ContractInfoWithAddress, error) { +func queryContractListByCode(ctx sdk.Context, codeID uint64, keeper types.ViewKeeper) ([]types.ContractInfoWithAddress, error) { var contracts []types.ContractInfoWithAddress keeper.IterateContractInfo(ctx, func(addr sdk.AccAddress, info types.ContractInfo) bool { if info.CodeID == codeID { diff --git a/x/wasm/keeper/legacy_querier_test.go b/x/wasm/keeper/legacy_querier_test.go index f056189981..35bade2a1f 100644 --- a/x/wasm/keeper/legacy_querier_test.go +++ b/x/wasm/keeper/legacy_querier_test.go @@ -48,7 +48,9 @@ func TestLegacyQueryContractState(t *testing.T) { keeper.importContractState(ctx, addr, contractModel) // this gets us full error, not redacted sdk.Error - q := NewLegacyQuerier(keeper) + var defaultQueryGasLimit sdk.Gas = 3000000 + q := NewLegacyQuerier(keeper, defaultQueryGasLimit) + specs := map[string]struct { srcPath []string srcReq abci.RequestQuery @@ -195,7 +197,9 @@ func TestLegacyQueryContractListByCodeOrdering(t *testing.T) { } // query and check the results are properly sorted - q := NewLegacyQuerier(keeper) + var defaultQueryGasLimit sdk.Gas = 3000000 + q := NewLegacyQuerier(keeper, defaultQueryGasLimit) + query := []string{QueryListContractByCode, fmt.Sprintf("%d", codeID)} data := abci.RequestQuery{} res, err := q(ctx, query, data) @@ -287,7 +291,9 @@ func TestLegacyQueryContractHistory(t *testing.T) { t.Run(msg, func(t *testing.T) { _, _, myContractAddr := keyPubAddr() keeper.appendToContractHistory(ctx, myContractAddr, spec.srcHistory...) - q := NewLegacyQuerier(keeper) + + var defaultQueryGasLimit sdk.Gas = 3000000 + q := NewLegacyQuerier(keeper, defaultQueryGasLimit) queryContractAddr := spec.srcQueryAddr if queryContractAddr == nil { queryContractAddr = myContractAddr @@ -336,7 +342,8 @@ func TestLegacyQueryCodeList(t *testing.T) { wasmCode), ) } - q := NewLegacyQuerier(keeper) + var defaultQueryGasLimit sdk.Gas = 3000000 + q := NewLegacyQuerier(keeper, defaultQueryGasLimit) // when query := []string{QueryListCode} data := abci.RequestQuery{} diff --git a/x/wasm/keeper/msg_server.go b/x/wasm/keeper/msg_server.go index 47ac36a344..50f5d013e7 100644 --- a/x/wasm/keeper/msg_server.go +++ b/x/wasm/keeper/msg_server.go @@ -11,10 +11,10 @@ import ( var _ types.MsgServer = msgServer{} type msgServer struct { - keeper *Keeper + keeper types.MsgOpsKeeper } -func NewMsgServerImpl(k *Keeper) types.MsgServer { +func NewMsgServerImpl(k types.MsgOpsKeeper) types.MsgServer { return &msgServer{keeper: k} } diff --git a/x/wasm/keeper/options.go b/x/wasm/keeper/options.go index 3e399efad3..2501544d52 100644 --- a/x/wasm/keeper/options.go +++ b/x/wasm/keeper/options.go @@ -21,7 +21,7 @@ func WithWasmEngine(x types.WasmerEngine) Option { // WithMessageHandler is an optional constructor parameter to set a custom handler for wasmVM messages. // This option should not be combined with Option `WithMessageEncoders`. -func WithMessageHandler(x messenger) Option { +func WithMessageHandler(x Messenger) Option { return optsFn(func(k *Keeper) { k.messenger = x }) @@ -29,7 +29,7 @@ func WithMessageHandler(x messenger) Option { // WithQueryHandler is an optional constructor parameter to set custom query handler for wasmVM requests. // This option should not be combined with Option `WithQueryPlugins`. -func WithQueryHandler(x wasmVMQueryHandler) Option { +func WithQueryHandler(x WASMVMQueryHandler) Option { return optsFn(func(k *Keeper) { k.wasmVMQueryHandler = x }) diff --git a/x/wasm/keeper/querier.go b/x/wasm/keeper/querier.go index 1ac865b5b1..7423ee2720 100644 --- a/x/wasm/keeper/querier.go +++ b/x/wasm/keeper/querier.go @@ -3,6 +3,7 @@ package keeper import ( "context" "encoding/binary" + "github.com/cosmos/cosmos-sdk/codec" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "runtime/debug" @@ -17,11 +18,14 @@ import ( var _ types.QueryServer = &grpcQuerier{} type grpcQuerier struct { - keeper *Keeper + cdc codec.Marshaler + storeKey sdk.StoreKey + keeper types.ViewKeeper + queryGasLimit sdk.Gas } -func NewQuerier(keeper *Keeper) grpcQuerier { - return grpcQuerier{keeper: keeper} +func NewGrpcQuerier(cdc codec.Marshaler, storeKey sdk.StoreKey, keeper types.ViewKeeper, queryGasLimit sdk.Gas) *grpcQuerier { + return &grpcQuerier{cdc: cdc, storeKey: storeKey, keeper: keeper, queryGasLimit: queryGasLimit} } func (q grpcQuerier) ContractInfo(c context.Context, req *types.QueryContractInfoRequest) (*types.QueryContractInfoResponse, error) { @@ -32,7 +36,7 @@ func (q grpcQuerier) ContractInfo(c context.Context, req *types.QueryContractInf if err != nil { return nil, err } - rsp, err := queryContractInfo(sdk.UnwrapSDKContext(c), contractAddr, *q.keeper) + rsp, err := queryContractInfo(sdk.UnwrapSDKContext(c), contractAddr, q.keeper) switch { case err != nil: return nil, err @@ -57,11 +61,11 @@ func (q grpcQuerier) ContractHistory(c context.Context, req *types.QueryContract ctx := sdk.UnwrapSDKContext(c) r := make([]types.ContractCodeHistoryEntry, 0) - prefixStore := prefix.NewStore(ctx.KVStore(q.keeper.storeKey), types.GetContractCodeHistoryElementPrefix(contractAddr)) + prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.GetContractCodeHistoryElementPrefix(contractAddr)) pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { if accumulate { var e types.ContractCodeHistoryEntry - if err := q.keeper.cdc.UnmarshalBinaryBare(value, &e); err != nil { + if err := q.cdc.UnmarshalBinaryBare(value, &e); err != nil { return false, err } e.Updated = nil // redact @@ -88,7 +92,7 @@ func (q grpcQuerier) ContractsByCode(c context.Context, req *types.QueryContract ctx := sdk.UnwrapSDKContext(c) r := make([]types.ContractInfoWithAddress, 0) - prefixStore := prefix.NewStore(ctx.KVStore(q.keeper.storeKey), types.GetContractByCodeIDSecondaryIndexPrefix(req.CodeId)) + prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.GetContractByCodeIDSecondaryIndexPrefix(req.CodeId)) pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { var contractAddr sdk.AccAddress = key[types.AbsoluteTxPositionLen:] c := q.keeper.GetContractInfo(ctx, contractAddr) @@ -122,12 +126,12 @@ func (q grpcQuerier) AllContractState(c context.Context, req *types.QueryAllCont return nil, err } ctx := sdk.UnwrapSDKContext(c) - if !q.keeper.containsContractInfo(ctx, contractAddr) { + if !q.keeper.HasContractInfo(ctx, contractAddr) { return nil, types.ErrNotFound } r := make([]types.Model, 0) - prefixStore := prefix.NewStore(ctx.KVStore(q.keeper.storeKey), types.GetContractStorePrefix(contractAddr)) + prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.GetContractStorePrefix(contractAddr)) pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { if accumulate { r = append(r, types.Model{ @@ -157,7 +161,7 @@ func (q grpcQuerier) RawContractState(c context.Context, req *types.QueryRawCont return nil, err } - if !q.keeper.containsContractInfo(ctx, contractAddr) { + if !q.keeper.HasContractInfo(ctx, contractAddr) { return nil, types.ErrNotFound } rsp := q.keeper.QueryRaw(ctx, contractAddr, req.QueryData) @@ -172,7 +176,7 @@ func (q grpcQuerier) SmartContractState(c context.Context, req *types.QuerySmart if err != nil { return nil, err } - ctx := sdk.UnwrapSDKContext(c).WithGasMeter(sdk.NewGasMeter(q.keeper.queryGasLimit)) + ctx := sdk.UnwrapSDKContext(c).WithGasMeter(sdk.NewGasMeter(q.queryGasLimit)) // recover from out-of-gas panic defer func() { if r := recover(); r != nil { @@ -186,7 +190,7 @@ func (q grpcQuerier) SmartContractState(c context.Context, req *types.QuerySmart err = sdkerrors.ErrPanic } rsp = nil - q.keeper.Logger(ctx). + moduleLogger(ctx). Debug("smart query contract", "error", "recovering panic", "contract-address", req.Address, @@ -231,11 +235,11 @@ func (q grpcQuerier) Codes(c context.Context, req *types.QueryCodesRequest) (*ty } ctx := sdk.UnwrapSDKContext(c) r := make([]types.CodeInfoResponse, 0) - prefixStore := prefix.NewStore(ctx.KVStore(q.keeper.storeKey), types.CodeKeyPrefix) + prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.CodeKeyPrefix) pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { if accumulate { var c types.CodeInfo - if err := q.keeper.cdc.UnmarshalBinaryBare(value, &c); err != nil { + if err := q.cdc.UnmarshalBinaryBare(value, &c); err != nil { return false, err } r = append(r, types.CodeInfoResponse{ @@ -254,7 +258,7 @@ func (q grpcQuerier) Codes(c context.Context, req *types.QueryCodesRequest) (*ty return &types.QueryCodesResponse{CodeInfos: r, Pagination: pageRes}, nil } -func queryContractInfo(ctx sdk.Context, addr sdk.AccAddress, keeper Keeper) (*types.ContractInfoWithAddress, error) { +func queryContractInfo(ctx sdk.Context, addr sdk.AccAddress, keeper types.ViewKeeper) (*types.ContractInfoWithAddress, error) { info := keeper.GetContractInfo(ctx, addr) if info == nil { return nil, types.ErrNotFound @@ -267,7 +271,7 @@ func queryContractInfo(ctx sdk.Context, addr sdk.AccAddress, keeper Keeper) (*ty }, nil } -func queryCode(ctx sdk.Context, codeID uint64, keeper *Keeper) (*types.QueryCodeResponse, error) { +func queryCode(ctx sdk.Context, codeID uint64, keeper types.ViewKeeper) (*types.QueryCodeResponse, error) { if codeID == 0 { return nil, nil } diff --git a/x/wasm/keeper/querier_test.go b/x/wasm/keeper/querier_test.go index 1c9c5e2064..8f501bbb8c 100644 --- a/x/wasm/keeper/querier_test.go +++ b/x/wasm/keeper/querier_test.go @@ -31,7 +31,7 @@ func TestQueryAllContractState(t *testing.T) { } require.NoError(t, keeper.importContractState(ctx, contractAddr, contractModel)) - q := NewQuerier(keeper) + q := Querier(keeper) specs := map[string]struct { srcQuery *types.QueryAllContractStateRequest expModelContains []types.Model @@ -113,7 +113,7 @@ func TestQuerySmartContractState(t *testing.T) { exampleContract := InstantiateHackatomExampleContract(t, ctx, keepers) contractAddr := exampleContract.Contract.String() - q := NewQuerier(keeper) + q := Querier(keeper) specs := map[string]struct { srcAddr sdk.AccAddress srcQuery *types.QuerySmartContractStateRequest @@ -183,7 +183,7 @@ func TestQuerySmartContractPanics(t *testing.T) { return nil, 0, nil }} // when - q := NewQuerier(keepers.WasmKeeper) + q := Querier(keepers.WasmKeeper) got, err := q.SmartContractState(sdk.WrapSDKContext(ctx), &types.QuerySmartContractStateRequest{ Address: contractAddr.String(), }) @@ -205,7 +205,7 @@ func TestQueryRawContractState(t *testing.T) { } require.NoError(t, keeper.importContractState(ctx, exampleContract.Contract, contractModel)) - q := NewQuerier(keeper) + q := Querier(keeper) specs := map[string]struct { srcQuery *types.QueryRawContractStateRequest expData []byte @@ -293,7 +293,7 @@ func TestQueryContractListByCodeOrdering(t *testing.T) { } // query and check the results are properly sorted - q := NewQuerier(keeper) + q := Querier(keeper) res, err := q.ContractsByCode(sdk.WrapSDKContext(ctx), &types.QueryContractsByCodeRequest{CodeId: codeID}) require.NoError(t, err) @@ -434,7 +434,7 @@ func TestQueryContractHistory(t *testing.T) { keeper.appendToContractHistory(xCtx, cAddr, spec.srcHistory...) // when - q := NewQuerier(keeper) + q := Querier(keeper) got, err := q.ContractHistory(sdk.WrapSDKContext(xCtx), &spec.req) // then @@ -509,7 +509,7 @@ func TestQueryCodeList(t *testing.T) { ) } // when - q := NewQuerier(keeper) + q := Querier(keeper) got, err := q.Codes(sdk.WrapSDKContext(xCtx), &spec.req) // then diff --git a/x/wasm/keeper/query_plugins.go b/x/wasm/keeper/query_plugins.go index b1f038359e..f469fdc266 100644 --- a/x/wasm/keeper/query_plugins.go +++ b/x/wasm/keeper/query_plugins.go @@ -16,11 +16,11 @@ import ( type QueryHandler struct { Ctx sdk.Context - Plugins wasmVMQueryHandler + Plugins WASMVMQueryHandler Caller sdk.AccAddress } -func NewQueryHandler(ctx sdk.Context, vmQueryHandler wasmVMQueryHandler, caller sdk.AccAddress) QueryHandler { +func NewQueryHandler(ctx sdk.Context, vmQueryHandler WASMVMQueryHandler, caller sdk.AccAddress) QueryHandler { return QueryHandler{ Ctx: ctx, Plugins: vmQueryHandler, diff --git a/x/wasm/keeper/recurse_test.go b/x/wasm/keeper/recurse_test.go index 92788ae436..b0f45c384b 100644 --- a/x/wasm/keeper/recurse_test.go +++ b/x/wasm/keeper/recurse_test.go @@ -189,9 +189,6 @@ func TestGasOnExternalQuery(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { - // set the external gas limit (normally from config file) - keeper.queryGasLimit = tc.gasLimit - recurse := tc.msg recurse.Contract = contractAddr msg := buildRecurseQuery(t, recurse) @@ -202,12 +199,12 @@ func TestGasOnExternalQuery(t *testing.T) { if tc.expectPanic { require.Panics(t, func() { // this should run out of gas - _, err := NewLegacyQuerier(keeper)(ctx, path, req) + _, err := NewLegacyQuerier(keeper, tc.gasLimit)(ctx, path, req) t.Logf("%v", err) }) } else { // otherwise, make sure we get a good success - _, err := NewLegacyQuerier(keeper)(ctx, path, req) + _, err := NewLegacyQuerier(keeper, tc.gasLimit)(ctx, path, req) require.NoError(t, err) } }) diff --git a/x/wasm/keeper/relay_test.go b/x/wasm/keeper/relay_test.go index 330e948112..889792b79e 100644 --- a/x/wasm/keeper/relay_test.go +++ b/x/wasm/keeper/relay_test.go @@ -82,7 +82,7 @@ func TestOnConnectChannel(t *testing.T) { contractGas sdk.Gas contractResp *wasmvmtypes.IBCBasicResponse contractErr error - overwriteMessenger messenger + overwriteMessenger Messenger expErr bool expContractEventAttrs int expNoEvents bool @@ -192,7 +192,7 @@ func TestOnCloseChannel(t *testing.T) { contractGas sdk.Gas contractResp *wasmvmtypes.IBCBasicResponse contractErr error - overwriteMessenger messenger + overwriteMessenger Messenger expErr bool expContractEventAttrs int expNoEvents bool @@ -302,7 +302,7 @@ func TestOnRecvPacket(t *testing.T) { contractGas sdk.Gas contractResp *wasmvmtypes.IBCReceiveResponse contractErr error - overwriteMessenger messenger + overwriteMessenger Messenger expErr bool expContractEventAttrs int expNoEvents bool @@ -427,7 +427,7 @@ func TestOnAckPacket(t *testing.T) { contractGas sdk.Gas contractResp *wasmvmtypes.IBCBasicResponse contractErr error - overwriteMessenger messenger + overwriteMessenger Messenger expErr bool expContractEventAttrs int expNoEvents bool @@ -538,7 +538,7 @@ func TestOnTimeoutPacket(t *testing.T) { contractGas sdk.Gas contractResp *wasmvmtypes.IBCBasicResponse contractErr error - overwriteMessenger messenger + overwriteMessenger Messenger expErr bool expContractEventAttrs int expNoEvents bool diff --git a/x/wasm/module.go b/x/wasm/module.go index 4a36fb23be..102c69165f 100644 --- a/x/wasm/module.go +++ b/x/wasm/module.go @@ -116,7 +116,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { } func (am AppModule) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier { - return keeper.NewLegacyQuerier(am.keeper) + return keeper.NewLegacyQuerier(am.keeper, am.keeper.QueryGasLimit()) } // RegisterInvariants registers the wasm module invariants. diff --git a/x/wasm/types/events.go b/x/wasm/types/events.go index 2f48e5847c..2ca36b9a72 100644 --- a/x/wasm/types/events.go +++ b/x/wasm/types/events.go @@ -7,6 +7,5 @@ const ( const ( // event attributes AttributeKeyContract = "contract_address" AttributeKeyCodeID = "code_id" - AttributeKeyCodeIDs = "code_ids" AttributeKeySigner = "signer" ) diff --git a/x/wasm/types/exported_keepers.go b/x/wasm/types/exported_keepers.go new file mode 100644 index 0000000000..348ca29a90 --- /dev/null +++ b/x/wasm/types/exported_keepers.go @@ -0,0 +1,76 @@ +package types + +import ( + types2 "github.com/CosmWasm/wasmvm/types" + "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" +) + +// ViewKeeper provides read only operations +type ViewKeeper interface { + GetContractHistory(ctx types.Context, contractAddr types.AccAddress) []ContractCodeHistoryEntry + QuerySmart(ctx types.Context, contractAddr types.AccAddress, req []byte) ([]byte, error) + QueryRaw(ctx types.Context, contractAddress types.AccAddress, key []byte) []byte + GetContractInfo(ctx types.Context, contractAddress types.AccAddress) *ContractInfo + IterateContractInfo(ctx types.Context, cb func(types.AccAddress, ContractInfo) bool) + GetContractState(ctx types.Context, contractAddress types.AccAddress) types.Iterator + GetCodeInfo(ctx types.Context, codeID uint64) *CodeInfo + IterateCodeInfos(ctx types.Context, cb func(uint64, CodeInfo) bool) + GetByteCode(ctx types.Context, codeID uint64) ([]byte, error) + IsPinnedCode(ctx types.Context, codeID uint64) bool + HasContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) bool +} + +// MsgOpsKeeper contains mutable operations that are triggered by messages normally +type MsgOpsKeeper interface { + Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, source string, builder string, instantiateAccess *AccessConfig) (codeID uint64, err error) + Instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins) (sdk.AccAddress, []byte, error) + Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) (*sdk.Result, error) + Migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newCodeID uint64, msg []byte) (*sdk.Result, error) + UpdateContractAdmin(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newAdmin sdk.AccAddress) error + + // ClearContractAdmin sets the admin value on the ContractInfo to nil, to disable further migrations/ updates. + ClearContractAdmin(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress) error + PinCode(ctx sdk.Context, codeID uint64) error + UnpinCode(ctx sdk.Context, codeID uint64) error +} + +// IBCContractKeeper IBC lifecycle event handler +type IBCContractKeeper interface { + OnOpenChannel( + ctx sdk.Context, + contractAddr sdk.AccAddress, + channel types2.IBCChannel, + ) error + OnConnectChannel( + ctx sdk.Context, + contractAddr sdk.AccAddress, + channel types2.IBCChannel, + ) error + OnCloseChannel( + ctx sdk.Context, + contractAddr sdk.AccAddress, + channel types2.IBCChannel, + ) error + OnRecvPacket( + ctx sdk.Context, + contractAddr sdk.AccAddress, + packet types2.IBCPacket, + ) ([]byte, error) + OnAckPacket( + ctx sdk.Context, + contractAddr sdk.AccAddress, + acknowledgement types2.IBCAcknowledgement, + ) error + OnTimeoutPacket( + ctx sdk.Context, + contractAddr sdk.AccAddress, + packet types2.IBCPacket, + ) error + // ClaimCapability allows the transfer module to claim a capability + //that IBC module passes to it + ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error + // AuthenticateCapability wraps the scopedKeeper's AuthenticateCapability function + AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool +} diff --git a/x/wasm/types/keys.go b/x/wasm/types/keys.go index e0415ca0d4..ff9bcb68a8 100644 --- a/x/wasm/types/keys.go +++ b/x/wasm/types/keys.go @@ -14,10 +14,10 @@ const ( // TStoreKey is the string transient store representation TStoreKey = "transient_" + ModuleName - // QuerierRoute is the querier route for the staking module + // QuerierRoute is the querier route for the wasm module QuerierRoute = ModuleName - // RouterKey is the msg router key for the staking module + // RouterKey is the msg router key for the wasm module RouterKey = ModuleName )