mirror of https://github.com/certusone/wasmd.git
Register and demo custom message handlers with mask
This commit is contained in:
parent
7b7a293835
commit
7caa786d71
|
@ -33,13 +33,94 @@ type reflectPayload struct {
|
|||
Msgs []wasmTypes.CosmosMsg `json:"msgs"`
|
||||
}
|
||||
|
||||
func TestMaskReflectCustom(t *testing.T) {
|
||||
// TODO
|
||||
t.Skip("this causes a panic in the rust code!")
|
||||
func TestMaskReflectContractSend(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tempDir)
|
||||
ctx, accKeeper, keeper := CreateTestInput(t, false, tempDir, nil)
|
||||
ctx, accKeeper, keeper := CreateTestInput(t, false, tempDir, maskEncoders(MakeTestCodec()))
|
||||
|
||||
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
|
||||
creator := createFakeFundedAccount(ctx, accKeeper, deposit)
|
||||
_, _, bob := keyPubAddr()
|
||||
|
||||
// upload mask code
|
||||
maskCode, err := ioutil.ReadFile("./testdata/mask.wasm")
|
||||
require.NoError(t, err)
|
||||
maskID, err := keeper.Create(ctx, creator, maskCode, "", "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), maskID)
|
||||
|
||||
// upload hackatom escrow code
|
||||
escrowCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
escrowID, err := keeper.Create(ctx, creator, escrowCode, "", "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(2), escrowID)
|
||||
|
||||
// creator instantiates a contract and gives it tokens
|
||||
maskStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
|
||||
maskAddr, err := keeper.Instantiate(ctx, maskID, creator, []byte("{}"), "mask contract 2", maskStart)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, maskAddr)
|
||||
|
||||
// now we set contract as verifier of an escrow
|
||||
initMsg := InitMsg{
|
||||
Verifier: maskAddr,
|
||||
Beneficiary: bob,
|
||||
}
|
||||
initMsgBz, err := json.Marshal(initMsg)
|
||||
require.NoError(t, err)
|
||||
escrowStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 25000))
|
||||
escrowAddr, err := keeper.Instantiate(ctx, escrowID, creator, initMsgBz, "escrow contract 2", escrowStart)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, escrowAddr)
|
||||
|
||||
// let's make sure all balances make sense
|
||||
checkAccount(t, ctx, accKeeper, creator, sdk.NewCoins(sdk.NewInt64Coin("denom", 35000))) // 100k - 40k - 25k
|
||||
checkAccount(t, ctx, accKeeper, maskAddr, maskStart)
|
||||
checkAccount(t, ctx, accKeeper, escrowAddr, escrowStart)
|
||||
checkAccount(t, ctx, accKeeper, bob, nil)
|
||||
|
||||
// now for the trick.... we reflect a message through the mask to call the escrow
|
||||
// we also send an additional 14k tokens there.
|
||||
// this should reduce the mask balance by 14k (to 26k)
|
||||
// this 14k is added to the escrow, then the entire balance is sent to bob (total: 39k)
|
||||
approveMsg := []byte(`{"release":{}}`)
|
||||
msgs := []wasmTypes.CosmosMsg{{
|
||||
Wasm: &wasmTypes.WasmMsg{
|
||||
Execute: &wasmTypes.ExecuteMsg{
|
||||
ContractAddr: escrowAddr.String(),
|
||||
Msg: approveMsg,
|
||||
Send: []wasmTypes.Coin{{
|
||||
Denom: "denom",
|
||||
Amount: "14000",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}}
|
||||
reflectSend := MaskHandleMsg{
|
||||
Reflect: &reflectPayload{
|
||||
Msgs: msgs,
|
||||
},
|
||||
}
|
||||
reflectSendBz, err := json.Marshal(reflectSend)
|
||||
require.NoError(t, err)
|
||||
_, err = keeper.Execute(ctx, maskAddr, creator, reflectSendBz, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// did this work???
|
||||
checkAccount(t, ctx, accKeeper, creator, sdk.NewCoins(sdk.NewInt64Coin("denom", 35000))) // same as before
|
||||
checkAccount(t, ctx, accKeeper, maskAddr, sdk.NewCoins(sdk.NewInt64Coin("denom", 26000))) // 40k - 14k (from send)
|
||||
checkAccount(t, ctx, accKeeper, escrowAddr, sdk.Coins{}) // emptied reserved
|
||||
checkAccount(t, ctx, accKeeper, bob, sdk.NewCoins(sdk.NewInt64Coin("denom", 39000))) // all escrow of 25k + 14k
|
||||
|
||||
}
|
||||
|
||||
func TestMaskReflectCustom(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tempDir)
|
||||
ctx, accKeeper, keeper := CreateTestInput(t, false, tempDir, maskEncoders(MakeTestCodec()))
|
||||
|
||||
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
|
||||
creator := createFakeFundedAccount(ctx, accKeeper, deposit)
|
||||
|
@ -130,9 +211,26 @@ func TestMaskReflectCustom(t *testing.T) {
|
|||
checkAccount(t, ctx, accKeeper, bob, deposit)
|
||||
}
|
||||
|
||||
func checkAccount(t *testing.T, ctx sdk.Context, accKeeper auth.AccountKeeper, addr sdk.AccAddress, expected sdk.Coins) {
|
||||
acct := accKeeper.GetAccount(ctx, addr)
|
||||
if expected == nil {
|
||||
assert.Nil(t, acct)
|
||||
} else {
|
||||
assert.NotNil(t, acct)
|
||||
if expected.Empty() {
|
||||
// there is confusion between nil and empty slice... let's just treat them the same
|
||||
assert.True(t, acct.GetCoins().Empty())
|
||||
} else {
|
||||
assert.Equal(t, acct.GetCoins(), expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**** Code to support custom messages *****/
|
||||
|
||||
type maskCustomMsg struct {
|
||||
Debug string `json:"debug"`
|
||||
Raw []byte `json:"raw"`
|
||||
Debug string `json:"debug,omitempty"`
|
||||
Raw []byte `json:"raw,omitempty"`
|
||||
}
|
||||
|
||||
// toMaskRawMsg encodes an sdk msg using amino json encoding.
|
||||
|
@ -151,115 +249,33 @@ func toMaskRawMsg(cdc *codec.Codec, msg sdk.Msg) (wasmTypes.CosmosMsg, error) {
|
|||
return res, nil
|
||||
}
|
||||
|
||||
// maskEncoders needs to be registered in test setup to handle custom callbacks
|
||||
func maskEncoders(cdc *codec.Codec) *MessageEncoders {
|
||||
return &MessageEncoders{
|
||||
Custom: fromMaskRawMsg(cdc),
|
||||
}
|
||||
}
|
||||
|
||||
// fromMaskRawMsg decodes msg.Data to an sdk.Msg using amino json encoding.
|
||||
// this needs to be registered on the Encoders
|
||||
func fromMaskRawMsg(cdc *codec.Codec, msg json.RawMessage) (sdk.Msg, error) {
|
||||
// TODO
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Reflect Custom message unimplemented")
|
||||
|
||||
//// until more is changes, format is amino json encoding, wrapped base64
|
||||
//var sdkmsg sdk.Msg
|
||||
//err := cdc.UnmarshalJSON(msg.Data, &sdkmsg)
|
||||
//if err != nil {
|
||||
// return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||
//}
|
||||
//return sdkmsg, nil
|
||||
}
|
||||
|
||||
func TestMaskReflectContractSend(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tempDir)
|
||||
ctx, accKeeper, keeper := CreateTestInput(t, false, tempDir, nil)
|
||||
|
||||
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
|
||||
creator := createFakeFundedAccount(ctx, accKeeper, deposit)
|
||||
_, _, bob := keyPubAddr()
|
||||
|
||||
// upload mask code
|
||||
maskCode, err := ioutil.ReadFile("./testdata/mask.wasm")
|
||||
require.NoError(t, err)
|
||||
maskID, err := keeper.Create(ctx, creator, maskCode, "", "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), maskID)
|
||||
|
||||
// upload hackatom escrow code
|
||||
escrowCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
escrowID, err := keeper.Create(ctx, creator, escrowCode, "", "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(2), escrowID)
|
||||
|
||||
// creator instantiates a contract and gives it tokens
|
||||
maskStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
|
||||
maskAddr, err := keeper.Instantiate(ctx, maskID, creator, []byte("{}"), "mask contract 2", maskStart)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, maskAddr)
|
||||
|
||||
// now we set contract as verifier of an escrow
|
||||
initMsg := InitMsg{
|
||||
Verifier: maskAddr,
|
||||
Beneficiary: bob,
|
||||
}
|
||||
initMsgBz, err := json.Marshal(initMsg)
|
||||
require.NoError(t, err)
|
||||
escrowStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 25000))
|
||||
escrowAddr, err := keeper.Instantiate(ctx, escrowID, creator, initMsgBz, "escrow contract 2", escrowStart)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, escrowAddr)
|
||||
|
||||
// let's make sure all balances make sense
|
||||
checkAccount(t, ctx, accKeeper, creator, sdk.NewCoins(sdk.NewInt64Coin("denom", 35000))) // 100k - 40k - 25k
|
||||
checkAccount(t, ctx, accKeeper, maskAddr, maskStart)
|
||||
checkAccount(t, ctx, accKeeper, escrowAddr, escrowStart)
|
||||
checkAccount(t, ctx, accKeeper, bob, nil)
|
||||
|
||||
// now for the trick.... we reflect a message through the mask to call the escrow
|
||||
// we also send an additional 14k tokens there.
|
||||
// this should reduce the mask balance by 14k (to 26k)
|
||||
// this 14k is added to the escrow, then the entire balance is sent to bob (total: 39k)
|
||||
approveMsg := []byte(`{"release":{}}`)
|
||||
msgs := []wasmTypes.CosmosMsg{{
|
||||
Wasm: &wasmTypes.WasmMsg{
|
||||
Execute: &wasmTypes.ExecuteMsg{
|
||||
ContractAddr: escrowAddr.String(),
|
||||
Msg: approveMsg,
|
||||
Send: []wasmTypes.Coin{{
|
||||
Denom: "denom",
|
||||
Amount: "14000",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}}
|
||||
reflectSend := MaskHandleMsg{
|
||||
Reflect: &reflectPayload{
|
||||
Msgs: msgs,
|
||||
},
|
||||
}
|
||||
reflectSendBz, err := json.Marshal(reflectSend)
|
||||
require.NoError(t, err)
|
||||
_, err = keeper.Execute(ctx, maskAddr, creator, reflectSendBz, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// did this work???
|
||||
checkAccount(t, ctx, accKeeper, creator, sdk.NewCoins(sdk.NewInt64Coin("denom", 35000))) // same as before
|
||||
checkAccount(t, ctx, accKeeper, maskAddr, sdk.NewCoins(sdk.NewInt64Coin("denom", 26000))) // 40k - 14k (from send)
|
||||
checkAccount(t, ctx, accKeeper, escrowAddr, sdk.Coins{}) // emptied reserved
|
||||
checkAccount(t, ctx, accKeeper, bob, sdk.NewCoins(sdk.NewInt64Coin("denom", 39000))) // all escrow of 25k + 14k
|
||||
|
||||
}
|
||||
|
||||
func checkAccount(t *testing.T, ctx sdk.Context, accKeeper auth.AccountKeeper, addr sdk.AccAddress, expected sdk.Coins) {
|
||||
acct := accKeeper.GetAccount(ctx, addr)
|
||||
if expected == nil {
|
||||
assert.Nil(t, acct)
|
||||
} else {
|
||||
assert.NotNil(t, acct)
|
||||
if expected.Empty() {
|
||||
// there is confusion between nil and empty slice... let's just treat them the same
|
||||
assert.True(t, acct.GetCoins().Empty())
|
||||
} else {
|
||||
assert.Equal(t, acct.GetCoins(), expected)
|
||||
func fromMaskRawMsg(cdc *codec.Codec) func(_sender sdk.AccAddress, msg json.RawMessage) (sdk.Msg, error) {
|
||||
return func(_sender sdk.AccAddress, msg json.RawMessage) (sdk.Msg, error) {
|
||||
var custom maskCustomMsg
|
||||
err := json.Unmarshal(msg, &custom)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||
}
|
||||
if custom.Raw != nil {
|
||||
var sdkMsg sdk.Msg
|
||||
err := cdc.UnmarshalJSON(custom.Raw, &sdkMsg)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
|
||||
}
|
||||
return sdkMsg, nil
|
||||
}
|
||||
if custom.Debug != "" {
|
||||
return nil, sdkerrors.Wrapf(types.ErrInvalidMsg, "Custom Debug: %s", custom.Debug)
|
||||
}
|
||||
return nil, sdkerrors.Wrap(types.ErrInvalidMsg, "Unknown Custom message variant")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ func MakeTestCodec() *codec.Codec {
|
|||
// cdc.RegisterConcrete(&auth.BaseAccount{}, "test/wasm/BaseAccount", nil)
|
||||
auth.AppModuleBasic{}.RegisterCodec(cdc)
|
||||
bank.AppModuleBasic{}.RegisterCodec(cdc)
|
||||
wasmTypes.RegisterCodec(cdc)
|
||||
sdk.RegisterCodec(cdc)
|
||||
codec.RegisterCrypto(cdc)
|
||||
|
||||
|
|
Loading…
Reference in New Issue