Allow contracts to dispatch contract messages
This commit is contained in:
@@ -16,10 +16,10 @@ type MessageHandler struct {
|
||||
}
|
||||
|
||||
type MessageEncoders struct {
|
||||
Bank func(msg *wasmTypes.BankMsg) (sdk.Msg, error)
|
||||
Custom func(msg json.RawMessage) (sdk.Msg, error)
|
||||
Staking func(msg *wasmTypes.StakingMsg) (sdk.Msg, error)
|
||||
Wasm func(msg *wasmTypes.WasmMsg) (sdk.Msg, error)
|
||||
Bank func(sender sdk.AccAddress, msg *wasmTypes.BankMsg) (sdk.Msg, error)
|
||||
Custom func(sender sdk.AccAddress, msg json.RawMessage) (sdk.Msg, error)
|
||||
Staking func(sender sdk.AccAddress, msg *wasmTypes.StakingMsg) (sdk.Msg, error)
|
||||
Wasm func(sender sdk.AccAddress, msg *wasmTypes.WasmMsg) (sdk.Msg, error)
|
||||
}
|
||||
|
||||
func DefaultEncoders() MessageEncoders {
|
||||
@@ -31,7 +31,7 @@ func DefaultEncoders() MessageEncoders {
|
||||
}
|
||||
}
|
||||
|
||||
func EncodeBankMsg(msg *wasmTypes.BankMsg) (sdk.Msg, error) {
|
||||
func EncodeBankMsg(sender sdk.AccAddress, msg *wasmTypes.BankMsg) (sdk.Msg, error) {
|
||||
if msg.Send == nil {
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Unknown variant of Bank")
|
||||
}
|
||||
@@ -58,19 +58,39 @@ func EncodeBankMsg(msg *wasmTypes.BankMsg) (sdk.Msg, error) {
|
||||
return sendMsg, nil
|
||||
}
|
||||
|
||||
func NoCustomMsg(msg json.RawMessage) (sdk.Msg, error) {
|
||||
func NoCustomMsg(sender sdk.AccAddress, msg json.RawMessage) (sdk.Msg, error) {
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Custom variant not supported")
|
||||
}
|
||||
|
||||
func EncodeStakingMsg(msg *wasmTypes.StakingMsg) (sdk.Msg, error) {
|
||||
func EncodeStakingMsg(sender sdk.AccAddress, msg *wasmTypes.StakingMsg) (sdk.Msg, error) {
|
||||
// TODO
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Staking variant not supported")
|
||||
}
|
||||
|
||||
func EncodeWasmMsg(msg *wasmTypes.WasmMsg) (sdk.Msg, error) {
|
||||
// TODO
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Wasm variant not supported")
|
||||
// } else if msg.Contract != nil {
|
||||
func EncodeWasmMsg(sender sdk.AccAddress, msg *wasmTypes.WasmMsg) (sdk.Msg, error) {
|
||||
if msg.Execute != nil {
|
||||
contractAddr, err := sdk.AccAddressFromBech32(msg.Execute.ContractAddr)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Execute.ContractAddr)
|
||||
}
|
||||
coins, err := convertWasmCoinToSdkCoin(msg.Execute.Send)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sdkMsg := types.MsgExecuteContract{
|
||||
Sender: sender,
|
||||
Contract: contractAddr,
|
||||
Msg: msg.Execute.Msg,
|
||||
SentFunds: coins,
|
||||
}
|
||||
return sdkMsg, nil
|
||||
}
|
||||
if msg.Instantiate != nil {
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Wasm.Instantiate variant not supported")
|
||||
}
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Unknown variant of Wasm")
|
||||
//lse if msg.Contract != nil {
|
||||
// targetAddr, stderr := sdk.AccAddressFromBech32(msg.Contract.ContractAddr)
|
||||
// if stderr != nil {
|
||||
// return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Contract.ContractAddr)
|
||||
@@ -91,13 +111,13 @@ func (h MessageHandler) Dispatch(ctx sdk.Context, contract exported.Account, msg
|
||||
var err error
|
||||
switch {
|
||||
case msg.Bank != nil:
|
||||
sdkMsg, err = h.encoders.Bank(msg.Bank)
|
||||
sdkMsg, err = h.encoders.Bank(contractAddr, msg.Bank)
|
||||
case msg.Custom != nil:
|
||||
sdkMsg, err = h.encoders.Custom(msg.Custom)
|
||||
sdkMsg, err = h.encoders.Custom(contractAddr, msg.Custom)
|
||||
case msg.Staking != nil:
|
||||
sdkMsg, err = h.encoders.Staking(msg.Staking)
|
||||
sdkMsg, err = h.encoders.Staking(contractAddr, msg.Staking)
|
||||
case msg.Wasm != nil:
|
||||
sdkMsg, err = h.encoders.Wasm(msg.Wasm)
|
||||
sdkMsg, err = h.encoders.Wasm(contractAddr, msg.Wasm)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -349,8 +349,6 @@ func TestExecuteWithPanic(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestExecuteWithCpuLoop(t *testing.T) {
|
||||
// TODO
|
||||
t.Skip("out of gas error not thrown")
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
@@ -167,8 +167,6 @@ func fromMaskRawMsg(cdc *codec.Codec, msg json.RawMessage) (sdk.Msg, error) {
|
||||
}
|
||||
|
||||
func TestMaskReflectContractSend(t *testing.T) {
|
||||
// TODO
|
||||
t.Skip("this causes a panic in the rust code!")
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
@@ -74,7 +76,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string) (sdk.Context,
|
||||
)
|
||||
bk.SetSendEnabled(ctx, true)
|
||||
|
||||
// TODO: register more than bank.send
|
||||
// TODO: register slashing (and more?)
|
||||
router := baseapp.NewRouter()
|
||||
h := bank.NewHandler(bk)
|
||||
router.AddRoute(bank.RouterKey, h)
|
||||
@@ -83,6 +85,53 @@ func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string) (sdk.Context,
|
||||
wasmConfig := wasmTypes.DefaultWasmConfig()
|
||||
|
||||
keeper := NewKeeper(cdc, keyContract, accountKeeper, bk, router, tempDir, wasmConfig)
|
||||
// add wasm handler so we can loop-back (contracts calling contracts)
|
||||
router.AddRoute(wasmTypes.RouterKey, TestHandler(keeper))
|
||||
|
||||
return ctx, accountKeeper, keeper
|
||||
}
|
||||
|
||||
// TestHandler returns a wasm handler for tests (to avoid circular imports)
|
||||
func TestHandler(k Keeper) sdk.Handler {
|
||||
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case wasmTypes.MsgInstantiateContract:
|
||||
return handleInstantiate(ctx, k, &msg)
|
||||
case *wasmTypes.MsgInstantiateContract:
|
||||
return handleInstantiate(ctx, k, msg)
|
||||
|
||||
case wasmTypes.MsgExecuteContract:
|
||||
return handleExecute(ctx, k, &msg)
|
||||
case *wasmTypes.MsgExecuteContract:
|
||||
return handleExecute(ctx, k, msg)
|
||||
|
||||
default:
|
||||
errMsg := fmt.Sprintf("unrecognized wasm message type: %T", msg)
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleInstantiate(ctx sdk.Context, k Keeper, msg *wasmTypes.MsgInstantiateContract) (*sdk.Result, error) {
|
||||
contractAddr, err := k.Instantiate(ctx, msg.Code, msg.Sender, msg.InitMsg, msg.Label, msg.InitFunds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sdk.Result{
|
||||
Data: contractAddr,
|
||||
Events: ctx.EventManager().Events(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func handleExecute(ctx sdk.Context, k Keeper, msg *wasmTypes.MsgExecuteContract) (*sdk.Result, error) {
|
||||
res, err := k.Execute(ctx, msg.Contract, msg.Sender, msg.Msg, msg.SentFunds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res.Events = ctx.EventManager().Events()
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user