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

Refactor to GRPC message server #366

Merged
merged 7 commits into from
Jan 8, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
369 changes: 236 additions & 133 deletions doc/proto.md

Large diffs are not rendered by default.

61 changes: 34 additions & 27 deletions x/wasm/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,38 @@ var (
)

type (
ProposalType = types.ProposalType
GenesisState = types.GenesisState
Code = types.Code
Contract = types.Contract
MsgStoreCode = types.MsgStoreCode
MsgInstantiateContract = types.MsgInstantiateContract
MsgExecuteContract = types.MsgExecuteContract
MsgMigrateContract = types.MsgMigrateContract
MsgUpdateAdmin = types.MsgUpdateAdmin
MsgClearAdmin = types.MsgClearAdmin
Model = types.Model
CodeInfo = types.CodeInfo
ContractInfo = types.ContractInfo
CreatedAt = types.AbsoluteTxPosition
Config = types.WasmConfig
ContractInfoWithAddress = types.ContractInfoWithAddress
CodeInfoResponse = types.CodeInfoResponse
MessageHandler = keeper.MessageHandler
BankEncoder = keeper.BankEncoder
CustomEncoder = keeper.CustomEncoder
StakingEncoder = keeper.StakingEncoder
WasmEncoder = keeper.WasmEncoder
MessageEncoders = keeper.MessageEncoders
Keeper = keeper.Keeper
QueryHandler = keeper.QueryHandler
CustomQuerier = keeper.CustomQuerier
QueryPlugins = keeper.QueryPlugins
ProposalType = types.ProposalType
GenesisState = types.GenesisState
Code = types.Code
Contract = types.Contract
MsgStoreCode = types.MsgStoreCode
MsgStoreCodeResponse = types.MsgStoreCodeResponse
MsgInstantiateContract = types.MsgInstantiateContract
MsgInstantiateContractResponse = types.MsgInstantiateContractResponse
MsgExecuteContract = types.MsgExecuteContract
MsgExecuteContractResponse = types.MsgExecuteContractResponse
MsgMigrateContract = types.MsgMigrateContract
MsgMigrateContractResponse = types.MsgMigrateContractResponse
MsgUpdateAdmin = types.MsgUpdateAdmin
MsgUpdateAdminResponse = types.MsgUpdateAdminResponse
MsgClearAdmin = types.MsgClearAdmin
MsgClearAdminResponse = types.MsgClearAdminResponse
MsgServer = types.MsgServer
Model = types.Model
CodeInfo = types.CodeInfo
ContractInfo = types.ContractInfo
CreatedAt = types.AbsoluteTxPosition
Config = types.WasmConfig
ContractInfoWithAddress = types.ContractInfoWithAddress
CodeInfoResponse = types.CodeInfoResponse
MessageHandler = keeper.MessageHandler
BankEncoder = keeper.BankEncoder
CustomEncoder = keeper.CustomEncoder
StakingEncoder = keeper.StakingEncoder
WasmEncoder = keeper.WasmEncoder
MessageEncoders = keeper.MessageEncoders
Keeper = keeper.Keeper
QueryHandler = keeper.QueryHandler
CustomQuerier = keeper.CustomQuerier
QueryPlugins = keeper.QueryPlugins
)
12 changes: 10 additions & 2 deletions x/wasm/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ func TestInitGenesis(t *testing.T) {

res, err := h(data.ctx, &msg)
require.NoError(t, err)
require.Equal(t, res.Data, []byte("1"))

var pStoreResp MsgStoreCodeResponse
ethanfrey marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, pStoreResp.Unmarshal(res.Data))
require.Equal(t, pStoreResp.CodeID, "1")

