From 52a7ddc14014903c2606eb7ab272d6a816648439 Mon Sep 17 00:00:00 2001 From: krhubert Date: Thu, 27 Feb 2020 11:36:12 +0100 Subject: [PATCH 01/17] Handle withdraw from resources --- app/app.go | 2 +- e2e/execution_test.go | 38 ++++++++++++ x/execution/handler.go | 2 +- x/ownership/alias.go | 4 ++ x/ownership/client/cli/tx.go | 39 ++++++++++++- x/ownership/client/rest/tx.go | 58 ++++++++++++++++++- x/ownership/handler.go | 30 +++++++++- x/ownership/internal/keeper/keeper.go | 20 ++++++- x/ownership/internal/types/events.go | 8 +++ .../internal/types/expected_keepers.go | 5 ++ x/ownership/internal/types/msg.go | 58 +++++++++++++++++++ 11 files changed, 254 insertions(+), 10 deletions(-) create mode 100644 x/ownership/internal/types/events.go create mode 100644 x/ownership/internal/types/msg.go diff --git a/app/app.go b/app/app.go index 499d7dd65..112c9523e 100644 --- a/app/app.go +++ b/app/app.go @@ -241,7 +241,7 @@ func NewInitApp( ) // Engine's module keepers - app.ownershipKeeper = ownership.NewKeeper(app.cdc, keys[ownership.StoreKey]) + app.ownershipKeeper = ownership.NewKeeper(app.cdc, keys[ownership.StoreKey], app.bankKeeper) app.instanceKeeper = instance.NewKeeper(app.cdc, keys[instance.StoreKey]) app.processKeeper = process.NewKeeper(app.cdc, keys[process.StoreKey], app.instanceKeeper, app.ownershipKeeper) app.serviceKeeper = service.NewKeeper(app.cdc, keys[service.StoreKey], app.ownershipKeeper) diff --git a/e2e/execution_test.go b/e2e/execution_test.go index b48339d01..88f272687 100644 --- a/e2e/execution_test.go +++ b/e2e/execution_test.go @@ -2,15 +2,18 @@ package main import ( "context" + "fmt" "sync" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/mesg-foundation/engine/execution" "github.com/mesg-foundation/engine/hash" + "github.com/mesg-foundation/engine/ownership" "github.com/mesg-foundation/engine/protobuf/acknowledgement" pb "github.com/mesg-foundation/engine/protobuf/api" "github.com/mesg-foundation/engine/protobuf/types" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" ) @@ -248,6 +251,41 @@ func testExecution(t *testing.T) { lcdGet(t, "bank/balances/"+execAddress.String(), &coins) require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(0))) }) + + // check balance of execution + t.Run("withdraw from service", func(t *testing.T) { + var os []*ownership.Ownership + lcdGet(t, "ownership/list", &os) + + var owner string + for _, o := range os { + if o.ResourceHash.Equal(testServiceHash) { + owner = o.Owner + break + } + } + assert.NotEmpty(t, owner) + + withdrawCoinsReq := struct { + Amount string `json:"amount"` + Hash hash.Hash `json:"hash"` + Owner string `json:"owner"` + }{"5atto", testServiceHash, owner} + + lcdPost(t, "ownership/withdraw-coins", withdrawCoinsReq, nil) + + coins := sdk.Coins{} + + serviceAddress := sdk.AccAddress(crypto.AddressHash(testServiceHash)) + lcdGet(t, "bank/balances/"+serviceAddress.String(), &coins) + fmt.Println(coins) + // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(0))) + + lcdGet(t, "bank/balances/"+owner, &coins) + fmt.Println(coins) + t.FailNow() + // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(5))) + }) }) t.Run("many executions in parallel", func(t *testing.T) { diff --git a/x/execution/handler.go b/x/execution/handler.go index b90aa3dd9..e49ac70d2 100644 --- a/x/execution/handler.go +++ b/x/execution/handler.go @@ -24,7 +24,7 @@ func NewHandler(k Keeper) sdk.Handler { } } -// handleMsgCreateExecution creates a new process. +// handleMsgCreateExecution creates a new execution. func handleMsgCreateExecution(ctx sdk.Context, k Keeper, msg MsgCreateExecution) (*sdk.Result, error) { s, err := k.Create(ctx, msg) if err != nil { diff --git a/x/ownership/alias.go b/x/ownership/alias.go index c4f00e3a2..617409936 100644 --- a/x/ownership/alias.go +++ b/x/ownership/alias.go @@ -25,6 +25,8 @@ var ( ModuleCdc = types.ModuleCdc QueryListOwnerships = types.QueryListOwnerships + + NewMsgWithdrawCoins = types.NewMsgWithdrawCoins ) // module types @@ -32,4 +34,6 @@ type ( Keeper = keeper.Keeper GenesisState = types.GenesisState Params = types.Params + + MsgWithdrawCoins = types.MsgWithdrawCoins ) diff --git a/x/ownership/client/cli/tx.go b/x/ownership/client/cli/tx.go index 67ad67c77..6b8717891 100644 --- a/x/ownership/client/cli/tx.go +++ b/x/ownership/client/cli/tx.go @@ -1,11 +1,17 @@ package cli import ( + "bufio" "fmt" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + "github.com/mesg-foundation/engine/hash" "github.com/mesg-foundation/engine/x/ownership/internal/types" "github.com/spf13/cobra" ) @@ -21,6 +27,37 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { } ownershipTxCmd.AddCommand(flags.PostCommands()...) - return ownershipTxCmd } + +// GetCmdWithdrawCoins is the CLI command for sending a WithdrawCoins transaction +func GetCmdWithdrawCoins(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "withdraw-coins [resource] [amount]", + Short: "withdraw amount from resource address", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + cliCtx := context.NewCLIContext().WithCodec(cdc) + + txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) + + h, err := hash.Decode(args[0]) + if err != nil { + return err + } + + coins, err := sdk.ParseCoins(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgWithdrawCoins(h, coins, cliCtx.GetFromAddress()) + if err = msg.ValidateBasic(); err != nil { + return err + } + + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } +} diff --git a/x/ownership/client/rest/tx.go b/x/ownership/client/rest/tx.go index ae173af7c..4b953412b 100644 --- a/x/ownership/client/rest/tx.go +++ b/x/ownership/client/rest/tx.go @@ -1,9 +1,63 @@ package rest import ( - "github.com/gorilla/mux" + "net/http" "github.com/cosmos/cosmos-sdk/client/context" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + "github.com/gorilla/mux" + "github.com/mesg-foundation/engine/hash" + "github.com/mesg-foundation/engine/x/ownership/internal/types" ) -func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) {} +type withdrawCoinsReq struct { + BaseReq rest.BaseReq `json:"base_req"` + Amount string `json:"amount"` + Hash hash.Hash `json:"hash"` + Owner string `json:"owner"` +} + +func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { + r.HandleFunc( + "/ownership/withdraw-coins", + txWithdrawCoinsHandlerFn(cliCtx), + ).Methods(http.MethodPost) +} + +func txWithdrawCoinsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req withdrawCoinsReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") + return + } + + baseReq := req.BaseReq.Sanitize() + if !baseReq.ValidateBasic(w) { + return + } + + owner, err := sdk.AccAddressFromBech32(req.Owner) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + amt, err := sdk.ParseCoins(req.Amount) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + msg := types.NewMsgWithdrawCoins(req.Hash, amt, owner) + if err := msg.ValidateBasic(); err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, baseReq, []sdk.Msg{msg}) + } +} diff --git a/x/ownership/handler.go b/x/ownership/handler.go index 322eb7fc0..e6fae32af 100644 --- a/x/ownership/handler.go +++ b/x/ownership/handler.go @@ -11,7 +11,33 @@ import ( // NewHandler creates an sdk.Handler for all the instance type messages func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { - errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) - return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) + ctx = ctx.WithEventManager(sdk.NewEventManager()) + switch msg := msg.(type) { + case MsgWithdrawCoins: + return handleMsgWithdrawCoins(ctx, k, msg) + default: + errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) + return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) + } } } + +// handleMsgWithdrawCoins withdraws coins from resource to the owner. +func handleMsgWithdrawCoins(ctx sdk.Context, k Keeper, msg MsgWithdrawCoins) (*sdk.Result, error) { + if err := k.WithdrawCoins(ctx, msg); err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, types.EventTypeWithdrawCoins), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Hash.String()), + ), + ) + + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil +} diff --git a/x/ownership/internal/keeper/keeper.go b/x/ownership/internal/keeper/keeper.go index 7a6a3a05e..f770542dd 100644 --- a/x/ownership/internal/keeper/keeper.go +++ b/x/ownership/internal/keeper/keeper.go @@ -5,9 +5,11 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/mesg-foundation/engine/hash" "github.com/mesg-foundation/engine/ownership" "github.com/mesg-foundation/engine/x/ownership/internal/types" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/libs/log" ) @@ -15,13 +17,16 @@ import ( type Keeper struct { storeKey sdk.StoreKey cdc *codec.Codec + + bankKeeper types.BankKeeper } // NewKeeper creates a ownership keeper -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper { +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, bankKeeper types.BankKeeper) Keeper { keeper := Keeper{ - storeKey: key, - cdc: cdc, + storeKey: key, + cdc: cdc, + bankKeeper: bankKeeper, } return keeper } @@ -83,6 +88,15 @@ func (k Keeper) Delete(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash. return nil } +// WithdrawCoins try to withdraw coins to owner rom specific resource. +func (k Keeper) WithdrawCoins(ctx sdk.Context, msg types.MsgWithdrawCoins) error { + if len(k.findOwnerships(ctx.KVStore(k.storeKey), msg.Owner.String(), msg.Hash)) == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "address %s is not owner of resource %s", msg.Owner, msg.Hash) + } + addr := sdk.AccAddress(crypto.AddressHash(msg.Hash)) + return k.bankKeeper.SendCoins(ctx, addr, msg.Owner, msg.Amount) +} + // hasOwner checks if given resource has owner. Returns all ownership hash and true if has one // nil and false otherwise. func (k Keeper) findOwnerships(store sdk.KVStore, owner string, resourceHash hash.Hash) []hash.Hash { diff --git a/x/ownership/internal/types/events.go b/x/ownership/internal/types/events.go new file mode 100644 index 000000000..9152c4e12 --- /dev/null +++ b/x/ownership/internal/types/events.go @@ -0,0 +1,8 @@ +package types + +// ownership module event types +const ( + EventTypeWithdrawCoins = "WithdrawCoins" + + AttributeValueCategory = ModuleName +) diff --git a/x/ownership/internal/types/expected_keepers.go b/x/ownership/internal/types/expected_keepers.go index 23128499d..3bfb9409e 100644 --- a/x/ownership/internal/types/expected_keepers.go +++ b/x/ownership/internal/types/expected_keepers.go @@ -12,3 +12,8 @@ type ParamSubspace interface { GetParamSet(ctx sdk.Context, ps params.ParamSet) SetParamSet(ctx sdk.Context, ps params.ParamSet) } + +// BankKeeper module interface. +type BankKeeper interface { + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error +} diff --git a/x/ownership/internal/types/msg.go b/x/ownership/internal/types/msg.go new file mode 100644 index 000000000..2c25c7dc2 --- /dev/null +++ b/x/ownership/internal/types/msg.go @@ -0,0 +1,58 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/mesg-foundation/engine/hash" +) + +// MsgWithdrawCoins defines a state transition to create a execution. +type MsgWithdrawCoins struct { + Hash hash.Hash `json:"hash"` + Amount sdk.Coins `json:"amount"` + Owner sdk.AccAddress `json:"owner"` +} + +// NewMsgWithdrawCoins is a constructor function for MsgWithdrawCoins. +func NewMsgWithdrawCoins(h hash.Hash, amount sdk.Coins, owner sdk.AccAddress) *MsgWithdrawCoins { + return &MsgWithdrawCoins{ + Hash: h, + Amount: amount, + Owner: owner, + } +} + +// Route should return the name of the module. +func (msg MsgWithdrawCoins) Route() string { + return ModuleName +} + +// Type returns the action. +func (msg MsgWithdrawCoins) Type() string { + return "WithdrawCoins" +} + +// ValidateBasic runs stateless checks on the message. +func (msg MsgWithdrawCoins) ValidateBasic() error { + if msg.Amount.IsAnyNegative() { + return sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "price must be positive") + } + if msg.Owner.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Owner.String()) + } + if msg.Hash.IsZero() || !msg.Hash.Valid() { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid resource address: %s", msg.Owner.String()) + } + + return nil +} + +// GetSignBytes encodes the message for signing. +func (msg MsgWithdrawCoins) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) +} + +// GetSigners defines whose signature is required. +func (msg MsgWithdrawCoins) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Owner} +} From 5e7f32d8c5bf58b5bb2e503d9981d7eebeca4cf5 Mon Sep 17 00:00:00 2001 From: krhubert Date: Fri, 28 Feb 2020 20:45:06 +0100 Subject: [PATCH 02/17] Send all resource to owner on deletion --- x/ownership/internal/keeper/keeper.go | 8 ++++++++ x/ownership/internal/types/expected_keepers.go | 1 + 2 files changed, 9 insertions(+) diff --git a/x/ownership/internal/keeper/keeper.go b/x/ownership/internal/keeper/keeper.go index f770542dd..6ca969870 100644 --- a/x/ownership/internal/keeper/keeper.go +++ b/x/ownership/internal/keeper/keeper.go @@ -82,6 +82,14 @@ func (k Keeper) Delete(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash. return fmt.Errorf("resource %q do not have any ownership", resourceHash) } + // transfer all spendable coins from resource address to owner + addr := sdk.AccAddress(crypto.AddressHash(resourceHash)) + coins := k.bankKeeper.SpendableCoins(ctx, addr) + if err := k.bankKeeper.SendCoins(ctx, addr, owner, coins); err != nil { + return err + } + + // remove all ownerships for _, hash := range hashes { store.Delete(hash) } diff --git a/x/ownership/internal/types/expected_keepers.go b/x/ownership/internal/types/expected_keepers.go index 3bfb9409e..7e45036fe 100644 --- a/x/ownership/internal/types/expected_keepers.go +++ b/x/ownership/internal/types/expected_keepers.go @@ -16,4 +16,5 @@ type ParamSubspace interface { // BankKeeper module interface. type BankKeeper interface { SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins } From b1216a91c7337a12fa776487c4a7fc44bd8cd195 Mon Sep 17 00:00:00 2001 From: krhubert Date: Fri, 28 Feb 2020 20:50:31 +0100 Subject: [PATCH 03/17] Add runner to ownership list --- ownership/ownership.pb.go | 47 +++++++++++---------- protobuf/types/ownership.proto | 1 + x/runner/internal/keeper/keeper.go | 22 +++++++--- x/runner/internal/types/expected_keepers.go | 6 +++ 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/ownership/ownership.pb.go b/ownership/ownership.pb.go index 86a57b02f..b35c324db 100644 --- a/ownership/ownership.pb.go +++ b/ownership/ownership.pb.go @@ -29,18 +29,21 @@ const ( Ownership_None Ownership_Resource = 0 Ownership_Service Ownership_Resource = 1 Ownership_Process Ownership_Resource = 2 + Ownership_Runner Ownership_Resource = 3 ) var Ownership_Resource_name = map[int32]string{ 0: "None", 1: "Service", 2: "Process", + 3: "Runner", } var Ownership_Resource_value = map[string]int32{ "None": 0, "Service": 1, "Process": 2, + "Runner": 3, } func (x Ownership_Resource) String() string { @@ -98,28 +101,28 @@ func init() { func init() { proto.RegisterFile("ownership.proto", fileDescriptor_21ae26e0dccf9d04) } var fileDescriptor_21ae26e0dccf9d04 = []byte{ - // 326 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x51, 0x4f, 0x4e, 0x32, 0x31, - 0x14, 0x67, 0x80, 0xef, 0x13, 0x2a, 0x2a, 0xe9, 0x6a, 0x62, 0x0c, 0x33, 0x36, 0x31, 0x21, 0x31, - 0x74, 0x12, 0x88, 0x9b, 0x71, 0x47, 0x5c, 0xb8, 0x52, 0x33, 0xec, 0xdc, 0x0d, 0xc3, 0xa3, 0x6d, - 0x22, 0x2d, 0xb6, 0x33, 0x18, 0x4f, 0xe0, 0x55, 0x3c, 0x0a, 0x67, 0x70, 0x31, 0x89, 0x1e, 0x81, - 0x13, 0x98, 0x16, 0x41, 0x4d, 0x5c, 0x18, 0x77, 0xfd, 0xbd, 0xfc, 0xfe, 0xf5, 0x3d, 0x74, 0xa0, - 0x1e, 0x24, 0x68, 0xc3, 0xc5, 0x9c, 0xce, 0xb5, 0xca, 0x15, 0x46, 0x33, 0x30, 0x8c, 0xe6, 0x8f, - 0x73, 0x30, 0x87, 0x84, 0x29, 0xa6, 0x22, 0x37, 0x1f, 0x17, 0xd3, 0xc8, 0x22, 0x07, 0xdc, 0x6b, - 0xcd, 0x27, 0x4f, 0x35, 0xd4, 0xbc, 0xde, 0x78, 0x60, 0x86, 0xea, 0x3c, 0x35, 0xdc, 0xf7, 0x42, - 0xaf, 0xdb, 0x1a, 0x8e, 0x96, 0x65, 0x50, 0x79, 0x29, 0x83, 0x53, 0x26, 0x72, 0x5e, 0x8c, 0x69, - 0xa6, 0x66, 0x91, 0xb5, 0xef, 0x4d, 0x55, 0x21, 0x27, 0x69, 0x2e, 0x94, 0x8c, 0x40, 0x32, 0x21, - 0x21, 0xb2, 0x2a, 0x7a, 0x99, 0x1a, 0xbe, 0x2a, 0x83, 0x23, 0x0b, 0x62, 0xd2, 0x23, 0xe1, 0x22, - 0xbd, 0x13, 0x93, 0x34, 0x87, 0x98, 0x68, 0xb8, 0x2f, 0x84, 0x86, 0x09, 0x49, 0x5c, 0x00, 0x3e, - 0x47, 0xff, 0x5c, 0x73, 0xbf, 0x1a, 0x7a, 0xdd, 0xe6, 0xf0, 0x64, 0x55, 0x06, 0xc7, 0x6b, 0x99, - 0x4c, 0x67, 0x10, 0xf7, 0x7f, 0xd6, 0xae, 0x35, 0x98, 0xa3, 0x96, 0x06, 0xa3, 0x0a, 0x9d, 0x81, - 0x8d, 0xf4, 0x6b, 0xae, 0xed, 0xc5, 0xdf, 0xda, 0xee, 0x7d, 0x89, 0x1d, 0x90, 0xe4, 0x9b, 0x33, - 0x8e, 0x51, 0x63, 0x83, 0xfd, 0x7a, 0xe8, 0x75, 0xf7, 0xfb, 0x1d, 0xfa, 0xb9, 0x60, 0xba, 0x5d, - 0x1c, 0x4d, 0x3e, 0x58, 0xc9, 0x96, 0x4f, 0x28, 0x6a, 0x6c, 0xa6, 0xb8, 0x81, 0xea, 0x57, 0x4a, - 0x42, 0xbb, 0x82, 0x77, 0xd1, 0xce, 0x08, 0xf4, 0x42, 0x64, 0xd0, 0xf6, 0x2c, 0xb8, 0xd1, 0x2a, - 0x03, 0x63, 0xda, 0xd5, 0xe1, 0xd9, 0xf2, 0xb5, 0x53, 0x79, 0x7e, 0xeb, 0x78, 0xb7, 0xbf, 0xf8, - 0xc1, 0xf6, 0xec, 0xe3, 0xff, 0xee, 0x8e, 0x83, 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2d, 0x23, - 0xcb, 0x4c, 0x0a, 0x02, 0x00, 0x00, + // 334 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xcf, 0x4e, 0xc2, 0x30, + 0x18, 0x67, 0x80, 0x08, 0x9f, 0xa8, 0x4b, 0x4f, 0x8b, 0x31, 0x6c, 0x36, 0x31, 0x21, 0x31, 0x74, + 0x09, 0xc4, 0xcb, 0xbc, 0x11, 0x0f, 0x9e, 0xd4, 0x8c, 0x9b, 0xb7, 0x31, 0x3e, 0xb6, 0x26, 0xd2, + 0x62, 0xbb, 0x61, 0x7c, 0x0e, 0x5f, 0xc2, 0x47, 0xe1, 0x19, 0x3c, 0x2c, 0xd1, 0x47, 0xe0, 0x09, + 0xcc, 0x8a, 0xa0, 0x26, 0x1e, 0x8c, 0xb7, 0xfe, 0xbe, 0xfc, 0xfe, 0xf5, 0x6b, 0xe1, 0x50, 0x3e, + 0x0a, 0x54, 0x3a, 0xe5, 0x73, 0x36, 0x57, 0x32, 0x93, 0x04, 0x66, 0xa8, 0x13, 0x96, 0x3d, 0xcd, + 0x51, 0x1f, 0xd1, 0x44, 0x26, 0xd2, 0x37, 0xf3, 0x71, 0x3e, 0xf5, 0x4b, 0x64, 0x80, 0x39, 0xad, + 0xf9, 0xf4, 0xb9, 0x06, 0xad, 0x9b, 0x8d, 0x07, 0x49, 0xa0, 0x9e, 0x46, 0x3a, 0x75, 0x2c, 0xcf, + 0xea, 0xb6, 0x87, 0xa3, 0x65, 0xe1, 0x56, 0x5e, 0x0b, 0xf7, 0x2c, 0xe1, 0x59, 0x9a, 0x8f, 0x59, + 0x2c, 0x67, 0x7e, 0x69, 0xdf, 0x9b, 0xca, 0x5c, 0x4c, 0xa2, 0x8c, 0x4b, 0xe1, 0xa3, 0x48, 0xb8, + 0x40, 0xbf, 0x54, 0xb1, 0xab, 0x48, 0xa7, 0xab, 0xc2, 0x3d, 0x2e, 0x41, 0x40, 0x7b, 0xd4, 0x5b, + 0x44, 0xf7, 0x7c, 0x12, 0x65, 0x18, 0x50, 0x85, 0x0f, 0x39, 0x57, 0x38, 0xa1, 0xa1, 0x09, 0x20, + 0x17, 0xb0, 0x63, 0x9a, 0x3b, 0x55, 0xcf, 0xea, 0xb6, 0x86, 0xa7, 0xab, 0xc2, 0x3d, 0x59, 0xcb, + 0x44, 0x34, 0xc3, 0xa0, 0xff, 0xbb, 0x76, 0xad, 0x21, 0x29, 0xb4, 0x15, 0x6a, 0x99, 0xab, 0x18, + 0xcb, 0x48, 0xa7, 0x66, 0xda, 0x5e, 0xfe, 0xaf, 0xed, 0xfe, 0xb7, 0xd8, 0x01, 0x0d, 0x7f, 0x38, + 0x93, 0x00, 0x9a, 0x1b, 0xec, 0xd4, 0x3d, 0xab, 0x7b, 0xd0, 0xef, 0xb0, 0xaf, 0x05, 0xb3, 0xed, + 0xe2, 0x58, 0xf8, 0xc9, 0x0a, 0xb7, 0x7c, 0x1a, 0x40, 0x73, 0x33, 0x25, 0x4d, 0xa8, 0x5f, 0x4b, + 0x81, 0x76, 0x85, 0xec, 0xc1, 0xee, 0x08, 0xd5, 0x82, 0xc7, 0x68, 0x5b, 0x25, 0xb8, 0x55, 0x32, + 0x46, 0xad, 0xed, 0x2a, 0x01, 0x68, 0x84, 0xb9, 0x10, 0xa8, 0xec, 0xda, 0xf0, 0x7c, 0xf9, 0xd6, + 0xa9, 0xbc, 0xbc, 0x77, 0xac, 0xbb, 0x3f, 0xdc, 0x66, 0xfb, 0x05, 0xc6, 0x0d, 0xf3, 0xa6, 0x83, + 0x8f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xb7, 0x4e, 0x6e, 0x16, 0x02, 0x00, 0x00, } func (this *Ownership) Equal(that interface{}) bool { diff --git a/protobuf/types/ownership.proto b/protobuf/types/ownership.proto index 6f8f8da95..9cfce7ecb 100644 --- a/protobuf/types/ownership.proto +++ b/protobuf/types/ownership.proto @@ -35,6 +35,7 @@ message Ownership { None = 0; Service = 1; Process = 2; + Runner = 3; } // Resource's type. diff --git a/x/runner/internal/keeper/keeper.go b/x/runner/internal/keeper/keeper.go index dc9bf1908..811676fd5 100644 --- a/x/runner/internal/keeper/keeper.go +++ b/x/runner/internal/keeper/keeper.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/mesg-foundation/engine/hash" + ownershippb "github.com/mesg-foundation/engine/ownership" "github.com/mesg-foundation/engine/runner" "github.com/mesg-foundation/engine/x/runner/internal/types" "github.com/tendermint/tendermint/libs/log" @@ -14,17 +15,19 @@ import ( // Keeper of the runner store type Keeper struct { - storeKey sdk.StoreKey - cdc *codec.Codec - instanceKeeper types.InstanceKeeper + storeKey sdk.StoreKey + cdc *codec.Codec + instanceKeeper types.InstanceKeeper + ownershipKeeper types.OwnershipKeeper } // NewKeeper creates a runner keeper -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, instanceKeeper types.InstanceKeeper) Keeper { +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, instanceKeeper types.InstanceKeeper, ownershipKeeper types.OwnershipKeeper) Keeper { keeper := Keeper{ - storeKey: key, - cdc: cdc, - instanceKeeper: instanceKeeper, + storeKey: key, + cdc: cdc, + instanceKeeper: instanceKeeper, + ownershipKeeper: ownershipKeeper, } return keeper } @@ -55,6 +58,11 @@ func (k Keeper) Create(ctx sdk.Context, msg *types.MsgCreateRunner) (*runner.Run if err != nil { return nil, err } + + if _, err := k.ownershipKeeper.Set(ctx, msg.Address, r.Hash, ownershippb.Ownership_Runner); err != nil { + return nil, err + } + store.Set(r.Hash, value) return r, nil } diff --git a/x/runner/internal/types/expected_keepers.go b/x/runner/internal/types/expected_keepers.go index 5b0fd210b..ba78e5caf 100644 --- a/x/runner/internal/types/expected_keepers.go +++ b/x/runner/internal/types/expected_keepers.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/params" "github.com/mesg-foundation/engine/hash" "github.com/mesg-foundation/engine/instance" + ownershippb "github.com/mesg-foundation/engine/ownership" ) // ParamSubspace defines the expected Subspace interfacace @@ -19,3 +20,8 @@ type ParamSubspace interface { type InstanceKeeper interface { FetchOrCreate(ctx sdk.Context, serviceHash hash.Hash, envHash hash.Hash) (*instance.Instance, error) } + +// OwnershipKeeper module interface. +type OwnershipKeeper interface { + Set(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash, resource ownershippb.Ownership_Resource) (*ownershippb.Ownership, error) +} From 688ed718d3d2e5416e5b557924a20a8032ae814b Mon Sep 17 00:00:00 2001 From: krhubert Date: Fri, 28 Feb 2020 20:58:00 +0100 Subject: [PATCH 04/17] Fix build error --- app/app.go | 2 +- x/ownership/internal/keeper/keeper.go | 2 +- x/ownership/internal/types/expected_keepers.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/app.go b/app/app.go index 112c9523e..ddb0c6f94 100644 --- a/app/app.go +++ b/app/app.go @@ -245,7 +245,7 @@ func NewInitApp( app.instanceKeeper = instance.NewKeeper(app.cdc, keys[instance.StoreKey]) app.processKeeper = process.NewKeeper(app.cdc, keys[process.StoreKey], app.instanceKeeper, app.ownershipKeeper) app.serviceKeeper = service.NewKeeper(app.cdc, keys[service.StoreKey], app.ownershipKeeper) - app.runnerKeeper = runner.NewKeeper(app.cdc, keys[runner.StoreKey], app.instanceKeeper) + app.runnerKeeper = runner.NewKeeper(app.cdc, keys[runner.StoreKey], app.instanceKeeper, app.ownershipKeeper) app.executionKeeper = execution.NewKeeper(app.cdc, keys[execution.StoreKey], app.bankKeeper, app.serviceKeeper, app.instanceKeeper, app.runnerKeeper, app.processKeeper) // NOTE: Any module instantiated in the module manager that is later modified diff --git a/x/ownership/internal/keeper/keeper.go b/x/ownership/internal/keeper/keeper.go index 6ca969870..1bb996023 100644 --- a/x/ownership/internal/keeper/keeper.go +++ b/x/ownership/internal/keeper/keeper.go @@ -84,7 +84,7 @@ func (k Keeper) Delete(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash. // transfer all spendable coins from resource address to owner addr := sdk.AccAddress(crypto.AddressHash(resourceHash)) - coins := k.bankKeeper.SpendableCoins(ctx, addr) + coins := k.bankKeeper.GetCoins(ctx, addr) if err := k.bankKeeper.SendCoins(ctx, addr, owner, coins); err != nil { return err } diff --git a/x/ownership/internal/types/expected_keepers.go b/x/ownership/internal/types/expected_keepers.go index 7e45036fe..c0d3713fc 100644 --- a/x/ownership/internal/types/expected_keepers.go +++ b/x/ownership/internal/types/expected_keepers.go @@ -16,5 +16,5 @@ type ParamSubspace interface { // BankKeeper module interface. type BankKeeper interface { SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error - SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins } From be164983c65df5ab67e92cefcd3fd678c518f807 Mon Sep 17 00:00:00 2001 From: krhubert Date: Mon, 2 Mar 2020 12:35:35 +0100 Subject: [PATCH 05/17] Add test for withdraw-coins --- core/main.go | 3 +- cosmos/client.go | 7 ++--- e2e/api_test.go | 18 ++++++++++-- e2e/execution_test.go | 43 ++++++++--------------------- e2e/process_test.go | 4 +-- x/ownership/internal/types/codec.go | 4 ++- 6 files changed, 38 insertions(+), 41 deletions(-) diff --git a/core/main.go b/core/main.go index aa6380459..0e00f3fd4 100644 --- a/core/main.go +++ b/core/main.go @@ -30,6 +30,7 @@ import ( "github.com/mesg-foundation/engine/server/grpc" "github.com/mesg-foundation/engine/version" "github.com/sirupsen/logrus" + rpcclient "github.com/tendermint/tendermint/rpc/client" rpcserver "github.com/tendermint/tendermint/rpc/lib/server" tmtypes "github.com/tendermint/tendermint/types" db "github.com/tendermint/tm-db" @@ -186,7 +187,7 @@ func main() { }() // create cosmos client - client, err := cosmos.NewClient(node, cdc, kb, genesis.ChainID, cfg.Account.Name, cfg.Account.Password, cfg.Cosmos.MinGasPrices) + client, err := cosmos.NewClient(rpcclient.NewLocal(node), cdc, kb, genesis.ChainID, cfg.Account.Name, cfg.Account.Password, cfg.Cosmos.MinGasPrices) if err != nil { logrus.WithField("module", "main").Fatalln(err) } diff --git a/cosmos/client.go b/cosmos/client.go index e040852db..081d757d1 100644 --- a/cosmos/client.go +++ b/cosmos/client.go @@ -19,14 +19,13 @@ import ( "github.com/mesg-foundation/engine/ext/xstrings" "github.com/mesg-foundation/engine/hash" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/node" rpcclient "github.com/tendermint/tendermint/rpc/client" tenderminttypes "github.com/tendermint/tendermint/types" ) // Client is a tendermint client with helper functions. type Client struct { - *rpcclient.Local + rpcclient.Client cdc *codec.Codec kb keys.Keybase chainID string @@ -41,13 +40,13 @@ type Client struct { } // NewClient returns a rpc tendermint client. -func NewClient(node *node.Node, cdc *codec.Codec, kb keys.Keybase, chainID, accName, accPassword, minGasPrices string) (*Client, error) { +func NewClient(client rpcclient.Client, cdc *codec.Codec, kb keys.Keybase, chainID, accName, accPassword, minGasPrices string) (*Client, error) { minGasPricesDecoded, err := sdktypes.ParseDecCoins(minGasPrices) if err != nil { return nil, err } return &Client{ - Local: rpcclient.NewLocal(node), + Client: client, cdc: cdc, kb: kb, chainID: chainID, diff --git a/e2e/api_test.go b/e2e/api_test.go index 5dcb2db13..ccd9448d4 100644 --- a/e2e/api_test.go +++ b/e2e/api_test.go @@ -5,6 +5,7 @@ import ( "context" "io/ioutil" "net/http" + "path/filepath" "testing" "github.com/cosmos/cosmos-sdk/types/rest" @@ -13,6 +14,7 @@ import ( "github.com/mesg-foundation/engine/cosmos" pb "github.com/mesg-foundation/engine/protobuf/api" "github.com/stretchr/testify/require" + rpcclient "github.com/tendermint/tendermint/rpc/client" "google.golang.org/grpc" ) @@ -27,8 +29,9 @@ type apiclient struct { } var ( - client apiclient - cdc = app.MakeCodec() + client apiclient + cclient *cosmos.Client + cdc = app.MakeCodec() ) const ( @@ -64,6 +67,10 @@ func lcdPost(t *testing.T, path string, req interface{}, ptr interface{}) { } } +func c() { + +} + func TestAPI(t *testing.T) { if testing.Short() { t.Skip() @@ -78,6 +85,13 @@ func TestAPI(t *testing.T) { conn, err := grpc.DialContext(context.Background(), "localhost:50052", grpc.WithInsecure()) require.NoError(t, err) + httpclient, err := rpcclient.NewHTTP("http://localhost:26657", "/websocket") + require.NoError(t, err) + kb, err := cosmos.NewKeybase(filepath.Join(cfg.Path, cfg.Cosmos.RelativePath)) + require.NoError(t, err) + cclient, err = cosmos.NewClient(httpclient, cdc, kb, cfg.DevGenesis.ChainID, cfg.Account.Name, cfg.Account.Password, cfg.Cosmos.MinGasPrices) + require.NoError(t, err) + client = apiclient{ pb.NewServiceClient(conn), pb.NewEventClient(conn), diff --git a/e2e/execution_test.go b/e2e/execution_test.go index 88f272687..32f92ffcd 100644 --- a/e2e/execution_test.go +++ b/e2e/execution_test.go @@ -2,18 +2,16 @@ package main import ( "context" - "fmt" "sync" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/mesg-foundation/engine/execution" "github.com/mesg-foundation/engine/hash" - "github.com/mesg-foundation/engine/ownership" "github.com/mesg-foundation/engine/protobuf/acknowledgement" pb "github.com/mesg-foundation/engine/protobuf/api" "github.com/mesg-foundation/engine/protobuf/types" - "github.com/stretchr/testify/assert" + "github.com/mesg-foundation/engine/x/ownership" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" ) @@ -254,37 +252,20 @@ func testExecution(t *testing.T) { // check balance of execution t.Run("withdraw from service", func(t *testing.T) { - var os []*ownership.Ownership - lcdGet(t, "ownership/list", &os) - - var owner string - for _, o := range os { - if o.ResourceHash.Equal(testServiceHash) { - owner = o.Owner - break - } - } - assert.NotEmpty(t, owner) - - withdrawCoinsReq := struct { - Amount string `json:"amount"` - Hash hash.Hash `json:"hash"` - Owner string `json:"owner"` - }{"5atto", testServiceHash, owner} - - lcdPost(t, "ownership/withdraw-coins", withdrawCoinsReq, nil) + acc, err := cclient.GetAccount() + require.NoError(t, err) + coins := sdk.NewCoins(sdk.NewCoin("atto", sdk.NewInt(5))) + _, err = cclient.BuildAndBroadcastMsg(ownership.NewMsgWithdrawCoins(testServiceHash, coins, acc.GetAddress())) + require.NoError(t, err) - coins := sdk.Coins{} + // coins := sdk.Coins{} - serviceAddress := sdk.AccAddress(crypto.AddressHash(testServiceHash)) - lcdGet(t, "bank/balances/"+serviceAddress.String(), &coins) - fmt.Println(coins) - // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(0))) + // serviceAddress := sdk.AccAddress(crypto.AddressHash(testServiceHash)) + // lcdGet(t, "bank/balances/"+serviceAddress.String(), &coins) + // // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(0))) - lcdGet(t, "bank/balances/"+owner, &coins) - fmt.Println(coins) - t.FailNow() - // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(5))) + // lcdGet(t, "bank/balances/"+owner, &coins) + // // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(5))) }) }) diff --git a/e2e/process_test.go b/e2e/process_test.go index 9856955db..0b1d89aff 100644 --- a/e2e/process_test.go +++ b/e2e/process_test.go @@ -124,12 +124,12 @@ func testProcess(t *testing.T) { t.Run("lcd", func(t *testing.T) { ownerships := make([]*ownership.Ownership, 0) lcdGet(t, "ownership/list", &ownerships) - require.Len(t, ownerships, 1) + require.Len(t, ownerships, 2) }) t.Run("grpc", func(t *testing.T) { ownerships, err := client.OwnershipClient.List(context.Background(), &pb.ListOwnershipRequest{}) require.NoError(t, err) - require.Len(t, ownerships.Ownerships, 1) + require.Len(t, ownerships.Ownerships, 2) }) }) } diff --git a/x/ownership/internal/types/codec.go b/x/ownership/internal/types/codec.go index b243782e1..eacaa243d 100644 --- a/x/ownership/internal/types/codec.go +++ b/x/ownership/internal/types/codec.go @@ -5,7 +5,9 @@ import ( ) // RegisterCodec registers concrete types on codec. -func RegisterCodec(cdc *codec.Codec) {} +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(MsgWithdrawCoins{}, "ownership/WithdrawCoins", nil) +} // ModuleCdc defines the module codec. var ModuleCdc *codec.Codec From c579c99d05a53f6cccf021ad30f5f460d1f3addd Mon Sep 17 00:00:00 2001 From: krhubert Date: Mon, 2 Mar 2020 18:05:20 +0100 Subject: [PATCH 06/17] Fixes --- cosmos/client.go | 4 ++-- e2e/api_test.go | 8 ++------ e2e/execution_test.go | 14 ++++---------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/cosmos/client.go b/cosmos/client.go index 081d757d1..18a05a786 100644 --- a/cosmos/client.go +++ b/cosmos/client.go @@ -92,7 +92,7 @@ func (c *Client) QueryWithData(path string, data []byte) ([]byte, int64, error) // BuildAndBroadcastMsg builds and signs message and broadcast it to node. func (c *Client) BuildAndBroadcastMsg(msg sdktypes.Msg) (*abci.ResponseDeliverTx, error) { c.broadcastMutex.Lock() // Lock the whole signature + broadcast of the transaction - signedTx, err := c.createAndSignTx([]sdktypes.Msg{msg}) + signedTx, err := c.CreateAndSignTx([]sdktypes.Msg{msg}) if err != nil { c.broadcastMutex.Unlock() return nil, err @@ -203,7 +203,7 @@ func (c *Client) GetAccount() (authExported.Account, error) { return c.acc, nil } -func (c *Client) createAndSignTx(msgs []sdktypes.Msg) (tenderminttypes.Tx, error) { +func (c *Client) CreateAndSignTx(msgs []sdktypes.Msg) (tenderminttypes.Tx, error) { // retrieve account accR, err := c.GetAccount() if err != nil { diff --git a/e2e/api_test.go b/e2e/api_test.go index ccd9448d4..498fcf6fa 100644 --- a/e2e/api_test.go +++ b/e2e/api_test.go @@ -67,10 +67,6 @@ func lcdPost(t *testing.T, path string, req interface{}, ptr interface{}) { } } -func c() { - -} - func TestAPI(t *testing.T) { if testing.Short() { t.Skip() @@ -85,10 +81,10 @@ func TestAPI(t *testing.T) { conn, err := grpc.DialContext(context.Background(), "localhost:50052", grpc.WithInsecure()) require.NoError(t, err) - httpclient, err := rpcclient.NewHTTP("http://localhost:26657", "/websocket") - require.NoError(t, err) kb, err := cosmos.NewKeybase(filepath.Join(cfg.Path, cfg.Cosmos.RelativePath)) require.NoError(t, err) + httpclient, err := rpcclient.NewHTTP("http://localhost:26657", "/websocket") + require.NoError(t, err) cclient, err = cosmos.NewClient(httpclient, cdc, kb, cfg.DevGenesis.ChainID, cfg.Account.Name, cfg.Account.Password, cfg.Cosmos.MinGasPrices) require.NoError(t, err) diff --git a/e2e/execution_test.go b/e2e/execution_test.go index 32f92ffcd..ca9bdf3e6 100644 --- a/e2e/execution_test.go +++ b/e2e/execution_test.go @@ -255,17 +255,11 @@ func testExecution(t *testing.T) { acc, err := cclient.GetAccount() require.NoError(t, err) coins := sdk.NewCoins(sdk.NewCoin("atto", sdk.NewInt(5))) - _, err = cclient.BuildAndBroadcastMsg(ownership.NewMsgWithdrawCoins(testServiceHash, coins, acc.GetAddress())) + msg := ownership.NewMsgWithdrawCoins(testServiceHash, coins, acc.GetAddress()) + signed, err := cclient.CreateAndSignTx([]sdk.Msg{msg}) + require.NoError(t, err) + _, err = cclient.BroadcastTxSync(signed) require.NoError(t, err) - - // coins := sdk.Coins{} - - // serviceAddress := sdk.AccAddress(crypto.AddressHash(testServiceHash)) - // lcdGet(t, "bank/balances/"+serviceAddress.String(), &coins) - // // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(0))) - - // lcdGet(t, "bank/balances/"+owner, &coins) - // // require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(5))) }) }) From 8c943a622c2da3292193c328e3a2a17ee98a19b5 Mon Sep 17 00:00:00 2001 From: krhubert Date: Tue, 3 Mar 2020 11:14:44 +0100 Subject: [PATCH 07/17] Remove runner owner on deletion --- e2e/runner_test.go | 11 +++++++++++ x/runner/internal/keeper/keeper.go | 12 ++++++++---- x/runner/internal/types/expected_keepers.go | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/e2e/runner_test.go b/e2e/runner_test.go index bfd6650b4..02642eed4 100644 --- a/e2e/runner_test.go +++ b/e2e/runner_test.go @@ -35,6 +35,17 @@ func testRunner(t *testing.T) { require.NoError(t, err) }) + t.Run("recreate", func(t *testing.T) { + _, err := client.RunnerClient.Delete(context.Background(), &pb.DeleteRunnerRequest{Hash: testRunnerHash}) + require.NoError(t, err) + resp, err := client.RunnerClient.Create(context.Background(), &pb.CreateRunnerRequest{ + ServiceHash: testServiceHash, + Env: []string{"BAR=3", "REQUIRED=4"}, + }) + require.NoError(t, err) + testRunnerHash = resp.Hash + }) + t.Run("get", func(t *testing.T) { t.Run("grpc", func(t *testing.T) { resp, err := client.RunnerClient.Get(context.Background(), &pb.GetRunnerRequest{Hash: testRunnerHash}) diff --git a/x/runner/internal/keeper/keeper.go b/x/runner/internal/keeper/keeper.go index 811676fd5..4d0187b4c 100644 --- a/x/runner/internal/keeper/keeper.go +++ b/x/runner/internal/keeper/keeper.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/mesg-foundation/engine/hash" ownershippb "github.com/mesg-foundation/engine/ownership" "github.com/mesg-foundation/engine/runner" @@ -42,7 +43,7 @@ func (k Keeper) Create(ctx sdk.Context, msg *types.MsgCreateRunner) (*runner.Run store := ctx.KVStore(k.storeKey) inst, err := k.instanceKeeper.FetchOrCreate(ctx, msg.ServiceHash, msg.EnvHash) if err != nil { - return nil, err + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) } r := &runner.Runner{ @@ -51,16 +52,16 @@ func (k Keeper) Create(ctx sdk.Context, msg *types.MsgCreateRunner) (*runner.Run } r.Hash = hash.Dump(r) if store.Has(r.Hash) { - return nil, fmt.Errorf("runner %q already exists", r.Hash) + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "runner %q already exists", r.Hash) } value, err := k.cdc.MarshalBinaryLengthPrefixed(r) if err != nil { - return nil, err + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) } if _, err := k.ownershipKeeper.Set(ctx, msg.Address, r.Hash, ownershippb.Ownership_Runner); err != nil { - return nil, err + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) } store.Set(r.Hash, value) @@ -82,6 +83,9 @@ func (k Keeper) Delete(ctx sdk.Context, msg *types.MsgDeleteRunner) error { if r.Address != msg.Address.String() { return errors.New("only the runner owner can remove itself") } + if err := k.ownershipKeeper.Delete(ctx, msg.Address, r.Hash); err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } store.Delete(msg.RunnerHash) return nil } diff --git a/x/runner/internal/types/expected_keepers.go b/x/runner/internal/types/expected_keepers.go index ba78e5caf..8814d2286 100644 --- a/x/runner/internal/types/expected_keepers.go +++ b/x/runner/internal/types/expected_keepers.go @@ -24,4 +24,5 @@ type InstanceKeeper interface { // OwnershipKeeper module interface. type OwnershipKeeper interface { Set(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash, resource ownershippb.Ownership_Resource) (*ownershippb.Ownership, error) + Delete(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash.Hash) error } From 8a7ab55c5b45aa324a0420c5ad535df7fefcc7ef Mon Sep 17 00:00:00 2001 From: krhubert Date: Tue, 3 Mar 2020 13:16:54 +0100 Subject: [PATCH 08/17] Enable websocket event subscribe for tm http client --- e2e/api_test.go | 2 ++ e2e/execution_test.go | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/api_test.go b/e2e/api_test.go index 498fcf6fa..7d2e604c4 100644 --- a/e2e/api_test.go +++ b/e2e/api_test.go @@ -85,6 +85,8 @@ func TestAPI(t *testing.T) { require.NoError(t, err) httpclient, err := rpcclient.NewHTTP("http://localhost:26657", "/websocket") require.NoError(t, err) + require.NoError(t, httpclient.OnStart()) + defer httpclient.Stop() cclient, err = cosmos.NewClient(httpclient, cdc, kb, cfg.DevGenesis.ChainID, cfg.Account.Name, cfg.Account.Password, cfg.Cosmos.MinGasPrices) require.NoError(t, err) diff --git a/e2e/execution_test.go b/e2e/execution_test.go index d3e1ddd5a..3590e43ee 100644 --- a/e2e/execution_test.go +++ b/e2e/execution_test.go @@ -262,9 +262,7 @@ func testExecution(t *testing.T) { require.NoError(t, err) coins := sdk.NewCoins(sdk.NewCoin("atto", sdk.NewInt(5))) msg := ownership.NewMsgWithdrawCoins(testServiceHash, coins, acc.GetAddress()) - signed, err := cclient.CreateAndSignTx([]sdk.Msg{msg}) - require.NoError(t, err) - _, err = cclient.BroadcastTxSync(signed) + _, err = cclient.BuildAndBroadcastMsg(msg) require.NoError(t, err) }) }) From a89199d636e117a6e58f0eac143ba00b7a165ab3 Mon Sep 17 00:00:00 2001 From: krhubert Date: Tue, 3 Mar 2020 13:22:15 +0100 Subject: [PATCH 09/17] Add docs --- cosmos/client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cosmos/client.go b/cosmos/client.go index 18a05a786..8310f7dde 100644 --- a/cosmos/client.go +++ b/cosmos/client.go @@ -203,6 +203,7 @@ func (c *Client) GetAccount() (authExported.Account, error) { return c.acc, nil } +// CreateAndSignTx build and sign a msg with client account. func (c *Client) CreateAndSignTx(msgs []sdktypes.Msg) (tenderminttypes.Tx, error) { // retrieve account accR, err := c.GetAccount() From 2485919b9f5283b3ac541d63fc40ab3fd2f33b63 Mon Sep 17 00:00:00 2001 From: krhubert Date: Tue, 3 Mar 2020 13:28:09 +0100 Subject: [PATCH 10/17] Create user in keybase for e2e tests --- e2e/api_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/e2e/api_test.go b/e2e/api_test.go index 7d2e604c4..f23dcac38 100644 --- a/e2e/api_test.go +++ b/e2e/api_test.go @@ -8,6 +8,7 @@ import ( "path/filepath" "testing" + "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/types/rest" "github.com/mesg-foundation/engine/app" "github.com/mesg-foundation/engine/config" @@ -73,9 +74,8 @@ func TestAPI(t *testing.T) { } cfg, err := config.New() - if err != nil { - panic(err) - } + require.NoError(t, err) + cosmos.CustomizeConfig(cfg) conn, err := grpc.DialContext(context.Background(), "localhost:50052", grpc.WithInsecure()) @@ -83,6 +83,11 @@ func TestAPI(t *testing.T) { kb, err := cosmos.NewKeybase(filepath.Join(cfg.Path, cfg.Cosmos.RelativePath)) require.NoError(t, err) + if cfg.Account.Mnemonic != "" { + _, err = kb.CreateAccount(cfg.Account.Name, cfg.Account.Mnemonic, "", cfg.Account.Password, keys.CreateHDPath(cfg.Account.Number, cfg.Account.Index).String(), cosmos.DefaultAlgo) + require.NoError(t, err) + } + httpclient, err := rpcclient.NewHTTP("http://localhost:26657", "/websocket") require.NoError(t, err) require.NoError(t, httpclient.OnStart()) From 7d0a16491bbcde85ef27e6785382b4f55eb43d2c Mon Sep 17 00:00:00 2001 From: krhubert Date: Wed, 4 Mar 2020 07:21:14 +0100 Subject: [PATCH 11/17] Check service balance after withdraw --- e2e/execution_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/e2e/execution_test.go b/e2e/execution_test.go index 3590e43ee..368e12eae 100644 --- a/e2e/execution_test.go +++ b/e2e/execution_test.go @@ -6,6 +6,7 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" "github.com/mesg-foundation/engine/execution" "github.com/mesg-foundation/engine/hash" "github.com/mesg-foundation/engine/protobuf/acknowledgement" @@ -260,10 +261,14 @@ func testExecution(t *testing.T) { t.Run("withdraw from service", func(t *testing.T) { acc, err := cclient.GetAccount() require.NoError(t, err) - coins := sdk.NewCoins(sdk.NewCoin("atto", sdk.NewInt(5))) + coins := sdk.NewCoins(sdk.NewCoin("atto", sdk.NewInt(7000))) msg := ownership.NewMsgWithdrawCoins(testServiceHash, coins, acc.GetAddress()) _, err = cclient.BuildAndBroadcastMsg(msg) require.NoError(t, err) + + param := bank.NewQueryBalanceParams(sdk.AccAddress(crypto.AddressHash(testServiceHash))) + require.NoError(t, cclient.QueryJSON("custom/bank/balances", param, &coins)) + require.True(t, coins.IsZero(), coins) }) }) From 0e0320b0b883da7bc307a506d306994f7a830002 Mon Sep 17 00:00:00 2001 From: krhubert Date: Wed, 4 Mar 2020 08:41:41 +0100 Subject: [PATCH 12/17] Fix e2e dir permissions --- e2e/api_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/e2e/api_test.go b/e2e/api_test.go index f23dcac38..2cbddd0f1 100644 --- a/e2e/api_test.go +++ b/e2e/api_test.go @@ -5,6 +5,7 @@ import ( "context" "io/ioutil" "net/http" + "os" "path/filepath" "testing" @@ -81,6 +82,11 @@ func TestAPI(t *testing.T) { conn, err := grpc.DialContext(context.Background(), "localhost:50052", grpc.WithInsecure()) require.NoError(t, err) + // change and recreate cosmos relative path because CI dir permissions + cfg.Cosmos.RelativePath = "e2e.cosmos" + err = os.MkdirAll(filepath.Join(cfg.Path, cfg.Cosmos.RelativePath), os.FileMode(0755)) + require.NoError(t, err) + kb, err := cosmos.NewKeybase(filepath.Join(cfg.Path, cfg.Cosmos.RelativePath)) require.NoError(t, err) if cfg.Account.Mnemonic != "" { @@ -90,7 +96,7 @@ func TestAPI(t *testing.T) { httpclient, err := rpcclient.NewHTTP("http://localhost:26657", "/websocket") require.NoError(t, err) - require.NoError(t, httpclient.OnStart()) + require.NoError(t, httpclient.Start()) defer httpclient.Stop() cclient, err = cosmos.NewClient(httpclient, cdc, kb, cfg.DevGenesis.ChainID, cfg.Account.Name, cfg.Account.Password, cfg.Cosmos.MinGasPrices) require.NoError(t, err) From 718aba319d3aa610a6bc7bf698524f59524e950d Mon Sep 17 00:00:00 2001 From: krhubert Date: Wed, 4 Mar 2020 09:14:10 +0100 Subject: [PATCH 13/17] Add e2e test for withdraw from runner --- e2e/execution_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/e2e/execution_test.go b/e2e/execution_test.go index 368e12eae..dd7f43d9b 100644 --- a/e2e/execution_test.go +++ b/e2e/execution_test.go @@ -270,6 +270,19 @@ func testExecution(t *testing.T) { require.NoError(t, cclient.QueryJSON("custom/bank/balances", param, &coins)) require.True(t, coins.IsZero(), coins) }) + + t.Run("withdraw from runner", func(t *testing.T) { + acc, err := cclient.GetAccount() + require.NoError(t, err) + coins := sdk.NewCoins(sdk.NewCoin("atto", sdk.NewInt(63000))) + msg := ownership.NewMsgWithdrawCoins(testRunnerHash, coins, acc.GetAddress()) + _, err = cclient.BuildAndBroadcastMsg(msg) + require.NoError(t, err) + + param := bank.NewQueryBalanceParams(sdk.AccAddress(crypto.AddressHash(testRunnerHash))) + require.NoError(t, cclient.QueryJSON("custom/bank/balances", param, &coins)) + require.True(t, coins.IsZero(), coins) + }) }) t.Run("many executions in parallel", func(t *testing.T) { From ae7b5ee9ecc1346b9f4bc7e438dff5d740eb6e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Mah=C3=A9?= Date: Wed, 4 Mar 2020 15:41:35 +0700 Subject: [PATCH 14/17] Remove wrong comment in test --- e2e/execution_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/execution_test.go b/e2e/execution_test.go index dd7f43d9b..4674b1916 100644 --- a/e2e/execution_test.go +++ b/e2e/execution_test.go @@ -257,7 +257,6 @@ func testExecution(t *testing.T) { require.True(t, coins.AmountOf("atto").Equal(sdk.NewInt(0))) }) - // check balance of execution t.Run("withdraw from service", func(t *testing.T) { acc, err := cclient.GetAccount() require.NoError(t, err) From 37fef319dab2e0b645e7879d56d6b71e31e648c7 Mon Sep 17 00:00:00 2001 From: Nicolas Mahe Date: Wed, 4 Mar 2020 16:11:19 +0700 Subject: [PATCH 15/17] Simplify ownership rest tx message by using directly BaseReq.From --- x/ownership/client/rest/tx.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/ownership/client/rest/tx.go b/x/ownership/client/rest/tx.go index 4b953412b..ef371501b 100644 --- a/x/ownership/client/rest/tx.go +++ b/x/ownership/client/rest/tx.go @@ -16,7 +16,6 @@ type withdrawCoinsReq struct { BaseReq rest.BaseReq `json:"base_req"` Amount string `json:"amount"` Hash hash.Hash `json:"hash"` - Owner string `json:"owner"` } func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { @@ -40,7 +39,7 @@ func txWithdrawCoinsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return } - owner, err := sdk.AccAddressFromBech32(req.Owner) + owner, err := sdk.AccAddressFromBech32(baseReq.From) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return From 75121e32bb8ece81db7a62dbea80fd02741d40a7 Mon Sep 17 00:00:00 2001 From: Nicolas Mahe Date: Wed, 4 Mar 2020 16:11:40 +0700 Subject: [PATCH 16/17] Register withdraw coins command to ownership commands --- x/ownership/client/cli/tx.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x/ownership/client/cli/tx.go b/x/ownership/client/cli/tx.go index 6b8717891..c3df07e36 100644 --- a/x/ownership/client/cli/tx.go +++ b/x/ownership/client/cli/tx.go @@ -26,7 +26,9 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - ownershipTxCmd.AddCommand(flags.PostCommands()...) + ownershipTxCmd.AddCommand(flags.PostCommands( + GetCmdWithdrawCoins(cdc), + )...) return ownershipTxCmd } From 7affbbabe5057a599061c9f969b45bb5dec5e1d0 Mon Sep 17 00:00:00 2001 From: krhubert Date: Wed, 4 Mar 2020 11:23:03 +0100 Subject: [PATCH 17/17] Send coins only if not zero --- x/ownership/internal/keeper/keeper.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x/ownership/internal/keeper/keeper.go b/x/ownership/internal/keeper/keeper.go index 1bb996023..53e3c7c29 100644 --- a/x/ownership/internal/keeper/keeper.go +++ b/x/ownership/internal/keeper/keeper.go @@ -85,8 +85,10 @@ func (k Keeper) Delete(ctx sdk.Context, owner sdk.AccAddress, resourceHash hash. // transfer all spendable coins from resource address to owner addr := sdk.AccAddress(crypto.AddressHash(resourceHash)) coins := k.bankKeeper.GetCoins(ctx, addr) - if err := k.bankKeeper.SendCoins(ctx, addr, owner, coins); err != nil { - return err + if !coins.IsZero() { + if err := k.bankKeeper.SendCoins(ctx, addr, owner, coins); err != nil { + return err + } } // remove all ownerships