_, _, bob := keyPubAddr()
initMsg := initMsg{
Expand All @@ -48,7 +51,9 @@ func TestInitGenesis(t *testing.T) {
}
res, err = h(data.ctx, &initCmd)
require.NoError(t, err)
contractBech32Addr := string(res.Data)
var pInstResp MsgInstantiateContractResponse
require.NoError(t, pInstResp.Unmarshal(res.Data))
contractBech32Addr := pInstResp.Address

execCmd := MsgExecuteContract{
Sender: fred.String(),
Expand All @@ -58,6 +63,9 @@ func TestInitGenesis(t *testing.T) {
}
res, err = h(data.ctx, &execCmd)
require.NoError(t, err)
var pExecResp MsgExecuteContractResponse
require.NoError(t, pExecResp.Unmarshal(res.Data))
require.NotEmpty(t, pExecResp.Data)

// ensure all contract state is as after init
assertCodeList(t, q, data.ctx, 1)
Expand Down
215 changes: 35 additions & 180 deletions x/wasm/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,215 +2,70 @@ package wasm

import (
"fmt"

"github.com/CosmWasm/wasmd/x/wasm/internal/keeper"
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
"github.com/gogo/protobuf/proto"
abci "github.com/tendermint/tendermint/abci/types"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
abci "github.com/tendermint/tendermint/abci/types"
)

// NewHandler returns a handler for "bank" type messages.
func NewHandler(k *Keeper) sdk.Handler {
msgServer := keeper.NewMsgServerImpl(k)

return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())

var (
res proto.Message
err error
)
switch msg := msg.(type) {
case *MsgStoreCode:
return handleStoreCode(ctx, k, msg)
res, err = msgServer.StoreCode(sdk.WrapSDKContext(ctx), msg)
case *MsgInstantiateContract:
return handleInstantiate(ctx, k, msg)
res, err = msgServer.InstantiateContract(sdk.WrapSDKContext(ctx), msg)
case *MsgExecuteContract:
return handleExecute(ctx, k, msg)
res, err = msgServer.ExecuteContract(sdk.WrapSDKContext(ctx), msg)
case *MsgMigrateContract:
return handleMigration(ctx, k, msg)
res, err = msgServer.MigrateContract(sdk.WrapSDKContext(ctx), msg)
case *MsgUpdateAdmin:
return handleUpdateContractAdmin(ctx, k, msg)
res, err = msgServer.UpdateAdmin(sdk.WrapSDKContext(ctx), msg)
case *MsgClearAdmin:
return handleClearContractAdmin(ctx, k, msg)
res, err = msgServer.ClearAdmin(sdk.WrapSDKContext(ctx), msg)
default:
errMsg := fmt.Sprintf("unrecognized wasm message type: %T", msg)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
}

ctx = ctx.WithEventManager(filterMessageEvents(ctx))
return sdk.WrapServiceResult(ctx, res, err)
}
}

// filterMessageEvents returns the same events with all of type == EventTypeMessage removed.
// filterMessageEvents returns the same events with all of type == EventTypeMessage removed except
// for wasm message types.
// this is so only our top-level message event comes through
func filteredMessageEvents(manager *sdk.EventManager) []abci.Event {
events := manager.ABCIEvents()
res := make([]abci.Event, 0, len(events))
for _, e := range events {
if e.Type != sdk.EventTypeMessage {
res = append(res, e)
func filterMessageEvents(ctx sdk.Context) *sdk.EventManager {
m := sdk.NewEventManager()
for _, e := range ctx.EventManager().Events() {
if e.Type == sdk.EventTypeMessage &&
!hasWasmModuleAttribute(e.Attributes) {
continue
}
m.EmitEvent(e)
}
return res
}

func handleStoreCode(ctx sdk.Context, k *Keeper, msg *MsgStoreCode) (*sdk.Result, error) {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, sdkerrors.Wrap(err, "sender")
}
codeID, err := k.Create(ctx, senderAddr, msg.WASMByteCode, msg.Source, msg.Builder, msg.InstantiatePermission)
if err != nil {
return nil, err
}

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(types.AttributeKeySigner, msg.Sender),
sdk.NewAttribute(types.AttributeKeyCodeID, fmt.Sprintf("%d", codeID)),
),
})

return &sdk.Result{
Data: []byte(fmt.Sprintf("%d", codeID)),
Events: ctx.EventManager().ABCIEvents(),
}, nil
return m
}

func handleInstantiate(ctx sdk.Context, k *Keeper, msg *MsgInstantiateContract) (*sdk.Result, error) {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, sdkerrors.Wrap(err, "sender")
}
var adminAddr sdk.AccAddress
if msg.Admin != "" {
if adminAddr, err = sdk.AccAddressFromBech32(msg.Admin); err != nil {
return nil, sdkerrors.Wrap(err, "admin")
func hasWasmModuleAttribute(attrs []abci.EventAttribute) bool {
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need this? I am a bit unsure and need to investigate the event/attribute system a bit more.

There were multiple sub-messages merging into each other before causing confusion. I will try some tests in a branch

Copy link
Member

Choose a reason for hiding this comment

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

Saved follow up for #368 but not for 0.14.0 release

for _, a := range attrs {
if sdk.AttributeKeyModule == string(a.Key) &&
types.ModuleName == string(a.Value) {
return true
}
}

contractAddr, err := k.Instantiate(ctx, msg.CodeID, senderAddr, adminAddr, msg.InitMsg, msg.Label, msg.InitFunds)
if err != nil {
return nil, err
}

events := filteredMessageEvents(ctx.EventManager())
custom := sdk.Events{sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(types.AttributeKeySigner, msg.Sender),
sdk.NewAttribute(types.AttributeKeyCodeID, fmt.Sprintf("%d", msg.CodeID)),
sdk.NewAttribute(types.AttributeKeyContract, contractAddr.String()),
)}
events = append(events, custom.ToABCIEvents()...)

return &sdk.Result{
Data: []byte(contractAddr.String()),
Events: events,
}, nil
}

func handleExecute(ctx sdk.Context, k *Keeper, msg *MsgExecuteContract) (*sdk.Result, error) {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, sdkerrors.Wrap(err, "sender")
}
contractAddr, err := sdk.AccAddressFromBech32(msg.Contract)
if err != nil {
return nil, sdkerrors.Wrap(err, "contract")
}

res, err := k.Execute(ctx, contractAddr, senderAddr, msg.Msg, msg.SentFunds)
if err != nil {
return nil, err
}

events := filteredMessageEvents(ctx.EventManager())
custom := sdk.Events{sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(types.AttributeKeySigner, msg.Sender),
sdk.NewAttribute(types.AttributeKeyContract, msg.Contract),
),
}
events = append(events, custom.ToABCIEvents()...)

res.Events = events
return res, nil
}

func handleMigration(ctx sdk.Context, k *Keeper, msg *MsgMigrateContract) (*sdk.Result, error) {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, sdkerrors.Wrap(err, "sender")
}
contractAddr, err := sdk.AccAddressFromBech32(msg.Contract)
if err != nil {
return nil, sdkerrors.Wrap(err, "contract")
}

res, err := k.Migrate(ctx, contractAddr, senderAddr, msg.CodeID, msg.MigrateMsg)
if err != nil {
return nil, err
}

events := filteredMessageEvents(ctx.EventManager())
custom := sdk.Events{sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(types.AttributeKeySigner, msg.Sender),
sdk.NewAttribute(types.AttributeKeyContract, msg.Contract),
)}
events = append(events, custom.ToABCIEvents()...)
res.Events = events
return res, nil
}

func handleUpdateContractAdmin(ctx sdk.Context, k *Keeper, msg *MsgUpdateAdmin) (*sdk.Result, error) {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, sdkerrors.Wrap(err, "sender")
}
contractAddr, err := sdk.AccAddressFromBech32(msg.Contract)
if err != nil {
return nil, sdkerrors.Wrap(err, "contract")
}
newAdminAddr, err := sdk.AccAddressFromBech32(msg.NewAdmin)
if err != nil {
return nil, sdkerrors.Wrap(err, "new admin")
}

if err := k.UpdateContractAdmin(ctx, contractAddr, senderAddr, newAdminAddr); err != nil {
return nil, err
}
events := ctx.EventManager().Events()
ourEvent := sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(types.AttributeKeySigner, msg.Sender),
sdk.NewAttribute(types.AttributeKeyContract, msg.Contract),
)
return &sdk.Result{
Events: append(events, ourEvent).ToABCIEvents(),
}, nil
}

func handleClearContractAdmin(ctx sdk.Context, k *Keeper, msg *MsgClearAdmin) (*sdk.Result, error) {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, sdkerrors.Wrap(err, "sender")
}
contractAddr, err := sdk.AccAddressFromBech32(msg.Contract)
if err != nil {
return nil, sdkerrors.Wrap(err, "contract")
}

if err := k.ClearContractAdmin(ctx, contractAddr, senderAddr); err != nil {
return nil, err
}
events := ctx.EventManager().Events()
ourEvent := sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(types.AttributeKeySigner, msg.Sender),
sdk.NewAttribute(types.AttributeKeyContract, msg.Contract),
)
return &sdk.Result{
Events: append(events, ourEvent).ToABCIEvents(),
}, nil
return false
}
Loading