Remove ServiceMsgs from ADR-031 (#9139)
* wip * wip * wip * wip on refactoring adr 031 type URLs * Fix msg_service_router * Fix gov client queries * Fix some modules tests * Remove all instances of "*.Msg/*" * Uncomment code * Remove commented code * // simulation.NewWeightedOperation( * Fix CopyTx * Fix more tests * Fix x/gov test * proto.MessageName->sdk.MsgName * Fix authz tests * Use MsgRoute in feegrant and staking/authz * Fix more tests * Fix sims? * Add norace tag * Add CL * rebuild rosetta api test data * Update ADR * Rename MsgRoute -> MsgTypeURL * Fix codec registration * Remove sdk.GetLegacySignBytes * Update types/tx_msg.go * Update x/authz/simulation/operations.go * Move LegacyMsg to legacytx * Update CHANGELOG.md Co-authored-by: Aaron Craelius <aaron@regen.network> * Remove NewAnyWithCustomTypeURL * Keep support for ServiceMsgs * Fix TxBody UnpackInterfaces * Fix test * Address review * Remove support for ServiceMsg typeURLs * Fix lint * Update changelog * Fix tests * Use sdk.MsgTypeURL everywhere * Fix tests * Fix rosetta, run make rosetta-data * Fix rosetta thanks to froydi * Address reviews * Fix test * Remove stray log * Update CL Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com> Co-authored-by: Alessio Treglia <alessio@tendermint.com> Co-authored-by: Aaron Craelius <aaron@regen.network>
This commit is contained in:
parent
6fbded9664
commit
dfe3e7a8d7
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -37,7 +37,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
## [Unreleased]
|
||||
* [\#9205](https://github.com/cosmos/cosmos-sdk/pull/9205) Improve readability in `abci` handleQueryP2P
|
||||
|
||||
## Features
|
||||
### Features
|
||||
|
||||
* [\#8965](https://github.com/cosmos/cosmos-sdk/pull/8965) cosmos reflection now provides more information on the application such as: deliverable msgs, sdk.Config info etc (still in alpha stage).
|
||||
* [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Added Protobuf compatible secp256r1 ECDSA signatures.
|
||||
* [\#8786](https://github.com/cosmos/cosmos-sdk/pull/8786) Enabled secp256r1 in x/auth.
|
||||
|
@ -48,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
* (x/staking) [\#9214](https://github.com/cosmos/cosmos-sdk/pull/9214) Added `new_shares` attribute inside `EventTypeDelegate` event.
|
||||
|
||||
### Client Breaking Changes
|
||||
|
||||
* [\#8363](https://github.com/cosmos/cosmos-sdk/pull/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address.
|
||||
* [\#8346](https://github.com/cosmos/cosmos-sdk/pull/8346) All CLI `tx` commands generate ServiceMsgs by default. Graceful Amino support has been added to ServiceMsgs to support signing legacy Msgs.
|
||||
* (crypto/ed25519) [\#8690] Adopt zip1215 ed2559 verification rules.
|
||||
|
@ -59,6 +61,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
* CLI: removed `--text` flag from `show-node-id` command; the text format for public keys is not used any more - instead we use ProtoJSON.
|
||||
* (types) [\#9079](https://github.com/cosmos/cosmos-sdk/issues/9079) Add `AddAmount`/`SubAmount` methods to `sdk.Coin`.
|
||||
* [\#8628](https://github.com/cosmos/cosmos-sdk/issues/8628) Commands no longer print outputs using `stderr` by default
|
||||
* [\#9139](https://github.com/cosmos/cosmos-sdk/pull/9139) Querying events:
|
||||
* via `ServiceMsg` TypeURLs (e.g. `message.action='/cosmos.bank.v1beta1.Msg/Send'`) does not work anymore,
|
||||
* via legacy `msg.Type()` (e.g. `message.action='send'`) is being deprecated, new `Msg`s won't emit these events.
|
||||
* Please use concrete `Msg` TypeURLs instead (e.g. `message.action='/cosmos.bank.v1beta1.MsgSend'`).
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
|
@ -92,6 +98,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
* `codec.JSONMarshaler` → `codec.JSONCodec`
|
||||
* Removed `BinaryBare` suffix from `BinaryCodec` methods (`MarshalBinaryBare`, `UnmarshalBinaryBare`, ...)
|
||||
* Removed `Binary` infix from `BinaryCodec` methods (`MarshalBinaryLengthPrefixed`, `UnmarshalBinaryLengthPrefixed`, ...)
|
||||
* [\#9139](https://github.com/cosmos/cosmos-sdk/pull/9139) `ServiceMsg` TypeURLs (e.g. `/cosmos.bank.v1beta1.Msg/Send`) have been removed, as they don't comply to the Probobuf `Any` spec. Please use `Msg` type TypeURLs (e.g. `/cosmos.bank.v1beta1.MsgSend`). This has multiple consequences:
|
||||
* The `sdk.ServiceMsg` struct has been removed.
|
||||
* `sdk.Msg` now only contains `ValidateBasic` and `GetSigners` methods. The remaining methods `GetSignBytes`, `Route` and `Type` are moved to `legacytx.LegacyMsg`.
|
||||
* The `RegisterCustomTypeURL` function and the `cosmos.base.v1beta1.ServiceMsg` interface have been removed from the interface registry.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/store/rootmulti"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -703,37 +704,39 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s
|
|||
}
|
||||
|
||||
var (
|
||||
msgEvents sdk.Events
|
||||
msgResult *sdk.Result
|
||||
msgFqName string
|
||||
err error
|
||||
msgResult *sdk.Result
|
||||
eventMsgName string // name to use as value in event `message.action`
|
||||
err error
|
||||
)
|
||||
|
||||
if svcMsg, ok := msg.(sdk.ServiceMsg); ok {
|
||||
msgFqName = svcMsg.MethodName
|
||||
handler := app.msgServiceRouter.Handler(msgFqName)
|
||||
if handler == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message service method: %s; message index: %d", msgFqName, i)
|
||||
}
|
||||
msgResult, err = handler(ctx, svcMsg.Request)
|
||||
} else {
|
||||
if handler := app.msgServiceRouter.Handler(msg); handler != nil {
|
||||
// ADR 031 request type routing
|
||||
msgResult, err = handler(ctx, msg)
|
||||
eventMsgName = sdk.MsgTypeURL(msg)
|
||||
} else if legacyMsg, ok := msg.(legacytx.LegacyMsg); ok {
|
||||
// legacy sdk.Msg routing
|
||||
msgRoute := msg.Route()
|
||||
msgFqName = msg.Type()
|
||||
// Assuming that the app developer has migrated all their Msgs to
|
||||
// proto messages and has registered all `Msg services`, then this
|
||||
// path should never be called, because all those Msgs should be
|
||||
// registered within the `msgServiceRouter` already.
|
||||
msgRoute := legacyMsg.Route()
|
||||
eventMsgName = legacyMsg.Type()
|
||||
handler := app.router.Route(ctx, msgRoute)
|
||||
if handler == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
|
||||
}
|
||||
|
||||
msgResult, err = handler(ctx, msg)
|
||||
} else {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "can't route message %+v", msg)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i)
|
||||
}
|
||||
|
||||
msgEvents = sdk.Events{
|
||||
sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msgFqName)),
|
||||
msgEvents := sdk.Events{
|
||||
sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, eventMsgName)),
|
||||
}
|
||||
msgEvents = msgEvents.AppendEvents(msgResult.GetEvents())
|
||||
|
||||
|
@ -743,7 +746,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s
|
|||
// separate each result.
|
||||
events = events.AppendEvents(msgEvents)
|
||||
|
||||
txMsgData.Data = append(txMsgData.Data, &sdk.MsgData{MsgType: msg.Type(), Data: msgResult.Data})
|
||||
txMsgData.Data = append(txMsgData.Data, &sdk.MsgData{MsgType: sdk.MsgTypeURL(msg), Data: msgResult.Data})
|
||||
msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint32(i), msgResult.Log, msgEvents))
|
||||
}
|
||||
|
||||
|
|
|
@ -29,12 +29,17 @@ func NewMsgServiceRouter() *MsgServiceRouter {
|
|||
}
|
||||
|
||||
// MsgServiceHandler defines a function type which handles Msg service message.
|
||||
type MsgServiceHandler = func(ctx sdk.Context, req sdk.MsgRequest) (*sdk.Result, error)
|
||||
type MsgServiceHandler = func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error)
|
||||
|
||||
// Handler returns the MsgServiceHandler for a given query route path or nil
|
||||
// Handler returns the MsgServiceHandler for a given msg or nil if not found.
|
||||
func (msr *MsgServiceRouter) Handler(msg sdk.Msg) MsgServiceHandler {
|
||||
return msr.routes[sdk.MsgTypeURL(msg)]
|
||||
}
|
||||
|
||||
// HandlerbyTypeURL returns the MsgServiceHandler for a given query route path or nil
|
||||
// if not found.
|
||||
func (msr *MsgServiceRouter) Handler(methodName string) MsgServiceHandler {
|
||||
return msr.routes[methodName]
|
||||
func (msr *MsgServiceRouter) HandlerbyTypeURL(typeURL string) MsgServiceHandler {
|
||||
return msr.routes[typeURL]
|
||||
}
|
||||
|
||||
// RegisterService implements the gRPC Server.RegisterService method. sd is a gRPC
|
||||
|
@ -50,20 +55,38 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter
|
|||
fqMethod := fmt.Sprintf("/%s/%s", sd.ServiceName, method.MethodName)
|
||||
methodHandler := method.Handler
|
||||
|
||||
var requestTypeName string
|
||||
|
||||
// NOTE: This is how we pull the concrete request type for each handler for registering in the InterfaceRegistry.
|
||||
// This approach is maybe a bit hacky, but less hacky than reflecting on the handler object itself.
|
||||
// We use a no-op interceptor to avoid actually calling into the handler itself.
|
||||
_, _ = methodHandler(nil, context.Background(), func(i interface{}) error {
|
||||
msg, ok := i.(sdk.Msg)
|
||||
if !ok {
|
||||
// We panic here because there is no other alternative and the app cannot be initialized correctly
|
||||
// this should only happen if there is a problem with code generation in which case the app won't
|
||||
// work correctly anyway.
|
||||
panic(fmt.Errorf("can't register request type %T for service method %s", i, fqMethod))
|
||||
}
|
||||
|
||||
requestTypeName = sdk.MsgTypeURL(msg)
|
||||
return nil
|
||||
}, noopInterceptor)
|
||||
|
||||
// Check that the service Msg fully-qualified method name has already
|
||||
// been registered (via RegisterInterfaces). If the user registers a
|
||||
// service without registering according service Msg type, there might be
|
||||
// some unexpected behavior down the road. Since we can't return an error
|
||||
// (`Server.RegisterService` interface restriction) we panic (at startup).
|
||||
serviceMsg, err := msr.interfaceRegistry.Resolve(fqMethod)
|
||||
if err != nil || serviceMsg == nil {
|
||||
reqType, err := msr.interfaceRegistry.Resolve(requestTypeName)
|
||||
if err != nil || reqType == nil {
|
||||
panic(
|
||||
fmt.Errorf(
|
||||
"type_url %s has not been registered yet. "+
|
||||
"Before calling RegisterService, you must register all interfaces by calling the `RegisterInterfaces` "+
|
||||
"method on module.BasicManager. Each module should call `msgservice.RegisterMsgServiceDesc` inside its "+
|
||||
"`RegisterInterfaces` method with the `_Msg_serviceDesc` generated by proto-gen",
|
||||
fqMethod,
|
||||
requestTypeName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -72,7 +95,7 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter
|
|||
// registered more than once, then we should error. Since we can't
|
||||
// return an error (`Server.RegisterService` interface restriction) we
|
||||
// panic (at startup).
|
||||
_, found := msr.routes[fqMethod]
|
||||
_, found := msr.routes[requestTypeName]
|
||||
if found {
|
||||
panic(
|
||||
fmt.Errorf(
|
||||
|
@ -83,7 +106,7 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter
|
|||
)
|
||||
}
|
||||
|
||||
msr.routes[fqMethod] = func(ctx sdk.Context, req sdk.MsgRequest) (*sdk.Result, error) {
|
||||
msr.routes[requestTypeName] = func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error) {
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
interceptor := func(goCtx context.Context, _ interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
goCtx = context.WithValue(goCtx, sdk.SdkContextKey, ctx)
|
||||
|
@ -112,3 +135,6 @@ func (msr *MsgServiceRouter) SetInterfaceRegistry(interfaceRegistry codectypes.I
|
|||
}
|
||||
|
||||
func noopDecoder(_ interface{}) error { return nil }
|
||||
func noopInterceptor(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -80,11 +80,11 @@ func TestMsgService(t *testing.T) {
|
|||
)
|
||||
_ = app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: 1}})
|
||||
|
||||
msg := testdata.NewServiceMsgCreateDog(&testdata.MsgCreateDog{Dog: &testdata.Dog{Name: "Spot"}})
|
||||
msg := testdata.MsgCreateDog{Dog: &testdata.Dog{Name: "Spot"}}
|
||||
txBuilder := encCfg.TxConfig.NewTxBuilder()
|
||||
txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())
|
||||
txBuilder.SetGasLimit(testdata.NewTestGasLimit())
|
||||
err := txBuilder.SetMsgs(msg)
|
||||
err := txBuilder.SetMsgs(&msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
// First round: we gather all the signer infos. We use the "set empty
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
signing2 "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
|
@ -39,10 +38,7 @@ var (
|
|||
},
|
||||
}
|
||||
msg0 = banktypes.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 1)))
|
||||
msg1 = sdk.ServiceMsg{
|
||||
MethodName: "/cosmos.bank.v1beta1.Msg/Send",
|
||||
Request: banktypes.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 2))),
|
||||
}
|
||||
msg1 = banktypes.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 2)))
|
||||
)
|
||||
|
||||
func buildTestTx(t *testing.T, builder client.TxBuilder) {
|
||||
|
@ -88,7 +84,7 @@ func (s *TestSuite) TestCopyTx() {
|
|||
s.Require().Equal(sigsV2_1, sigsV2_2)
|
||||
s.Require().Equal(protoBuilder.GetTx().GetSigners(), protoBuilder2.GetTx().GetSigners())
|
||||
s.Require().Equal(protoBuilder.GetTx().GetMsgs()[0], protoBuilder2.GetTx().GetMsgs()[0])
|
||||
s.Require().Equal(protoBuilder.GetTx().GetMsgs()[1].(sdk.ServiceMsg).Request, protoBuilder2.GetTx().GetMsgs()[1]) // We lose the "ServiceMsg" information
|
||||
s.Require().Equal(protoBuilder.GetTx().GetMsgs()[1], protoBuilder2.GetTx().GetMsgs()[1])
|
||||
|
||||
// amino -> proto -> amino
|
||||
aminoBuilder = s.aminoCfg.NewTxBuilder()
|
||||
|
@ -120,7 +116,7 @@ func (s *TestSuite) TestConvertTxToStdTx() {
|
|||
s.Require().Equal(gas, stdTx.Fee.Gas)
|
||||
s.Require().Equal(fee, stdTx.Fee.Amount)
|
||||
s.Require().Equal(msg0, stdTx.Msgs[0])
|
||||
s.Require().Equal(msg1.Request, stdTx.Msgs[1])
|
||||
s.Require().Equal(msg1, stdTx.Msgs[1])
|
||||
s.Require().Equal(timeoutHeight, stdTx.TimeoutHeight)
|
||||
s.Require().Equal(sig.PubKey, stdTx.Signatures[0].PubKey)
|
||||
s.Require().Equal(sig.Data.(*signing2.SingleSignatureData).Signature, stdTx.Signatures[0].Signature)
|
||||
|
@ -140,7 +136,7 @@ func (s *TestSuite) TestConvertTxToStdTx() {
|
|||
s.Require().Equal(gas, stdTx.Fee.Gas)
|
||||
s.Require().Equal(fee, stdTx.Fee.Amount)
|
||||
s.Require().Equal(msg0, stdTx.Msgs[0])
|
||||
s.Require().Equal(msg1.Request, stdTx.Msgs[1])
|
||||
s.Require().Equal(msg1, stdTx.Msgs[1])
|
||||
s.Require().Equal(timeoutHeight, stdTx.TimeoutHeight)
|
||||
s.Require().Empty(stdTx.Signatures)
|
||||
|
||||
|
|
|
@ -64,20 +64,14 @@ func NewAnyWithValue(v proto.Message) (*Any, error) {
|
|||
if v == nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, "Expecting non nil value to create a new Any")
|
||||
}
|
||||
return NewAnyWithCustomTypeURL(v, "/"+proto.MessageName(v))
|
||||
}
|
||||
|
||||
// NewAnyWithCustomTypeURL same as NewAnyWithValue, but sets a custom type url, instead
|
||||
// using the one from proto.Message.
|
||||
// NOTE: This functions should be only used for types with additional logic bundled
|
||||
// into the protobuf Any serialization. For simple marshaling you should use NewAnyWithValue.
|
||||
func NewAnyWithCustomTypeURL(v proto.Message, typeURL string) (*Any, error) {
|
||||
bz, err := proto.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Any{
|
||||
TypeUrl: typeURL,
|
||||
TypeUrl: "/" + proto.MessageName(v),
|
||||
Value: bz,
|
||||
cachedValue: v,
|
||||
}, nil
|
||||
|
|
|
@ -23,8 +23,6 @@ func (eom *errOnMarshal) XXX_Marshal(b []byte, deterministic bool) ([]byte, erro
|
|||
return nil, errAlways
|
||||
}
|
||||
|
||||
const fauxURL = "/anyhere"
|
||||
|
||||
var eom = &errOnMarshal{}
|
||||
|
||||
// Ensure that returning an error doesn't suddenly allocate and waste bytes.
|
||||
|
@ -32,7 +30,7 @@ var eom = &errOnMarshal{}
|
|||
func TestNewAnyWithCustomTypeURLWithErrorNoAllocation(t *testing.T) {
|
||||
var ms1, ms2 runtime.MemStats
|
||||
runtime.ReadMemStats(&ms1)
|
||||
any, err := types.NewAnyWithCustomTypeURL(eom, fauxURL)
|
||||
any, err := types.NewAnyWithValue(eom)
|
||||
runtime.ReadMemStats(&ms2)
|
||||
// Ensure that no fresh allocation was made.
|
||||
if diff := ms2.HeapAlloc - ms1.HeapAlloc; diff > 0 {
|
||||
|
@ -52,7 +50,7 @@ func BenchmarkNewAnyWithCustomTypeURLWithErrorReturned(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
any, err := types.NewAnyWithCustomTypeURL(eom, fauxURL)
|
||||
any, err := types.NewAnyWithValue(eom)
|
||||
if err == nil {
|
||||
b.Fatal("err wasn't returned")
|
||||
}
|
||||
|
|
|
@ -46,17 +46,6 @@ type InterfaceRegistry interface {
|
|||
// registry.RegisterImplementations((*sdk.Msg)(nil), &MsgSend{}, &MsgMultiSend{})
|
||||
RegisterImplementations(iface interface{}, impls ...proto.Message)
|
||||
|
||||
// RegisterCustomTypeURL allows a protobuf message to be registered as a
|
||||
// google.protobuf.Any with a custom typeURL (besides its own canonical
|
||||
// typeURL). iface should be an interface as type, as in RegisterInterface
|
||||
// and RegisterImplementations.
|
||||
//
|
||||
// Ex:
|
||||
// This will allow us to pack service methods in Any's using the full method name
|
||||
// as the type URL and the request body as the value, and allow us to unpack
|
||||
// such packed methods using the normal UnpackAny method for the interface iface.
|
||||
RegisterCustomTypeURL(iface interface{}, typeURL string, impl proto.Message)
|
||||
|
||||
// ListAllInterfaces list the type URLs of all registered interfaces.
|
||||
ListAllInterfaces() []string
|
||||
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
package types_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/grpc"
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
grpc2 "google.golang.org/grpc"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
)
|
||||
|
@ -185,60 +180,3 @@ func TestAny_ProtoJSON(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, spot, ha2.Animal.GetCachedValue())
|
||||
}
|
||||
|
||||
// this instance of grpc.ClientConn is used to test packing service method
|
||||
// requests into Any's
|
||||
type testAnyPackClient struct {
|
||||
any types.Any
|
||||
interfaceRegistry types.InterfaceRegistry
|
||||
}
|
||||
|
||||
var _ grpc.ClientConn = &testAnyPackClient{}
|
||||
|
||||
func (t *testAnyPackClient) Invoke(_ context.Context, method string, args, _ interface{}, _ ...grpc2.CallOption) error {
|
||||
reqMsg, ok := args.(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf("can't proto marshal %T", args)
|
||||
}
|
||||
|
||||
// registry the method request type with the interface registry
|
||||
t.interfaceRegistry.RegisterCustomTypeURL((*interface{})(nil), method, reqMsg)
|
||||
|
||||
bz, err := proto.Marshal(reqMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.any.TypeUrl = method
|
||||
t.any.Value = bz
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *testAnyPackClient) NewStream(context.Context, *grpc2.StreamDesc, string, ...grpc2.CallOption) (grpc2.ClientStream, error) {
|
||||
return nil, fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
func TestAny_ServiceRequestProtoJSON(t *testing.T) {
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
anyPacker := &testAnyPackClient{interfaceRegistry: interfaceRegistry}
|
||||
dogMsgClient := testdata.NewMsgClient(anyPacker)
|
||||
_, err := dogMsgClient.CreateDog(context.Background(), &testdata.MsgCreateDog{Dog: &testdata.Dog{
|
||||
Name: "spot",
|
||||
}})
|
||||
require.NoError(t, err)
|
||||
|
||||
// marshal JSON
|
||||
cdc := codec.NewProtoCodec(interfaceRegistry)
|
||||
bz, err := cdc.MarshalJSON(&anyPacker.any)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t,
|
||||
`{"@type":"/testdata.Msg/CreateDog","dog":{"size":"","name":"spot"}}`,
|
||||
string(bz))
|
||||
|
||||
// unmarshal JSON
|
||||
var any2 types.Any
|
||||
err = cdc.UnmarshalJSON(bz, &any2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, anyPacker.any, any2)
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ transfer(3){
|
|||
transfer.operations = [
|
||||
{
|
||||
"operation_identifier":{"index":0},
|
||||
"type":"cosmos.bank.v1beta1.MsgSend",
|
||||
"type":"/cosmos.bank.v1beta1.MsgSend",
|
||||
"account":{{sender.account_identifier}},
|
||||
"metadata": {
|
||||
"amount": [
|
||||
|
|
Binary file not shown.
|
@ -3,6 +3,7 @@
|
|||
## Changelog
|
||||
|
||||
- 2020-10-05: Initial Draft
|
||||
- 2021-04-21: Remove `ServiceMsg`s to follow Protobuf `Any`'s spec, see [#9063](https://github.com/cosmos/cosmos-sdk/issues/9063).
|
||||
|
||||
## Status
|
||||
|
||||
|
@ -96,71 +97,28 @@ On the client side, developers could take advantage of this by creating RPC impl
|
|||
logic. Protobuf libraries that use asynchronous callbacks, like [protobuf.js](https://github.com/protobufjs/protobuf.js#using-services)
|
||||
could use this to register callbacks for specific messages even for transactions that include multiple `Msg`s.
|
||||
|
||||
For backwards compatibility, existing `Msg` types should be used as the request parameter
|
||||
for `service` definitions. Newer `Msg` types which only support `service` definitions
|
||||
should use the more canonical `Msg...Request` names.
|
||||
Each `Msg` service method should have exactly one request parameter: its corresponding `Msg` type. For example, the `Msg` service method `/cosmos.gov.v1beta1.Msg/SubmitProposal` above has exactly one request parameter, namely the `Msg` type `/cosmos.gov.v1beta1.MsgSubmitProposal`. It is important the reader understands clearly the nomenclature difference between a `Msg` service (a Protobuf service) and a `Msg` type (a Protobuf message), and the differences in their fully-qualified name.
|
||||
|
||||
This convention has been decided over the more canonical `Msg...Request` names mainly for backwards compatibility, but also for better readability in `TxBody.messages` (see [Encoding section](#encoding) below): transactions containing `/cosmos.gov.MsgSubmitProposal` read better than those containing `/cosmos.gov.v1beta1.MsgSubmitProposalRequest`.
|
||||
|
||||
One consequence of this convention is that each `Msg` type can be the request parameter of only one `Msg` service method. However, we consider this limitation a good practice in explicitness.
|
||||
|
||||
### Encoding
|
||||
|
||||
Currently, we are encoding `Msg`s as `Any` in `Tx`s which involves packing the
|
||||
Encoding of transactions generated with `Msg` services do not differ from current Protobuf transaction encoding as defined in [ADR-020](./adr-020-protobuf-transaction-encoding.md). We are encoding `Msg` types (which are exactly `Msg` service methods' request parameters) as `Any` in `Tx`s which involves packing the
|
||||
binary-encoded `Msg` with its type URL.
|
||||
|
||||
The type URL for `MsgSubmitProposal` based on the proto3 spec is `/cosmos.gov.MsgSubmitProposal`.
|
||||
|
||||
The fully-qualified name for the `SubmitProposal` service method above (also
|
||||
based on the proto3 and gRPC specs) is `/cosmos.gov.Msg/SubmitProposal` which varies
|
||||
by a single `/` character. The generated `.pb.go` files for protobuf `service`s
|
||||
include names of this form and any compliant protobuf/gRPC code generator will
|
||||
generate the same name.
|
||||
|
||||
In order to encode service methods in transactions, we encode them as `Any`s in
|
||||
the same `TxBody.messages` field as other `Msg`s. We simply set `Any.type_url`
|
||||
to the full-qualified method name (ex. `/cosmos.gov.Msg/SubmitProposal`) and
|
||||
set `Any.value` to the protobuf encoding of the request message
|
||||
(`MsgSubmitProposal` in this case).
|
||||
|
||||
### Decoding
|
||||
|
||||
When decoding, `TxBody.UnpackInterfaces` will need a special case
|
||||
to detect if `Any` type URLs match the service method format (ex. `/cosmos.gov.Msg/SubmitProposal`)
|
||||
by checking for two `/` characters. Messages that are method names plus request parameters
|
||||
instead of a normal `Any` messages will get unpacked into the `ServiceMsg` struct:
|
||||
|
||||
```go
|
||||
type ServiceMsg struct {
|
||||
// MethodName is the fully-qualified service name
|
||||
MethodName string
|
||||
// Request is the request payload
|
||||
Request MsgRequest
|
||||
}
|
||||
```
|
||||
Since `Msg` types are packed into `Any`, decoding transactions messages are done by unpacking `Any`s into `Msg` types. For more information, please refer to [ADR-020](./adr-020-protobuf-transaction-encoding.md#transactions).
|
||||
|
||||
### Routing
|
||||
|
||||
In the future, `service` definitions may become the primary method for defining
|
||||
`Msg`s. As a starting point, we need to integrate with the SDK's existing routing
|
||||
and `Msg` interface.
|
||||
We propose to add a `msg_service_router` in BaseApp. This router is a key/value map which maps `Msg` types' `type_url`s to their corresponding `Msg` service method handler. Since there is a 1-to-1 mapping between `Msg` types and `Msg` service method, the `msg_service_router` has exactly one entry per `Msg` service method.
|
||||
|
||||
To do this, `ServiceMsg` implements the `sdk.Msg` interface and its handler does the
|
||||
actual method routing, allowing this feature to be added incrementally on top of
|
||||
existing functionality.
|
||||
When a transaction is processed by BaseApp (in CheckTx or in DeliverTx), its `TxBody.messages` are decoded as `Msg`s. Each `Msg`'s `type_url` is matched against an entry in the `msg_service_router`, and the respective `Msg` service method handler is called.
|
||||
|
||||
### `MsgRequest` interface
|
||||
|
||||
All request messages will need to implement the `MsgRequest` interface which is a
|
||||
simplified version of `Msg`, without `Route()`, `Type()` and `GetSignBytes()` which
|
||||
are no longer needed:
|
||||
|
||||
```go
|
||||
type MsgRequest interface {
|
||||
proto.Message
|
||||
ValidateBasic() error
|
||||
GetSigners() []AccAddress
|
||||
}
|
||||
```
|
||||
|
||||
`ServiceMsg` will forward its `ValidateBasic` and `GetSigners` methods to the `MsgRequest`
|
||||
methods.
|
||||
For backward compatability, the old handlers are not removed yet. If BaseApp receives a legacy `Msg` with no correspoding entry in the `msg_service_router`, it will be routed via its legacy `Route()` method into the legacy handler.
|
||||
|
||||
### Module Configuration
|
||||
|
||||
|
@ -192,8 +150,8 @@ The `RegisterServices` method and the `Configurator` interface are intended to
|
|||
evolve to satisfy the use cases discussed in [\#7093](https://github.com/cosmos/cosmos-sdk/issues/7093)
|
||||
and [\#7122](https://github.com/cosmos/cosmos-sdk/issues/7421).
|
||||
|
||||
When `Msg` services are registered, the framework _should_ verify that all `Msg...Request` types
|
||||
implement the `MsgRequest` interface described above and throw an error during initialization rather
|
||||
When `Msg` services are registered, the framework _should_ verify that all `Msg` types
|
||||
implement the `sdk.Msg` interface and throw an error during initialization rather
|
||||
than later when transactions are processed.
|
||||
|
||||
### `Msg` Service Implementation
|
||||
|
@ -211,8 +169,7 @@ func (k Keeper) SubmitProposal(goCtx context.Context, params *types.MsgSubmitPro
|
|||
}
|
||||
```
|
||||
|
||||
The `sdk.Context` should have an `EventManager` already attached by the `ServiceMsg`
|
||||
router.
|
||||
The `sdk.Context` should have an `EventManager` already attached by BaseApp's `msg_service_router`.
|
||||
|
||||
Separate handler definition is no longer needed with this approach.
|
||||
|
||||
|
@ -232,8 +189,6 @@ Finally, closing a module to client API opens desirable OCAP patterns discussed
|
|||
- dramatically reduces and simplifies the code
|
||||
|
||||
### Cons
|
||||
- supporting both this and the current concrete `Msg` type approach simultaneously could be confusing
|
||||
(we could choose to deprecate the current approach)
|
||||
- using `service` definitions outside the context of gRPC could be confusing (but doesn’t violate the proto3 spec)
|
||||
|
||||
|
||||
|
|
|
@ -169,12 +169,12 @@ func newTxDescriptor(ir codectypes.InterfaceRegistry) (*TxDescriptor, error) {
|
|||
return nil, fmt.Errorf("unable to get *tx.Tx protobuf name")
|
||||
}
|
||||
// get msgs
|
||||
svcMsgImplementers := ir.ListImplementations(sdk.ServiceMsgInterfaceProtoName)
|
||||
sdkMsgImplementers := ir.ListImplementations(sdk.MsgInterfaceProtoName)
|
||||
|
||||
msgsDesc := make([]*MsgDescriptor, 0, len(svcMsgImplementers))
|
||||
msgsDesc := make([]*MsgDescriptor, 0, len(sdkMsgImplementers))
|
||||
|
||||
// process sdk.ServiceMsg
|
||||
for _, svcMsg := range svcMsgImplementers {
|
||||
for _, svcMsg := range sdkMsgImplementers {
|
||||
resolved, err := ir.Resolve(svcMsg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to resolve sdk.ServiceMsg %s: %w", svcMsg, err)
|
||||
|
|
|
@ -16,7 +16,9 @@ import (
|
|||
"google.golang.org/grpc/metadata"
|
||||
rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
reflectionv1 "github.com/cosmos/cosmos-sdk/client/grpc/reflection"
|
||||
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
reflectionv2 "github.com/cosmos/cosmos-sdk/server/grpc/reflection/v2alpha1"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
@ -24,7 +26,8 @@ import (
|
|||
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
|
@ -95,6 +98,7 @@ func (s *IntegrationTestSuite) TestGRPCServer_BankBalance() {
|
|||
&banktypes.QueryBalanceRequest{Address: val0.Address.String(), Denom: denom},
|
||||
grpc.Header(&header),
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
blockHeight = header.Get(grpctypes.GRPCBlockHeightHeader)
|
||||
s.Require().NotEmpty(blockHeight[0]) // blockHeight is []string, first element is block height.
|
||||
}
|
||||
|
@ -161,9 +165,20 @@ func (s *IntegrationTestSuite) TestGRPCServer_GetTxsEvent() {
|
|||
func (s *IntegrationTestSuite) TestGRPCServer_BroadcastTx() {
|
||||
val0 := s.network.Validators[0]
|
||||
|
||||
grpcRes, err := banktestutil.LegacyGRPCProtoMsgSend(val0.ClientCtx,
|
||||
val0.Moniker, val0.Address, val0.Address,
|
||||
sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}, sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)},
|
||||
txBuilder := s.mkTxBuilder()
|
||||
|
||||
txBytes, err := val0.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Broadcast the tx via gRPC.
|
||||
queryClient := txtypes.NewServiceClient(s.conn)
|
||||
|
||||
grpcRes, err := queryClient.BroadcastTx(
|
||||
context.Background(),
|
||||
&txtypes.BroadcastTxRequest{
|
||||
Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC,
|
||||
TxBytes: txBytes,
|
||||
},
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint32(0), grpcRes.TxResponse.Code)
|
||||
|
@ -174,7 +189,6 @@ func (s *IntegrationTestSuite) TestGRPCServer_BroadcastTx() {
|
|||
// See issue https://github.com/cosmos/cosmos-sdk/issues/7662.
|
||||
func (s *IntegrationTestSuite) TestGRPCServerInvalidHeaderHeights() {
|
||||
t := s.T()
|
||||
val0 := s.network.Validators[0]
|
||||
|
||||
// We should reject connections with invalid block heights off the bat.
|
||||
invalidHeightStrs := []struct {
|
||||
|
@ -189,13 +203,7 @@ func (s *IntegrationTestSuite) TestGRPCServerInvalidHeaderHeights() {
|
|||
}
|
||||
for _, tt := range invalidHeightStrs {
|
||||
t.Run(tt.value, func(t *testing.T) {
|
||||
conn, err := grpc.Dial(
|
||||
val0.AppConfig.GRPC.Address,
|
||||
grpc.WithInsecure(), // Or else we get "no transport security set"
|
||||
)
|
||||
defer conn.Close()
|
||||
|
||||
testClient := testdata.NewQueryClient(conn)
|
||||
testClient := testdata.NewQueryClient(s.conn)
|
||||
ctx := metadata.AppendToOutgoingContext(context.Background(), grpctypes.GRPCBlockHeightHeader, tt.value)
|
||||
testRes, err := testClient.Echo(ctx, &testdata.EchoRequest{Message: "hello"})
|
||||
require.Error(t, err)
|
||||
|
@ -205,6 +213,40 @@ func (s *IntegrationTestSuite) TestGRPCServerInvalidHeaderHeights() {
|
|||
}
|
||||
}
|
||||
|
||||
// mkTxBuilder creates a TxBuilder containing a signed tx from validator 0.
|
||||
func (s IntegrationTestSuite) mkTxBuilder() client.TxBuilder {
|
||||
val := s.network.Validators[0]
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// prepare txBuilder with msg
|
||||
txBuilder := val.ClientCtx.TxConfig.NewTxBuilder()
|
||||
feeAmount := sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}
|
||||
gasLimit := testdata.NewTestGasLimit()
|
||||
s.Require().NoError(
|
||||
txBuilder.SetMsgs(&banktypes.MsgSend{
|
||||
FromAddress: val.Address.String(),
|
||||
ToAddress: val.Address.String(),
|
||||
Amount: sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)},
|
||||
}),
|
||||
)
|
||||
txBuilder.SetFeeAmount(feeAmount)
|
||||
txBuilder.SetGasLimit(gasLimit)
|
||||
txBuilder.SetMemo("foobar")
|
||||
|
||||
// setup txFactory
|
||||
txFactory := clienttx.Factory{}.
|
||||
WithChainID(val.ClientCtx.ChainID).
|
||||
WithKeybase(val.ClientCtx.Keyring).
|
||||
WithTxConfig(val.ClientCtx.TxConfig).
|
||||
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT)
|
||||
|
||||
// Sign Tx.
|
||||
err := authclient.SignTx(txFactory, val.ClientCtx, val.Moniker, txBuilder, false, true)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"encoding/hex"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
|
@ -71,7 +70,7 @@ func NewClient(cfg *Config) (*Client, error) {
|
|||
}
|
||||
|
||||
if _, ok := resolvedMsg.(sdk.Msg); ok {
|
||||
supportedOperations = append(supportedOperations, strings.TrimLeft(ii, "/"))
|
||||
supportedOperations = append(supportedOperations, ii)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
|
||||
rosettatypes "github.com/coinbase/rosetta-sdk-go/types"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
@ -147,7 +146,7 @@ func (c converter) UnsignedTx(ops []*rosettatypes.Operation) (tx authsigning.Tx,
|
|||
for i := 0; i < len(ops); i++ {
|
||||
op := ops[i]
|
||||
|
||||
protoMessage, err := c.ir.Resolve("/" + op.Type)
|
||||
protoMessage, err := c.ir.Resolve(op.Type)
|
||||
if err != nil {
|
||||
return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "operation not found: "+op.Type)
|
||||
}
|
||||
|
@ -241,31 +240,7 @@ func (c converter) Meta(msg sdk.Msg) (meta map[string]interface{}, err error) {
|
|||
// with the message proto name as type, and the raw fields
|
||||
// as metadata
|
||||
func (c converter) Ops(status string, msg sdk.Msg) ([]*rosettatypes.Operation, error) {
|
||||
opName := proto.MessageName(msg)
|
||||
// in case proto does not recognize the message name
|
||||
// then we should try to cast it to service msg, to
|
||||
// check if it was wrapped or not, in case the cast
|
||||
// from sdk.ServiceMsg to sdk.Msg fails, then a
|
||||
// codec error is returned
|
||||
if opName == "" {
|
||||
unwrappedMsg, ok := msg.(sdk.ServiceMsg)
|
||||
if !ok {
|
||||
return nil, crgerrs.WrapError(crgerrs.ErrCodec, fmt.Sprintf("unrecognized message type: %T", msg))
|
||||
}
|
||||
|
||||
msg, ok = unwrappedMsg.Request.(sdk.Msg)
|
||||
if !ok {
|
||||
return nil, crgerrs.WrapError(
|
||||
crgerrs.ErrCodec,
|
||||
fmt.Sprintf("unable to cast %T to sdk.Msg, method: %s", unwrappedMsg.Request, unwrappedMsg.MethodName),
|
||||
)
|
||||
}
|
||||
|
||||
opName = proto.MessageName(msg)
|
||||
if opName == "" {
|
||||
return nil, crgerrs.WrapError(crgerrs.ErrCodec, fmt.Sprintf("unrecognized message type: %T", msg))
|
||||
}
|
||||
}
|
||||
opName := sdk.MsgTypeURL(msg)
|
||||
|
||||
meta, err := c.Meta(msg)
|
||||
if err != nil {
|
||||
|
|
|
@ -77,14 +77,7 @@ func (msg *TestMsg) GetSigners() []sdk.AccAddress {
|
|||
}
|
||||
func (msg *TestMsg) ValidateBasic() error { return nil }
|
||||
|
||||
var _ sdk.MsgRequest = &MsgCreateDog{}
|
||||
var _ sdk.Msg = &MsgCreateDog{}
|
||||
|
||||
func (msg *MsgCreateDog) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{} }
|
||||
func (msg *MsgCreateDog) ValidateBasic() error { return nil }
|
||||
|
||||
func NewServiceMsgCreateDog(msg *MsgCreateDog) sdk.Msg {
|
||||
return sdk.ServiceMsg{
|
||||
MethodName: "/testdata.Msg/CreateDog",
|
||||
Request: msg,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import (
|
|||
const (
|
||||
// MsgInterfaceProtoName defines the protobuf name of the cosmos Msg interface
|
||||
MsgInterfaceProtoName = "cosmos.base.v1beta1.Msg"
|
||||
// ServiceMsgInterfaceProtoName defines the protobuf name of the cosmos MsgRequest interface
|
||||
ServiceMsgInterfaceProtoName = "cosmos.base.v1beta1.ServiceMsg"
|
||||
)
|
||||
|
||||
// RegisterLegacyAminoCodec registers the sdk message type.
|
||||
|
@ -21,7 +19,4 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
|||
// RegisterInterfaces registers the sdk message type.
|
||||
func RegisterInterfaces(registry types.InterfaceRegistry) {
|
||||
registry.RegisterInterface(MsgInterfaceProtoName, (*Msg)(nil))
|
||||
// the interface name for MsgRequest is ServiceMsg because this is most useful for clients
|
||||
// to understand - it will be the way for clients to introspect on available Msg service methods
|
||||
registry.RegisterInterface(ServiceMsgInterfaceProtoName, (*MsgRequest)(nil))
|
||||
}
|
||||
|
|
|
@ -3,9 +3,7 @@ package msgservice
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
|
@ -24,7 +22,7 @@ func RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.Serv
|
|||
// This approach is maybe a bit hacky, but less hacky than reflecting on the handler object itself.
|
||||
// We use a no-op interceptor to avoid actually calling into the handler itself.
|
||||
_, _ = methodHandler(nil, context.Background(), func(i interface{}) error {
|
||||
msg, ok := i.(proto.Message)
|
||||
msg, ok := i.(sdk.Msg)
|
||||
if !ok {
|
||||
// We panic here because there is no other alternative and the app cannot be initialized correctly
|
||||
// this should only happen if there is a problem with code generation in which case the app won't
|
||||
|
@ -32,7 +30,8 @@ func RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.Serv
|
|||
panic(fmt.Errorf("can't register request type %T for service method %s", i, fqMethod))
|
||||
}
|
||||
|
||||
registry.RegisterCustomTypeURL((*sdk.MsgRequest)(nil), fqMethod, msg)
|
||||
registry.RegisterImplementations((*sdk.Msg)(nil), msg)
|
||||
|
||||
return nil
|
||||
}, noopInterceptor)
|
||||
|
||||
|
@ -43,9 +42,3 @@ func RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.Serv
|
|||
func noopInterceptor(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// IsServiceMsg checks if a type URL corresponds to a service method name,
|
||||
// i.e. /cosmos.bank.Msg/Send vs /cosmos.bank.MsgSend
|
||||
func IsServiceMsg(typeURL string) bool {
|
||||
return strings.Count(typeURL, "/") >= 2
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ type ServiceMsgClientConn struct {
|
|||
}
|
||||
|
||||
// Invoke implements the grpc ClientConn.Invoke method
|
||||
func (t *ServiceMsgClientConn) Invoke(_ context.Context, method string, args, _ interface{}, _ ...grpc.CallOption) error {
|
||||
req, ok := args.(sdk.MsgRequest)
|
||||
func (t *ServiceMsgClientConn) Invoke(_ context.Context, _ string, args, _ interface{}, _ ...grpc.CallOption) error {
|
||||
req, ok := args.(sdk.Msg)
|
||||
if !ok {
|
||||
return fmt.Errorf("%T should implement %T", args, (*sdk.MsgRequest)(nil))
|
||||
return fmt.Errorf("%T should implement %T", args, (*sdk.Msg)(nil))
|
||||
}
|
||||
|
||||
err := req.ValidateBasic()
|
||||
|
@ -31,10 +31,7 @@ func (t *ServiceMsgClientConn) Invoke(_ context.Context, method string, args, _
|
|||
return err
|
||||
}
|
||||
|
||||
t.msgs = append(t.msgs, sdk.ServiceMsg{
|
||||
MethodName: method,
|
||||
Request: req,
|
||||
})
|
||||
t.msgs = append(t.msgs, req)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
// MsgRequest is the interface a transaction message, defined as a proto
|
||||
// service method, must fulfill.
|
||||
type MsgRequest interface {
|
||||
proto.Message
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
ValidateBasic() error
|
||||
// Signers returns the addrs of signers that must sign.
|
||||
// CONTRACT: All signatures must be present to be valid.
|
||||
// CONTRACT: Returns addrs in some deterministic order.
|
||||
GetSigners() []AccAddress
|
||||
}
|
||||
|
||||
// ServiceMsg is the struct into which an Any whose typeUrl matches a service
|
||||
// method format (ex. `/cosmos.gov.v1beta1.Msg/SubmitProposal`) unpacks.
|
||||
type ServiceMsg struct {
|
||||
// MethodName is the fully-qualified service method name.
|
||||
MethodName string
|
||||
// Request is the request payload.
|
||||
Request MsgRequest
|
||||
}
|
||||
|
||||
var _ Msg = ServiceMsg{}
|
||||
|
||||
func (msg ServiceMsg) ProtoMessage() {}
|
||||
func (msg ServiceMsg) Reset() {}
|
||||
func (msg ServiceMsg) String() string { return "ServiceMsg" }
|
||||
|
||||
// Route implements Msg.Route method.
|
||||
func (msg ServiceMsg) Route() string {
|
||||
return msg.MethodName
|
||||
}
|
||||
|
||||
// ValidateBasic implements Msg.ValidateBasic method.
|
||||
func (msg ServiceMsg) ValidateBasic() error {
|
||||
return msg.Request.ValidateBasic()
|
||||
}
|
||||
|
||||
// GetSignBytes implements Msg.GetSignBytes method.
|
||||
func (msg ServiceMsg) GetSignBytes() []byte {
|
||||
// Here, we're gracefully supporting Amino JSON for service
|
||||
// Msgs.
|
||||
// ref: https://github.com/cosmos/cosmos-sdk/issues/8346
|
||||
// If `msg` is a service Msg, then we cast its `Request` to a sdk.Msg
|
||||
// and call GetSignBytes on the `Request`.
|
||||
msgRequest, ok := msg.Request.(Msg)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("cannot convert ServiceMsg request to sdk.Msg, got %T", msgRequest))
|
||||
}
|
||||
|
||||
return msgRequest.GetSignBytes()
|
||||
}
|
||||
|
||||
// GetSigners implements Msg.GetSigners method.
|
||||
func (msg ServiceMsg) GetSigners() []AccAddress {
|
||||
return msg.Request.GetSigners()
|
||||
}
|
||||
|
||||
// Type implements Msg.Type method.
|
||||
func (msg ServiceMsg) Type() string {
|
||||
return msg.MethodName
|
||||
}
|
|
@ -2,14 +2,13 @@ package simulation
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||
)
|
||||
|
||||
type WeightedProposalContent interface {
|
||||
|
@ -78,16 +77,14 @@ func NewOperationMsgBasic(route, name, comment string, ok bool, msg []byte) Oper
|
|||
|
||||
// NewOperationMsg - create a new operation message from sdk.Msg
|
||||
func NewOperationMsg(msg sdk.Msg, ok bool, comment string, cdc *codec.ProtoCodec) OperationMsg {
|
||||
if reflect.TypeOf(msg) == reflect.TypeOf(sdk.ServiceMsg{}) {
|
||||
srvMsg, ok := msg.(sdk.ServiceMsg)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Expecting %T to implement sdk.ServiceMsg", msg))
|
||||
}
|
||||
bz := cdc.MustMarshalJSON(srvMsg.Request)
|
||||
|
||||
return NewOperationMsgBasic(srvMsg.MethodName, srvMsg.MethodName, comment, ok, bz)
|
||||
if legacyMsg, okType := msg.(legacytx.LegacyMsg); okType {
|
||||
return NewOperationMsgBasic(legacyMsg.Route(), legacyMsg.Type(), comment, ok, legacyMsg.GetSignBytes())
|
||||
}
|
||||
return NewOperationMsgBasic(msg.Route(), msg.Type(), comment, ok, msg.GetSignBytes())
|
||||
|
||||
bz := cdc.MustMarshalJSON(msg)
|
||||
|
||||
return NewOperationMsgBasic(sdk.MsgTypeURL(msg), sdk.MsgTypeURL(msg), comment, ok, bz)
|
||||
|
||||
}
|
||||
|
||||
// NoOpMsg - create a no-operation message
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
)
|
||||
|
||||
// MaxGasWanted defines the max gas allowed.
|
||||
|
@ -26,20 +25,11 @@ func (t *Tx) GetMsgs() []sdk.Msg {
|
|||
anys := t.Body.Messages
|
||||
res := make([]sdk.Msg, len(anys))
|
||||
for i, any := range anys {
|
||||
var msg sdk.Msg
|
||||
if msgservice.IsServiceMsg(any.TypeUrl) {
|
||||
req := any.GetCachedValue()
|
||||
if req == nil {
|
||||
panic("Any cached value is nil. Transaction messages must be correctly packed Any values.")
|
||||
}
|
||||
msg = sdk.ServiceMsg{
|
||||
MethodName: any.TypeUrl,
|
||||
Request: any.GetCachedValue().(sdk.MsgRequest),
|
||||
}
|
||||
} else {
|
||||
msg = any.GetCachedValue().(sdk.Msg)
|
||||
cached := any.GetCachedValue()
|
||||
if cached == nil {
|
||||
panic("Any cached value is nil. Transaction messages must be correctly packed Any values.")
|
||||
}
|
||||
res[i] = msg
|
||||
res[i] = cached.(sdk.Msg)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@ -181,20 +171,10 @@ func (t *Tx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
|||
// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
|
||||
func (m *TxBody) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
||||
for _, any := range m.Messages {
|
||||
// If the any's typeUrl contains 2 slashes, then we unpack the any into
|
||||
// a ServiceMsg struct as per ADR-031.
|
||||
if msgservice.IsServiceMsg(any.TypeUrl) {
|
||||
var req sdk.MsgRequest
|
||||
err := unpacker.UnpackAny(any, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
var msg sdk.Msg
|
||||
err := unpacker.UnpackAny(any, &msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var msg sdk.Msg
|
||||
err := unpacker.UnpackAny(any, &msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
|
@ -11,21 +13,10 @@ type (
|
|||
Msg interface {
|
||||
proto.Message
|
||||
|
||||
// Return the message type.
|
||||
// Must be alphanumeric or empty.
|
||||
Route() string
|
||||
|
||||
// Returns a human-readable string for the message, intended for utilization
|
||||
// within tags
|
||||
Type() string
|
||||
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
ValidateBasic() error
|
||||
|
||||
// Get the canonical byte representation of the Msg.
|
||||
GetSignBytes() []byte
|
||||
|
||||
// Signers returns the addrs of signers that must sign.
|
||||
// CONTRACT: All signatures must be present to be valid.
|
||||
// CONTRACT: Returns addrs in some deterministic order.
|
||||
|
@ -85,3 +76,8 @@ type TxDecoder func(txBytes []byte) (Tx, error)
|
|||
|
||||
// TxEncoder marshals transaction to bytes
|
||||
type TxEncoder func(tx Tx) ([]byte, error)
|
||||
|
||||
// MsgTypeURL returns the TypeURL of a `sdk.Msg`.
|
||||
func MsgTypeURL(msg Msg) string {
|
||||
return fmt.Sprintf("/%s", proto.MessageName(msg))
|
||||
}
|
||||
|
|
|
@ -251,19 +251,7 @@ func (s *IntegrationTestSuite) TestCLIQueryTxCmd() {
|
|||
|
||||
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
|
||||
|
||||
// Send coins, try both with legacy Msg and with Msg service.
|
||||
// Legacy proto Msg.
|
||||
legacyTxRes, err := bankcli.LegacyGRPCProtoMsgSend(
|
||||
val.ClientCtx, val.Moniker,
|
||||
val.Address,
|
||||
account2.GetAddress(),
|
||||
sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))),
|
||||
sdk.NewCoins(sendTokens),
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// Service Msg.
|
||||
// Send coins.
|
||||
out, err := s.createBankMsg(
|
||||
val, account2.GetAddress(),
|
||||
sdk.NewCoins(sendTokens),
|
||||
|
@ -292,16 +280,10 @@ func (s *IntegrationTestSuite) TestCLIQueryTxCmd() {
|
|||
"",
|
||||
},
|
||||
{
|
||||
"happy case (legacy Msg)",
|
||||
[]string{legacyTxRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"happy case (service Msg)",
|
||||
"happy case",
|
||||
[]string{txRes.TxHash, fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
|
||||
false,
|
||||
"/cosmos.bank.v1beta1.Msg/Send",
|
||||
"/cosmos.bank.v1beta1.MsgSend",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,24 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
)
|
||||
|
||||
// LegacyMsg defines the old interface a message must fulfill, containing
|
||||
// Amino signing method and legacy router info.
|
||||
// Deprecated: Please use `Msg` instead.
|
||||
type LegacyMsg interface {
|
||||
sdk.Msg
|
||||
|
||||
// Get the canonical byte representation of the Msg.
|
||||
GetSignBytes() []byte
|
||||
|
||||
// Return the message type.
|
||||
// Must be alphanumeric or empty.
|
||||
Route() string
|
||||
|
||||
// Returns a human-readable string for the message, intended for utilization
|
||||
// within tags
|
||||
Type() string
|
||||
}
|
||||
|
||||
// StdSignDoc is replay-prevention structure.
|
||||
// It includes the result of msg.GetSignBytes(),
|
||||
// as well as the ChainID (prevent cross chain replay)
|
||||
|
@ -38,7 +56,7 @@ func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee,
|
|||
// If msg is a legacy Msg, then GetSignBytes is implemented.
|
||||
// If msg is a ServiceMsg, then GetSignBytes has graceful support of
|
||||
// calling GetSignBytes from its underlying Msg.
|
||||
msgsBytes = append(msgsBytes, json.RawMessage(msg.GetSignBytes()))
|
||||
msgsBytes = append(msgsBytes, json.RawMessage(msg.(LegacyMsg).GetSignBytes()))
|
||||
}
|
||||
|
||||
bz, err := legacy.Cdc.MarshalJSON(StdSignDoc{
|
||||
|
|
|
@ -29,25 +29,7 @@ func (s *StdTxBuilder) GetTx() authsigning.Tx {
|
|||
|
||||
// SetMsgs implements TxBuilder.SetMsgs
|
||||
func (s *StdTxBuilder) SetMsgs(msgs ...sdk.Msg) error {
|
||||
stdTxMsgs := make([]sdk.Msg, len(msgs))
|
||||
|
||||
for i, msg := range msgs {
|
||||
switch msg := msg.(type) {
|
||||
case sdk.ServiceMsg:
|
||||
// Since ServiceMsg isn't registered with amino, we unpack msg.Request
|
||||
// into a Msg so that it's handled gracefully for the legacy
|
||||
// GET /txs/{hash} and /txs endpoints.
|
||||
sdkMsg, ok := msg.Request.(sdk.Msg)
|
||||
if !ok {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "Expecting %T at %d to implement sdk.Msg", msg.Request, i)
|
||||
}
|
||||
stdTxMsgs[i] = sdkMsg
|
||||
default:
|
||||
// legacy sdk.Msg
|
||||
stdTxMsgs[i] = msg
|
||||
}
|
||||
}
|
||||
s.Msgs = stdTxMsgs
|
||||
s.Msgs = msgs
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -204,12 +204,7 @@ func (w *wrapper) SetMsgs(msgs ...sdk.Msg) error {
|
|||
|
||||
for i, msg := range msgs {
|
||||
var err error
|
||||
switch msg := msg.(type) {
|
||||
case sdk.ServiceMsg:
|
||||
anys[i], err = codectypes.NewAnyWithCustomTypeURL(msg.Request, msg.MethodName)
|
||||
default:
|
||||
anys[i], err = codectypes.NewAnyWithValue(msg)
|
||||
}
|
||||
anys[i], err = codectypes.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ import (
|
|||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
var bankMsgSendEventAction = fmt.Sprintf("message.action='%s'", sdk.MsgTypeURL(&banktypes.MsgSend{}))
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
|
@ -192,7 +194,7 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() {
|
|||
{
|
||||
"request with order-by",
|
||||
&tx.GetTxsEventRequest{
|
||||
Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'"},
|
||||
Events: []string{bankMsgSendEventAction},
|
||||
OrderBy: tx.OrderBy_ORDER_BY_ASC,
|
||||
},
|
||||
false, "",
|
||||
|
@ -200,14 +202,14 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() {
|
|||
{
|
||||
"without pagination",
|
||||
&tx.GetTxsEventRequest{
|
||||
Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'"},
|
||||
Events: []string{bankMsgSendEventAction},
|
||||
},
|
||||
false, "",
|
||||
},
|
||||
{
|
||||
"with pagination",
|
||||
&tx.GetTxsEventRequest{
|
||||
Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'"},
|
||||
Events: []string{bankMsgSendEventAction},
|
||||
Pagination: &query.PageRequest{
|
||||
CountTotal: false,
|
||||
Offset: 0,
|
||||
|
@ -219,7 +221,7 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() {
|
|||
{
|
||||
"with multi events",
|
||||
&tx.GetTxsEventRequest{
|
||||
Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"},
|
||||
Events: []string{bankMsgSendEventAction, "message.module='bank'"},
|
||||
},
|
||||
false, "",
|
||||
},
|
||||
|
@ -262,43 +264,43 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPCGateway() {
|
|||
},
|
||||
{
|
||||
"without pagination",
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'"),
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, bankMsgSendEventAction),
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"with pagination",
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&pagination.offset=%d&pagination.limit=%d", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", 0, 10),
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&pagination.offset=%d&pagination.limit=%d", val.APIAddress, bankMsgSendEventAction, 0, 10),
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid request: order by asc",
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=ORDER_BY_ASC", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"),
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=ORDER_BY_ASC", val.APIAddress, bankMsgSendEventAction, "message.module='bank'"),
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid request: order by desc",
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=ORDER_BY_DESC", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"),
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=ORDER_BY_DESC", val.APIAddress, bankMsgSendEventAction, "message.module='bank'"),
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"invalid request: invalid order by",
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=invalid_order", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"),
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=invalid_order", val.APIAddress, bankMsgSendEventAction, "message.module='bank'"),
|
||||
true,
|
||||
"is not a valid tx.OrderBy",
|
||||
},
|
||||
{
|
||||
"expect pass with multiple-events",
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"),
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s", val.APIAddress, bankMsgSendEventAction, "message.module='bank'"),
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"expect pass with escape event",
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action%3D'%2Fcosmos.bank.v1beta1.Msg%2FSend'"),
|
||||
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action%3D'/cosmos.bank.v1beta1.MsgSend'"),
|
||||
false,
|
||||
"",
|
||||
},
|
||||
|
@ -584,6 +586,7 @@ func (s IntegrationTestSuite) mkTxBuilder() client.TxBuilder {
|
|||
)
|
||||
txBuilder.SetFeeAmount(feeAmount)
|
||||
txBuilder.SetGasLimit(gasLimit)
|
||||
txBuilder.SetMemo("foobar")
|
||||
|
||||
// setup txFactory
|
||||
txFactory := clienttx.Factory{}.
|
||||
|
|
|
@ -60,7 +60,7 @@ func NewCmdGrantAuthorization() *cobra.Command {
|
|||
|
||||
Examples:
|
||||
$ %s tx %s grant cosmos1skjw.. send %s --spend-limit=1000stake --from=cosmos1skl..
|
||||
$ %s tx %s grant cosmos1skjw.. generic --msg-type=/cosmos.gov.v1beta1.Msg/Vote --from=cosmos1sk..
|
||||
$ %s tx %s grant cosmos1skjw.. generic --msg-type=/cosmos.gov.v1beta1.MsgVote --from=cosmos1sk..
|
||||
`, version.AppName, types.ModuleName, bank.SendAuthorization{}.MethodName(), version.AppName, types.ModuleName),
|
||||
),
|
||||
Args: cobra.ExactArgs(2),
|
||||
|
@ -254,17 +254,7 @@ Example:
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgs := theTx.GetMsgs()
|
||||
serviceMsgs := make([]sdk.ServiceMsg, len(msgs))
|
||||
for i, msg := range msgs {
|
||||
srvMsg, ok := msg.(sdk.ServiceMsg)
|
||||
if !ok {
|
||||
return fmt.Errorf("tx contains %T which is not a sdk.ServiceMsg", msg)
|
||||
}
|
||||
serviceMsgs[i] = srvMsg
|
||||
}
|
||||
|
||||
msg := types.NewMsgExecAuthorized(grantee, serviceMsgs)
|
||||
msg := types.NewMsgExecAuthorized(grantee, theTx.GetMsgs())
|
||||
svcMsgClientConn := &msgservice.ServiceMsgClientConn{}
|
||||
msgClient := types.NewMsgClient(svcMsgClientConn)
|
||||
_, err = msgClient.ExecAuthorized(context.Background(), &msg)
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
types "github.com/cosmos/cosmos-sdk/x/authz/types"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
)
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
|
@ -30,7 +31,7 @@ type IntegrationTestSuite struct {
|
|||
}
|
||||
|
||||
var typeMsgSend = banktypes.SendAuthorization{}.MethodName()
|
||||
var typeMsgVote = "/cosmos.gov.v1beta1.Msg/Vote"
|
||||
var typeMsgVote = sdk.MsgTypeURL(&govtypes.MsgVote{})
|
||||
|
||||
func (s *IntegrationTestSuite) SetupSuite() {
|
||||
s.T().Log("setting up integration test suite")
|
||||
|
@ -48,7 +49,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
|||
newAddr := sdk.AccAddress(info.GetPubKey().Address())
|
||||
|
||||
// Send some funds to the new account.
|
||||
_, err = banktestutil.MsgSendExec(
|
||||
out, err := banktestutil.MsgSendExec(
|
||||
val.ClientCtx,
|
||||
val.Address,
|
||||
newAddr,
|
||||
|
@ -57,9 +58,10 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
|||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Contains(out.String(), `"code":0`)
|
||||
|
||||
// grant authorization
|
||||
_, err = authztestutil.ExecGrantAuthorization(val, []string{
|
||||
out, err = authztestutil.ExecGrantAuthorization(val, []string{
|
||||
newAddr.String(),
|
||||
"send",
|
||||
fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit),
|
||||
|
@ -70,6 +72,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
|||
fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Contains(out.String(), `"code":0`)
|
||||
|
||||
s.grantee = newAddr
|
||||
_, err = s.network.WaitForHeight(1)
|
||||
|
@ -185,10 +188,9 @@ func (s *IntegrationTestSuite) TestQueryAuthorizationsGRPC() {
|
|||
fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, val.Address.String(), s.grantee.String()),
|
||||
false,
|
||||
"",
|
||||
func() {
|
||||
},
|
||||
func() {},
|
||||
func(authorizations *types.QueryAuthorizationsResponse) {
|
||||
s.Require().Equal(len(authorizations.Authorizations), 1)
|
||||
s.Require().Len(authorizations.Authorizations), 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -5,25 +5,22 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/authz/client/cli"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
|
||||
govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
stakingcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli"
|
||||
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
|
@ -81,7 +78,7 @@ func (s *IntegrationTestSuite) TearDownSuite() {
|
|||
}
|
||||
|
||||
var typeMsgSend = bank.SendAuthorization{}.MethodName()
|
||||
var typeMsgVote = "/cosmos.gov.v1beta1.Msg/Vote"
|
||||
var typeMsgVote = sdk.MsgTypeURL(&govtypes.MsgVote{})
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
||||
val := s.network.Validators[0]
|
||||
|
@ -93,7 +90,6 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
respType proto.Message
|
||||
expectedCode uint32
|
||||
expectErr bool
|
||||
}{
|
||||
|
@ -107,7 +103,6 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
|
||||
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
|
||||
},
|
||||
nil,
|
||||
0,
|
||||
true,
|
||||
},
|
||||
|
@ -121,7 +116,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
|
||||
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
|
||||
},
|
||||
nil, 0,
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
|
@ -134,7 +129,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
|
||||
fmt.Sprintf("--%s=%d", cli.FlagExpiration, pastHour),
|
||||
},
|
||||
nil, 0,
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
|
@ -149,8 +144,8 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
|
||||
},
|
||||
nil, 0,
|
||||
true,
|
||||
0x1d,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"failed with error both validators not allowed",
|
||||
|
@ -166,7 +161,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, val.ValAddress.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
nil, 0,
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
|
@ -182,7 +177,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
&sdk.TxResponse{}, 0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
|
@ -198,7 +193,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, val.ValAddress.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
&sdk.TxResponse{}, 0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
|
@ -214,7 +209,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
&sdk.TxResponse{}, 0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
|
@ -230,7 +225,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
&sdk.TxResponse{}, 0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
|
@ -245,7 +240,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
&sdk.TxResponse{}, 0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
|
@ -260,7 +255,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
&sdk.TxResponse{}, 0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
@ -276,9 +271,9 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
var txResp sdk.TxResponse
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
|
||||
txResp := tc.respType.(*sdk.TxResponse)
|
||||
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &txResp), out.String())
|
||||
s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
|
||||
}
|
||||
})
|
||||
|
@ -427,7 +422,7 @@ func (s *IntegrationTestSuite) TestExecAuthorizationWithExpiration() {
|
|||
)
|
||||
s.Require().NoError(err)
|
||||
// msg vote
|
||||
voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.Msg/Vote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String())
|
||||
voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.MsgVote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String())
|
||||
execMsg := testutil.WriteToNewTempFile(s.T(), voteTx)
|
||||
|
||||
// waiting for authorization to expires
|
||||
|
@ -468,7 +463,7 @@ func (s *IntegrationTestSuite) TestNewExecGenericAuthorized() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// msg vote
|
||||
voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.Msg/Vote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String())
|
||||
voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.MsgVote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String())
|
||||
execMsg := testutil.WriteToNewTempFile(s.T(), voteTx)
|
||||
|
||||
testCases := []struct {
|
||||
|
@ -646,7 +641,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() {
|
|||
sdk.NewCoin("stake", sdk.NewInt(50)),
|
||||
)
|
||||
|
||||
delegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Delegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
delegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgDelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
tokens.GetDenomByIndex(0), tokens[0].Amount)
|
||||
execMsg := testutil.WriteToNewTempFile(s.T(), delegateTx)
|
||||
|
||||
|
@ -736,7 +731,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() {
|
|||
sdk.NewCoin("stake", sdk.NewInt(50)),
|
||||
)
|
||||
|
||||
delegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Delegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
delegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgDelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
tokens.GetDenomByIndex(0), tokens[0].Amount)
|
||||
execMsg = testutil.WriteToNewTempFile(s.T(), delegateTx)
|
||||
|
||||
|
@ -822,7 +817,6 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() {
|
|||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
|
||||
s.Require().NoError(err)
|
||||
s.Contains(out.String(), fmt.Sprintf("cannot delegate/undelegate to %s validator", val.ValAddress.String()))
|
||||
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() {
|
||||
|
@ -865,7 +859,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() {
|
|||
sdk.NewCoin("stake", sdk.NewInt(50)),
|
||||
)
|
||||
|
||||
undelegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Undelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
undelegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgUndelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
tokens.GetDenomByIndex(0), tokens[0].Amount)
|
||||
execMsg := testutil.WriteToNewTempFile(s.T(), undelegateTx)
|
||||
|
||||
|
@ -955,7 +949,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() {
|
|||
sdk.NewCoin("stake", sdk.NewInt(50)),
|
||||
)
|
||||
|
||||
undelegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Undelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
undelegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgUndelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String(), val.ValAddress.String(),
|
||||
tokens.GetDenomByIndex(0), tokens[0].Amount)
|
||||
execMsg = testutil.WriteToNewTempFile(s.T(), undelegateTx)
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ type Authorization interface {
|
|||
|
||||
// Accept determines whether this grant permits the provided sdk.ServiceMsg to be performed, and if
|
||||
// so provides an upgraded authorization instance.
|
||||
Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated Authorization, delete bool, err error)
|
||||
Accept(ctx sdk.Context, msg sdk.Msg) (updated Authorization, delete bool, err error)
|
||||
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
|
|
|
@ -73,26 +73,29 @@ func (k Keeper) update(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccA
|
|||
|
||||
// DispatchActions attempts to execute the provided messages via authorization
|
||||
// grants from the message signer to the grantee.
|
||||
func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, serviceMsgs []sdk.ServiceMsg) (*sdk.Result, error) {
|
||||
func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, msgs []sdk.Msg) (*sdk.Result, error) {
|
||||
var msgResult *sdk.Result
|
||||
var err error
|
||||
for _, serviceMsg := range serviceMsgs {
|
||||
signers := serviceMsg.GetSigners()
|
||||
for _, msg := range msgs {
|
||||
signers := msg.GetSigners()
|
||||
if len(signers) != 1 {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "authorization can be given to msg with only one signer")
|
||||
}
|
||||
granter := signers[0]
|
||||
if !granter.Equals(grantee) {
|
||||
authorization, _ := k.GetOrRevokeAuthorization(ctx, grantee, granter, serviceMsg.MethodName)
|
||||
authorization, _ := k.GetOrRevokeAuthorization(ctx, grantee, granter, sdk.MsgTypeURL(msg))
|
||||
if authorization == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "authorization not found")
|
||||
}
|
||||
updated, del, err := authorization.Accept(ctx, serviceMsg)
|
||||
updated, del, err := authorization.Accept(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if del {
|
||||
k.Revoke(ctx, grantee, granter, serviceMsg.Type())
|
||||
err = k.Revoke(ctx, grantee, granter, sdk.MsgTypeURL(msg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if updated != nil {
|
||||
err = k.update(ctx, grantee, granter, updated)
|
||||
if err != nil {
|
||||
|
@ -100,15 +103,15 @@ func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, service
|
|||
}
|
||||
}
|
||||
}
|
||||
handler := k.router.Handler(serviceMsg.Route())
|
||||
handler := k.router.Handler(msg)
|
||||
|
||||
if handler == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s", serviceMsg.Route())
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s", sdk.MsgTypeURL(msg))
|
||||
}
|
||||
|
||||
msgResult, err = handler(ctx, serviceMsg.Request)
|
||||
msgResult, err = handler(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "failed to execute message; message %s", serviceMsg.MethodName)
|
||||
return nil, sdkerrors.Wrapf(err, "failed to execute message; message %v", msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,11 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/authz/types"
|
||||
|
@ -42,7 +38,6 @@ func (s *TestSuite) SetupTest() {
|
|||
s.ctx = ctx
|
||||
s.queryClient = queryClient
|
||||
s.addrs = simapp.AddTestAddrsIncremental(app, ctx, 3, sdk.NewInt(30000000))
|
||||
|
||||
}
|
||||
|
||||
func (s *TestSuite) TestKeeper() {
|
||||
|
@ -76,7 +71,7 @@ func (s *TestSuite) TestKeeper() {
|
|||
s.Require().Equal(authorization.MethodName(), banktypes.SendAuthorization{}.MethodName())
|
||||
|
||||
s.T().Log("verify fetching authorization with wrong msg type fails")
|
||||
authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, proto.MessageName(&banktypes.MsgMultiSend{}))
|
||||
authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, sdk.MsgTypeURL(&banktypes.MsgMultiSend{}))
|
||||
s.Require().Nil(authorization)
|
||||
|
||||
s.T().Log("verify fetching authorization with wrong grantee fails")
|
||||
|
@ -139,21 +134,18 @@ func (s *TestSuite) TestKeeperFees() {
|
|||
smallCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 20))
|
||||
someCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 123))
|
||||
|
||||
msgs := types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{
|
||||
{
|
||||
MethodName: banktypes.SendAuthorization{}.MethodName(),
|
||||
Request: &banktypes.MsgSend{
|
||||
Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)),
|
||||
FromAddress: granterAddr.String(),
|
||||
ToAddress: recipientAddr.String(),
|
||||
},
|
||||
msgs := types.NewMsgExecAuthorized(granteeAddr, []sdk.Msg{
|
||||
&banktypes.MsgSend{
|
||||
Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)),
|
||||
FromAddress: granterAddr.String(),
|
||||
ToAddress: recipientAddr.String(),
|
||||
},
|
||||
})
|
||||
|
||||
s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec()))
|
||||
|
||||
s.T().Log("verify dispatch fails with invalid authorization")
|
||||
executeMsgs, err := msgs.GetServiceMsgs()
|
||||
executeMsgs, err := msgs.GetMessages()
|
||||
s.Require().NoError(err)
|
||||
result, err := app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs)
|
||||
|
||||
|
@ -169,7 +161,7 @@ func (s *TestSuite) TestKeeperFees() {
|
|||
|
||||
s.Require().Equal(authorization.MethodName(), banktypes.SendAuthorization{}.MethodName())
|
||||
|
||||
executeMsgs, err = msgs.GetServiceMsgs()
|
||||
executeMsgs, err = msgs.GetMessages()
|
||||
s.Require().NoError(err)
|
||||
|
||||
result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs)
|
||||
|
@ -182,19 +174,16 @@ func (s *TestSuite) TestKeeperFees() {
|
|||
s.T().Log("verify dispatch fails with overlimit")
|
||||
// grant authorization
|
||||
|
||||
msgs = types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{
|
||||
{
|
||||
MethodName: banktypes.SendAuthorization{}.MethodName(),
|
||||
Request: &banktypes.MsgSend{
|
||||
Amount: someCoin,
|
||||
FromAddress: granterAddr.String(),
|
||||
ToAddress: recipientAddr.String(),
|
||||
},
|
||||
msgs = types.NewMsgExecAuthorized(granteeAddr, []sdk.Msg{
|
||||
&banktypes.MsgSend{
|
||||
Amount: someCoin,
|
||||
FromAddress: granterAddr.String(),
|
||||
ToAddress: recipientAddr.String(),
|
||||
},
|
||||
})
|
||||
|
||||
s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec()))
|
||||
executeMsgs, err = msgs.GetServiceMsgs()
|
||||
executeMsgs, err = msgs.GetMessages()
|
||||
s.Require().NoError(err)
|
||||
|
||||
result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs)
|
||||
|
|
|
@ -24,7 +24,7 @@ func (k Keeper) GrantAuthorization(goCtx context.Context, msg *types.MsgGrantAut
|
|||
|
||||
authorization := msg.GetGrantAuthorization()
|
||||
// If the granted service Msg doesn't exist, we throw an error.
|
||||
if k.router.Handler(authorization.MethodName()) == nil {
|
||||
if k.router.HandlerbyTypeURL(authorization.MethodName()) == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "%s doesn't exist.", authorization.MethodName())
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ func (k Keeper) ExecAuthorized(goCtx context.Context, msg *types.MsgExecAuthoriz
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgs, err := msg.GetServiceMsgs()
|
||||
msgs, err := msg.GetMessages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -20,10 +20,12 @@ import (
|
|||
)
|
||||
|
||||
// authz message types
|
||||
const (
|
||||
TypeMsgGrantAuthorization = "/cosmos.authz.v1beta1.Msg/GrantAuthorization"
|
||||
TypeMsgRevokeAuthorization = "/cosmos.authz.v1beta1.Msg/RevokeAuthorization"
|
||||
TypeMsgExecDelegated = "/cosmos.authz.v1beta1.Msg/ExecAuthorized"
|
||||
var (
|
||||
// TODO Remove `Request` suffix
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/9114
|
||||
TypeMsgGrantAuthorization = sdk.MsgTypeURL(&types.MsgGrantAuthorizationRequest{})
|
||||
TypeMsgRevokeAuthorization = sdk.MsgTypeURL(&types.MsgRevokeAuthorizationRequest{})
|
||||
TypeMsgExecDelegated = sdk.MsgTypeURL(&types.MsgExecAuthorizedRequest{})
|
||||
)
|
||||
|
||||
// Simulation operation weights constants
|
||||
|
@ -130,7 +132,7 @@ func SimulateMsgGrantAuthorization(ak types.AccountKeeper, bk types.BankKeeper,
|
|||
|
||||
_, _, err = app.Deliver(txGen.TxEncoder(), tx)
|
||||
if err != nil {
|
||||
return simtypes.NoOpMsg(types.ModuleName, svcMsgClientConn.GetMsgs()[0].Type(), "unable to deliver tx"), nil, err
|
||||
return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(svcMsgClientConn.GetMsgs()[0]), "unable to deliver tx"), nil, err
|
||||
}
|
||||
return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err
|
||||
}
|
||||
|
@ -242,16 +244,13 @@ func SimulateMsgExecuteAuthorized(ak types.AccountKeeper, bk types.BankKeeper, k
|
|||
}
|
||||
sendCoins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(10)))
|
||||
|
||||
execMsg := sdk.ServiceMsg{
|
||||
MethodName: banktype.SendAuthorization{}.MethodName(),
|
||||
Request: banktype.NewMsgSend(
|
||||
granterAddr,
|
||||
granteeAddr,
|
||||
sendCoins,
|
||||
),
|
||||
}
|
||||
execMsg := banktype.NewMsgSend(
|
||||
granterAddr,
|
||||
granteeAddr,
|
||||
sendCoins,
|
||||
)
|
||||
|
||||
msg := types.NewMsgExecAuthorized(grantee.Address, []sdk.ServiceMsg{execMsg})
|
||||
msg := types.NewMsgExecAuthorized(grantee.Address, []sdk.Msg{execMsg})
|
||||
sendGrant := targetGrant.Authorization.GetCachedValue().(*banktype.SendAuthorization)
|
||||
_, _, err = sendGrant.Accept(ctx, execMsg)
|
||||
if err != nil {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
// RegisterInterfaces registers the interfaces types with the interface registry
|
||||
func RegisterInterfaces(registry types.InterfaceRegistry) {
|
||||
registry.RegisterImplementations((*sdk.MsgRequest)(nil),
|
||||
registry.RegisterImplementations((*sdk.Msg)(nil),
|
||||
&MsgGrantAuthorizationRequest{},
|
||||
&MsgRevokeAuthorizationRequest{},
|
||||
&MsgExecAuthorizedRequest{},
|
||||
|
|
|
@ -2,8 +2,6 @@ package types
|
|||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
"github.com/cosmos/cosmos-sdk/x/authz/exported"
|
||||
)
|
||||
|
||||
|
@ -24,14 +22,11 @@ func (authorization GenericAuthorization) MethodName() string {
|
|||
}
|
||||
|
||||
// Accept implements Authorization.Accept.
|
||||
func (authorization GenericAuthorization) Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated exported.Authorization, delete bool, err error) {
|
||||
func (authorization GenericAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (updated exported.Authorization, delete bool, err error) {
|
||||
return &authorization, false, nil
|
||||
}
|
||||
|
||||
// ValidateBasic implements Authorization.ValidateBasic.
|
||||
func (authorization GenericAuthorization) ValidateBasic() error {
|
||||
if !msgservice.IsServiceMsg(authorization.MessageName) {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, " %s is not a valid service msg", authorization.MessageName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -10,12 +10,8 @@ import (
|
|||
)
|
||||
|
||||
func TestGenericAuthorization(t *testing.T) {
|
||||
t.Log("verify ValidateBasic returns error for non-service msg")
|
||||
authorization := types.NewGenericAuthorization(banktypes.TypeMsgSend)
|
||||
require.Error(t, authorization.ValidateBasic())
|
||||
|
||||
t.Log("verify ValidateBasic returns nil for service msg")
|
||||
authorization = types.NewGenericAuthorization(banktypes.SendAuthorization{}.MethodName())
|
||||
authorization := types.NewGenericAuthorization(banktypes.SendAuthorization{}.MethodName())
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
require.Equal(t, banktypes.SendAuthorization{}.MethodName(), authorization.MessageName)
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
_ sdk.MsgRequest = &MsgGrantAuthorizationRequest{}
|
||||
_ sdk.MsgRequest = &MsgRevokeAuthorizationRequest{}
|
||||
_ sdk.MsgRequest = &MsgExecAuthorizedRequest{}
|
||||
_ sdk.Msg = &MsgGrantAuthorizationRequest{}
|
||||
_ sdk.Msg = &MsgRevokeAuthorizationRequest{}
|
||||
_ sdk.Msg = &MsgExecAuthorizedRequest{}
|
||||
|
||||
_ types.UnpackInterfacesMessage = &MsgGrantAuthorizationRequest{}
|
||||
_ types.UnpackInterfacesMessage = &MsgExecAuthorizedRequest{}
|
||||
|
@ -96,7 +96,7 @@ func (msg *MsgGrantAuthorizationRequest) SetAuthorization(authorization exported
|
|||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||
func (msg MsgExecAuthorizedRequest) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
||||
for _, x := range msg.Msgs {
|
||||
var msgExecAuthorized sdk.MsgRequest
|
||||
var msgExecAuthorized sdk.Msg
|
||||
err := unpacker.UnpackAny(x, &msgExecAuthorized)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -155,20 +155,15 @@ func (msg MsgRevokeAuthorizationRequest) ValidateBasic() error {
|
|||
|
||||
// NewMsgExecAuthorized creates a new MsgExecAuthorized
|
||||
//nolint:interfacer
|
||||
func NewMsgExecAuthorized(grantee sdk.AccAddress, msgs []sdk.ServiceMsg) MsgExecAuthorizedRequest {
|
||||
func NewMsgExecAuthorized(grantee sdk.AccAddress, msgs []sdk.Msg) MsgExecAuthorizedRequest {
|
||||
msgsAny := make([]*types.Any, len(msgs))
|
||||
for i, msg := range msgs {
|
||||
bz, err := proto.Marshal(msg.Request)
|
||||
any, err := types.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
anyMsg := &types.Any{
|
||||
TypeUrl: msg.MethodName,
|
||||
Value: bz,
|
||||
}
|
||||
|
||||
msgsAny[i] = anyMsg
|
||||
msgsAny[i] = any
|
||||
}
|
||||
|
||||
return MsgExecAuthorizedRequest{
|
||||
|
@ -177,20 +172,15 @@ func NewMsgExecAuthorized(grantee sdk.AccAddress, msgs []sdk.ServiceMsg) MsgExec
|
|||
}
|
||||
}
|
||||
|
||||
// GetServiceMsgs returns the cache values from the MsgExecAuthorized.Msgs if present.
|
||||
func (msg MsgExecAuthorizedRequest) GetServiceMsgs() ([]sdk.ServiceMsg, error) {
|
||||
msgs := make([]sdk.ServiceMsg, len(msg.Msgs))
|
||||
// GetMessages returns the cache values from the MsgExecAuthorized.Msgs if present.
|
||||
func (msg MsgExecAuthorizedRequest) GetMessages() ([]sdk.Msg, error) {
|
||||
msgs := make([]sdk.Msg, len(msg.Msgs))
|
||||
for i, msgAny := range msg.Msgs {
|
||||
msgReq, ok := msgAny.GetCachedValue().(sdk.MsgRequest)
|
||||
msg, ok := msgAny.GetCachedValue().(sdk.Msg)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "messages contains %T which is not a sdk.MsgRequest", msgAny)
|
||||
}
|
||||
srvMsg := sdk.ServiceMsg{
|
||||
MethodName: msgAny.TypeUrl,
|
||||
Request: msgReq,
|
||||
}
|
||||
|
||||
msgs[i] = srvMsg
|
||||
msgs[i] = msg
|
||||
}
|
||||
|
||||
return msgs, nil
|
||||
|
|
|
@ -23,19 +23,16 @@ func TestMsgExecAuthorized(t *testing.T) {
|
|||
tests := []struct {
|
||||
title string
|
||||
grantee sdk.AccAddress
|
||||
msgs []sdk.ServiceMsg
|
||||
msgs []sdk.Msg
|
||||
expectPass bool
|
||||
}{
|
||||
{"nil grantee address", nil, []sdk.ServiceMsg{}, false},
|
||||
{"zero-messages test: should fail", grantee, []sdk.ServiceMsg{}, false},
|
||||
{"valid test: msg type", grantee, []sdk.ServiceMsg{
|
||||
{
|
||||
MethodName: banktypes.SendAuthorization{}.MethodName(),
|
||||
Request: &banktypes.MsgSend{
|
||||
Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)),
|
||||
FromAddress: granter.String(),
|
||||
ToAddress: grantee.String(),
|
||||
},
|
||||
{"nil grantee address", nil, []sdk.Msg{}, false},
|
||||
{"zero-messages test: should fail", grantee, []sdk.Msg{}, false},
|
||||
{"valid test: msg type", grantee, []sdk.Msg{
|
||||
&banktypes.MsgSend{
|
||||
Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)),
|
||||
FromAddress: granter.String(),
|
||||
ToAddress: grantee.String(),
|
||||
},
|
||||
}, true},
|
||||
}
|
||||
|
|
|
@ -1,22 +1,14 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, extraArgs ...string) (testutil.BufferWriter, error) {
|
||||
|
@ -32,56 +24,3 @@ func QueryBalancesExec(clientCtx client.Context, address fmt.Stringer, extraArgs
|
|||
|
||||
return clitestutil.ExecTestCLICmd(clientCtx, bankcli.GetBalancesCmd(), args)
|
||||
}
|
||||
|
||||
// LegacyGRPCProtoMsgSend is a legacy method to broadcast a legacy proto MsgSend.
|
||||
//
|
||||
// Deprecated.
|
||||
//nolint:interfacer
|
||||
func LegacyGRPCProtoMsgSend(clientCtx client.Context, keyName string, from, to sdk.Address, fee, amount []sdk.Coin, extraArgs ...string) (*txtypes.BroadcastTxResponse, error) {
|
||||
// prepare txBuilder with msg
|
||||
txBuilder := clientCtx.TxConfig.NewTxBuilder()
|
||||
feeAmount := fee
|
||||
gasLimit := testdata.NewTestGasLimit()
|
||||
|
||||
// This sets a legacy Proto MsgSend.
|
||||
err := txBuilder.SetMsgs(&types.MsgSend{
|
||||
FromAddress: from.String(),
|
||||
ToAddress: to.String(),
|
||||
Amount: amount,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txBuilder.SetFeeAmount(feeAmount)
|
||||
txBuilder.SetGasLimit(gasLimit)
|
||||
|
||||
// setup txFactory
|
||||
txFactory := tx.Factory{}.
|
||||
WithChainID(clientCtx.ChainID).
|
||||
WithKeybase(clientCtx.Keyring).
|
||||
WithTxConfig(clientCtx.TxConfig).
|
||||
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT)
|
||||
|
||||
// Sign Tx.
|
||||
err = authclient.SignTx(txFactory, clientCtx, keyName, txBuilder, false, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Broadcast the tx via gRPC.
|
||||
queryClient := txtypes.NewServiceClient(clientCtx)
|
||||
|
||||
return queryClient.BroadcastTx(
|
||||
context.Background(),
|
||||
&txtypes.BroadcastTxRequest{
|
||||
Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC,
|
||||
TxBytes: txBytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -383,10 +383,7 @@ func (s *IntegrationTestSuite) TestNewSendTxCmdGenOnly() {
|
|||
s.Require().NoError(err)
|
||||
tx, err := s.cfg.TxConfig.TxJSONDecoder()(bz.Bytes())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal([]sdk.Msg{sdk.ServiceMsg{
|
||||
MethodName: "/cosmos.bank.v1beta1.Msg/Send",
|
||||
Request: types.NewMsgSend(from, to, amount),
|
||||
}}, tx.GetMsgs())
|
||||
s.Require().Equal([]sdk.Msg{types.NewMsgSend(from, to, amount)}, tx.GetMsgs())
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestNewSendTxCmd() {
|
||||
|
@ -473,62 +470,6 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() {
|
|||
}
|
||||
}
|
||||
|
||||
// TestBankMsgService does a basic test of whether or not service Msg's as defined
|
||||
// in ADR 031 work in the most basic end-to-end case.
|
||||
func (s *IntegrationTestSuite) TestBankMsgService() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
from, to sdk.AccAddress
|
||||
amount sdk.Coins
|
||||
args []string
|
||||
expectErr bool
|
||||
expectedCode uint32
|
||||
respType proto.Message
|
||||
rawLogContains string
|
||||
}{
|
||||
{
|
||||
"valid transaction",
|
||||
val.Address,
|
||||
val.Address,
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
|
||||
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
|
||||
),
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
false,
|
||||
0,
|
||||
&sdk.TxResponse{},
|
||||
"/cosmos.bank.v1beta1.Msg/Send", // indicates we are using ServiceMsg and not a regular Msg
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
clientCtx := val.ClientCtx
|
||||
|
||||
bz, err := MsgSendExec(clientCtx, tc.from, tc.to, tc.amount, tc.args...)
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(bz.Bytes(), tc.respType), bz.String())
|
||||
txResp := tc.respType.(*sdk.TxResponse)
|
||||
s.Require().Equal(tc.expectedCode, txResp.Code)
|
||||
s.Require().Contains(txResp.RawLog, tc.rawLogContains)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func NewCoin(denom string, amount sdk.Int) *sdk.Coin {
|
||||
coin := sdk.NewCoin(denom, amount)
|
||||
return &coin
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authz "github.com/cosmos/cosmos-sdk/x/authz/exported"
|
||||
|
@ -21,26 +19,25 @@ func NewSendAuthorization(spendLimit sdk.Coins) *SendAuthorization {
|
|||
|
||||
// MethodName implements Authorization.MethodName.
|
||||
func (authorization SendAuthorization) MethodName() string {
|
||||
return "/cosmos.bank.v1beta1.Msg/Send"
|
||||
return sdk.MsgTypeURL(&MsgSend{})
|
||||
}
|
||||
|
||||
// Accept implements Authorization.Accept.
|
||||
func (authorization SendAuthorization) Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated authz.Authorization, delete bool, err error) {
|
||||
if reflect.TypeOf(msg.Request) == reflect.TypeOf(&MsgSend{}) {
|
||||
msg, ok := msg.Request.(*MsgSend)
|
||||
if ok {
|
||||
limitLeft, isNegative := authorization.SpendLimit.SafeSub(msg.Amount)
|
||||
if isNegative {
|
||||
return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit")
|
||||
}
|
||||
if limitLeft.IsZero() {
|
||||
return nil, true, nil
|
||||
}
|
||||
|
||||
return &SendAuthorization{SpendLimit: limitLeft}, false, nil
|
||||
}
|
||||
func (authorization SendAuthorization) Accept(_ sdk.Context, msg sdk.Msg) (updated authz.Authorization, delete bool, err error) {
|
||||
msgSend, ok := msg.(*MsgSend)
|
||||
if !ok {
|
||||
return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "type mismatch")
|
||||
}
|
||||
return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "type mismatch")
|
||||
|
||||
limitLeft, isNegative := authorization.SpendLimit.SafeSub(msgSend.Amount)
|
||||
if isNegative {
|
||||
return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit")
|
||||
}
|
||||
if limitLeft.IsZero() {
|
||||
return nil, true, nil
|
||||
}
|
||||
|
||||
return &SendAuthorization{SpendLimit: limitLeft}, false, nil
|
||||
}
|
||||
|
||||
// ValidateBasic implements Authorization.ValidateBasic.
|
||||
|
|
|
@ -24,31 +24,24 @@ func TestSendAuthorization(t *testing.T) {
|
|||
authorization := types.NewSendAuthorization(coins1000)
|
||||
|
||||
t.Log("verify authorization returns valid method name")
|
||||
require.Equal(t, authorization.MethodName(), "/cosmos.bank.v1beta1.Msg/Send")
|
||||
require.Equal(t, authorization.MethodName(), "/cosmos.bank.v1beta1.MsgSend")
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
send := types.NewMsgSend(fromAddr, toAddr, coins1000)
|
||||
srvMsg := sdk.ServiceMsg{
|
||||
MethodName: "/cosmos.bank.v1beta1.Msg/Send",
|
||||
Request: send,
|
||||
}
|
||||
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
|
||||
t.Log("verify updated authorization returns nil")
|
||||
updated, del, err := authorization.Accept(ctx, srvMsg)
|
||||
updated, del, err := authorization.Accept(ctx, send)
|
||||
require.NoError(t, err)
|
||||
require.True(t, del)
|
||||
require.Nil(t, updated)
|
||||
|
||||
authorization = types.NewSendAuthorization(coins1000)
|
||||
require.Equal(t, authorization.MethodName(), "/cosmos.bank.v1beta1.Msg/Send")
|
||||
require.Equal(t, authorization.MethodName(), "/cosmos.bank.v1beta1.MsgSend")
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
send = types.NewMsgSend(fromAddr, toAddr, coins500)
|
||||
srvMsg = sdk.ServiceMsg{
|
||||
MethodName: "/cosmos.bank.v1beta1.Msg/Send",
|
||||
Request: send,
|
||||
}
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
updated, del, err = authorization.Accept(ctx, srvMsg)
|
||||
updated, del, err = authorization.Accept(ctx, send)
|
||||
|
||||
t.Log("verify updated authorization returns remaining spent limit")
|
||||
require.NoError(t, err)
|
||||
|
@ -58,7 +51,7 @@ func TestSendAuthorization(t *testing.T) {
|
|||
require.Equal(t, sendAuth.String(), updated.String())
|
||||
|
||||
t.Log("expect updated authorization nil after spending remaining amount")
|
||||
updated, del, err = updated.Accept(ctx, srvMsg)
|
||||
updated, del, err = updated.Accept(ctx, send)
|
||||
require.NoError(t, err)
|
||||
require.True(t, del)
|
||||
require.Nil(t, updated)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||
"github.com/cosmos/cosmos-sdk/x/evidence/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/evidence/types"
|
||||
)
|
||||
|
@ -50,8 +51,8 @@ func TestMsgSubmitEvidence(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
require.Equal(t, tc.msg.Route(), types.RouterKey, "unexpected result for tc #%d", i)
|
||||
require.Equal(t, tc.msg.Type(), types.TypeMsgSubmitEvidence, "unexpected result for tc #%d", i)
|
||||
require.Equal(t, tc.msg.(legacytx.LegacyMsg).Route(), types.RouterKey, "unexpected result for tc #%d", i)
|
||||
require.Equal(t, tc.msg.(legacytx.LegacyMsg).Type(), types.TypeMsgSubmitEvidence, "unexpected result for tc #%d", i)
|
||||
require.Equal(t, tc.expectErr, tc.msg.ValidateBasic() != nil, "unexpected result for tc #%d", i)
|
||||
|
||||
if !tc.expectErr {
|
||||
|
|
|
@ -58,7 +58,7 @@ Examples:
|
|||
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 2022-01-30T15:04:05Z or
|
||||
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --period 3600 --period-limit 10stake --expiration 36000 or
|
||||
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 2022-01-30T15:04:05Z
|
||||
--allowed-messages "/cosmos.gov.v1beta1.Msg/SubmitProposal,/cosmos.gov.v1beta1.Msg/Vote"
|
||||
--allowed-messages "/cosmos.gov.v1beta1.MsgSubmitProposal,/cosmos.gov.v1beta1.MsgVote"
|
||||
`, version.AppName, types.ModuleName, version.AppName, types.ModuleName, version.AppName, types.ModuleName,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -2,6 +2,7 @@ package testutil
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -649,7 +650,7 @@ func (s *IntegrationTestSuite) TestFilteredFeeAllowance() {
|
|||
}
|
||||
spendLimit := sdk.NewCoin("stake", sdk.NewInt(1000))
|
||||
|
||||
allowMsgs := "/cosmos.gov.v1beta1.Msg/SubmitProposal,weighted_vote"
|
||||
allowMsgs := strings.Join([]string{sdk.MsgTypeURL(&govtypes.MsgSubmitProposal{}), sdk.MsgTypeURL(&govtypes.MsgVoteWeighted{})}, ",")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
|
|
@ -52,7 +52,7 @@ func generateRandomAllowances(granter, grantee sdk.AccAddress, r *rand.Rand) typ
|
|||
|
||||
filteredAllowance, err := types.NewFeeAllowanceGrant(granter, grantee, &types.AllowedMsgFeeAllowance{
|
||||
Allowance: basicAllowance.GetAllowance(),
|
||||
AllowedMessages: []string{"/cosmos.gov.v1beta1.Msg/SubmitProposal"},
|
||||
AllowedMessages: []string{"/cosmos.gov.v1beta1.MsgSubmitProposal"},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -21,8 +21,11 @@ import (
|
|||
const (
|
||||
OpWeightMsgGrantFeeAllowance = "op_weight_msg_grant_fee_allowance"
|
||||
OpWeightMsgRevokeFeeAllowance = "op_weight_msg_grant_revoke_allowance"
|
||||
TypeMsgGrantFeeAllowance = "/cosmos.feegrant.v1beta1.Msg/GrantFeeAllowance"
|
||||
TypeMsgRevokeFeeAllowance = "/cosmos.feegrant.v1beta1.Msg/RevokeFeeAllowance"
|
||||
)
|
||||
|
||||
var (
|
||||
TypeMsgGrantFeeAllowance = sdk.MsgTypeURL(&types.MsgGrantFeeAllowance{})
|
||||
TypeMsgRevokeFeeAllowance = sdk.MsgTypeURL(&types.MsgRevokeFeeAllowance{})
|
||||
)
|
||||
|
||||
func WeightedOperations(
|
||||
|
@ -121,7 +124,7 @@ func SimulateMsgGrantFeeAllowance(ak types.AccountKeeper, bk types.BankKeeper, k
|
|||
_, _, err = app.Deliver(txGen.TxEncoder(), tx)
|
||||
|
||||
if err != nil {
|
||||
return simtypes.NoOpMsg(types.ModuleName, svcMsgClientConn.GetMsgs()[0].Type(), "unable to deliver tx"), nil, err
|
||||
return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(svcMsgClientConn.GetMsgs()[0]), "unable to deliver tx"), nil, err
|
||||
}
|
||||
return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
// RegisterInterfaces registers the interfaces types with the interface registry
|
||||
func RegisterInterfaces(registry types.InterfaceRegistry) {
|
||||
registry.RegisterImplementations((*sdk.MsgRequest)(nil),
|
||||
registry.RegisterImplementations((*sdk.Msg)(nil),
|
||||
&MsgGrantFeeAllowance{},
|
||||
&MsgRevokeFeeAllowance{},
|
||||
)
|
||||
|
|
|
@ -80,7 +80,7 @@ func (a *AllowedMsgFeeAllowance) allMsgTypesAllowed(ctx sdk.Context, msgs []sdk.
|
|||
|
||||
for _, msg := range msgs {
|
||||
ctx.GasMeter().ConsumeGas(gasCostPerIteration, "check msg")
|
||||
if !msgsMap[msg.Type()] {
|
||||
if !msgsMap[sdk.MsgTypeURL(msg)] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
_, _ sdk.MsgRequest = &MsgGrantFeeAllowance{}, &MsgRevokeFeeAllowance{}
|
||||
_, _ sdk.Msg = &MsgGrantFeeAllowance{}, &MsgRevokeFeeAllowance{}
|
||||
_ types.UnpackInterfacesMessage = &MsgGrantFeeAllowance{}
|
||||
)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
@ -84,7 +85,7 @@ func (s *IntegrationTestSuite) TestGenTxCmd() {
|
|||
msgs := tx.GetMsgs()
|
||||
s.Require().Len(msgs, 1)
|
||||
|
||||
s.Require().Equal(types.TypeMsgCreateValidator, msgs[0].Type())
|
||||
s.Require().Equal(types.TypeMsgCreateValidator, msgs[0].(legacytx.LegacyMsg).Type())
|
||||
s.Require().Equal([]sdk.AccAddress{val.Address}, msgs[0].GetSigners())
|
||||
s.Require().Equal(amount, msgs[0].(*types.MsgCreateValidator).Value)
|
||||
err = tx.ValidateBasic()
|
||||
|
|
|
@ -39,14 +39,14 @@ func (p Proposer) String() string {
|
|||
func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposalParams) ([]byte, error) {
|
||||
searchResult, err := combineEvents(
|
||||
clientCtx, defaultPage,
|
||||
// Query old Msgs
|
||||
// Query legacy Msgs event action
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
},
|
||||
// Query service Msgs
|
||||
// Query proto Msgs event action
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgDeposit),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgDeposit{})),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
},
|
||||
)
|
||||
|
@ -58,14 +58,7 @@ func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposal
|
|||
|
||||
for _, info := range searchResult.Txs {
|
||||
for _, msg := range info.GetTx().GetMsgs() {
|
||||
var depMsg *types.MsgDeposit
|
||||
if msg.Type() == types.TypeSvcMsgDeposit {
|
||||
depMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgDeposit)
|
||||
} else if protoDepMsg, ok := msg.(*types.MsgDeposit); ok {
|
||||
depMsg = protoDepMsg
|
||||
}
|
||||
|
||||
if depMsg != nil {
|
||||
if depMsg, ok := msg.(*types.MsgDeposit); ok {
|
||||
deposits = append(deposits, types.Deposit{
|
||||
Depositor: depMsg.Depositor,
|
||||
ProposalId: params.ProposalID,
|
||||
|
@ -95,27 +88,27 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot
|
|||
|
||||
// query interrupted either if we collected enough votes or tx indexer run out of relevant txs
|
||||
for len(votes) < totalLimit {
|
||||
// Search for both (old) votes and weighted votes.
|
||||
// Search for both (legacy) votes and weighted votes.
|
||||
searchResult, err := combineEvents(
|
||||
clientCtx, nextTxPage,
|
||||
// Query old Vote Msgs
|
||||
// Query legacy Vote Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
},
|
||||
// Query Vote service Msgs
|
||||
// Query Vote proto Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVote),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgVote{})),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
},
|
||||
// Query old VoteWeighted Msgs
|
||||
// Query legacy VoteWeighted Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVoteWeighted),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
},
|
||||
// Query VoteWeighted service Msgs
|
||||
// Query VoteWeighted proto Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVoteWeighted),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgVoteWeighted{})),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
},
|
||||
)
|
||||
|
@ -125,14 +118,7 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot
|
|||
|
||||
for _, info := range searchResult.Txs {
|
||||
for _, msg := range info.GetTx().GetMsgs() {
|
||||
var voteMsg *types.MsgVote
|
||||
if msg.Type() == types.TypeSvcMsgVote {
|
||||
voteMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgVote)
|
||||
} else if protoVoteMsg, ok := msg.(*types.MsgVote); ok {
|
||||
voteMsg = protoVoteMsg
|
||||
}
|
||||
|
||||
if voteMsg != nil {
|
||||
if voteMsg, ok := msg.(*types.MsgVote); ok {
|
||||
votes = append(votes, types.Vote{
|
||||
Voter: voteMsg.Voter,
|
||||
ProposalId: params.ProposalID,
|
||||
|
@ -140,14 +126,7 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot
|
|||
})
|
||||
}
|
||||
|
||||
var voteWeightedMsg *types.MsgVoteWeighted
|
||||
if msg.Type() == types.TypeSvcMsgVoteWeighted {
|
||||
voteWeightedMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgVoteWeighted)
|
||||
} else if protoVoteWeightedMsg, ok := msg.(*types.MsgVoteWeighted); ok {
|
||||
voteWeightedMsg = protoVoteWeightedMsg
|
||||
}
|
||||
|
||||
if voteWeightedMsg != nil {
|
||||
if voteWeightedMsg, ok := msg.(*types.MsgVoteWeighted); ok {
|
||||
votes = append(votes, types.Vote{
|
||||
Voter: voteWeightedMsg.Voter,
|
||||
ProposalId: params.ProposalID,
|
||||
|
@ -181,27 +160,27 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot
|
|||
func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) ([]byte, error) {
|
||||
searchResult, err := combineEvents(
|
||||
clientCtx, defaultPage,
|
||||
// Query old Vote Msgs
|
||||
// Query legacy Vote Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())),
|
||||
},
|
||||
// Query Vote service Msgs
|
||||
// Query Vote proto Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVote),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgVote{})),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())),
|
||||
},
|
||||
// Query old VoteWeighted Msgs
|
||||
// Query legacy VoteWeighted Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVoteWeighted),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())),
|
||||
},
|
||||
// Query VoteWeighted service Msgs
|
||||
// Query VoteWeighted proto Msgs
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVoteWeighted),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgVoteWeighted{})),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())),
|
||||
},
|
||||
|
@ -212,37 +191,26 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams)
|
|||
|
||||
for _, info := range searchResult.Txs {
|
||||
for _, msg := range info.GetTx().GetMsgs() {
|
||||
var voteMsg *types.MsgVote
|
||||
// there should only be a single vote under the given conditions
|
||||
if msg.Type() == types.TypeSvcMsgVote {
|
||||
voteMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgVote)
|
||||
} else if protoVoteMsg, ok := msg.(*types.MsgVote); ok {
|
||||
voteMsg = protoVoteMsg
|
||||
}
|
||||
|
||||
if voteMsg != nil {
|
||||
vote := types.Vote{
|
||||
var vote *types.Vote
|
||||
if voteMsg, ok := msg.(*types.MsgVote); ok {
|
||||
vote = &types.Vote{
|
||||
Voter: voteMsg.Voter,
|
||||
ProposalId: params.ProposalID,
|
||||
Options: types.NewNonSplitVoteOption(voteMsg.Option),
|
||||
}
|
||||
}
|
||||
|
||||
bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
} else if msg.Type() == types.TypeMsgVoteWeighted {
|
||||
voteMsg := msg.(*types.MsgVoteWeighted)
|
||||
|
||||
vote := types.Vote{
|
||||
Voter: voteMsg.Voter,
|
||||
if voteWeightedMsg, ok := msg.(*types.MsgVoteWeighted); ok {
|
||||
vote = &types.Vote{
|
||||
Voter: voteWeightedMsg.Voter,
|
||||
ProposalId: params.ProposalID,
|
||||
Options: voteMsg.Options,
|
||||
Options: voteWeightedMsg.Options,
|
||||
}
|
||||
}
|
||||
|
||||
bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote)
|
||||
if vote != nil {
|
||||
bz, err := clientCtx.JSONMarshaler.MarshalJSON(vote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -260,15 +228,15 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams)
|
|||
func QueryDepositByTxQuery(clientCtx client.Context, params types.QueryDepositParams) ([]byte, error) {
|
||||
searchResult, err := combineEvents(
|
||||
clientCtx, defaultPage,
|
||||
// Query old Msgs
|
||||
// Query legacy Msgs event action
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Depositor.String())),
|
||||
},
|
||||
// Query service Msgs
|
||||
// Query proto Msgs event action
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgDeposit),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgDeposit{})),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Depositor.String())),
|
||||
},
|
||||
|
@ -279,15 +247,8 @@ func QueryDepositByTxQuery(clientCtx client.Context, params types.QueryDepositPa
|
|||
|
||||
for _, info := range searchResult.Txs {
|
||||
for _, msg := range info.GetTx().GetMsgs() {
|
||||
var depMsg *types.MsgDeposit
|
||||
// there should only be a single deposit under the given conditions
|
||||
if msg.Type() == types.TypeSvcMsgDeposit {
|
||||
depMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgDeposit)
|
||||
} else if protoDepMsg, ok := msg.(*types.MsgDeposit); ok {
|
||||
depMsg = protoDepMsg
|
||||
}
|
||||
|
||||
if depMsg != nil {
|
||||
if depMsg, ok := msg.(*types.MsgDeposit); ok {
|
||||
deposit := types.Deposit{
|
||||
Depositor: depMsg.Depositor,
|
||||
ProposalId: params.ProposalID,
|
||||
|
@ -313,14 +274,14 @@ func QueryProposerByTxQuery(clientCtx client.Context, proposalID uint64) (Propos
|
|||
searchResult, err := combineEvents(
|
||||
clientCtx,
|
||||
defaultPage,
|
||||
// Query old Msgs
|
||||
// Query legacy Msgs event action
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgSubmitProposal),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))),
|
||||
},
|
||||
// Query service Msgs
|
||||
// Query proto Msgs event action
|
||||
[]string{
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgSubmitProposal),
|
||||
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgSubmitProposal{})),
|
||||
fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))),
|
||||
},
|
||||
)
|
||||
|
@ -331,13 +292,7 @@ func QueryProposerByTxQuery(clientCtx client.Context, proposalID uint64) (Propos
|
|||
for _, info := range searchResult.Txs {
|
||||
for _, msg := range info.GetTx().GetMsgs() {
|
||||
// there should only be a single proposal under the given conditions
|
||||
if msg.Type() == types.TypeSvcMsgSubmitProposal {
|
||||
subMsg := msg.(sdk.ServiceMsg).Request.(*types.MsgSubmitProposal)
|
||||
|
||||
return NewProposer(proposalID, subMsg.Proposer), nil
|
||||
} else if protoSubMsg, ok := msg.(*types.MsgSubmitProposal); ok {
|
||||
subMsg := protoSubMsg
|
||||
|
||||
if subMsg, ok := msg.(*types.MsgSubmitProposal); ok {
|
||||
return NewProposer(proposalID, subMsg.Proposer), nil
|
||||
}
|
||||
}
|
||||
|
@ -367,7 +322,7 @@ func QueryProposalByID(proposalID uint64, clientCtx client.Context, queryRoute s
|
|||
//
|
||||
// Tx are indexed in tendermint via their Msgs `Type()`, which can be:
|
||||
// - via legacy Msgs (amino or proto), their `Type()` is a custom string,
|
||||
// - via ADR-031 service msgs, their `Type()` is the protobuf FQ method name.
|
||||
// - via ADR-031 proto msgs, their `Type()` is the protobuf FQ method name.
|
||||
// In searching for events, we search for both `Type()`s, and we use the
|
||||
// `combineEvents` function here to merge events.
|
||||
func combineEvents(clientCtx client.Context, page int, eventGroups ...[]string) (*sdk.SearchTxsResult, error) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
)
|
||||
|
@ -44,7 +45,7 @@ func (mock TxSearchMock) TxSearch(ctx context.Context, query string, prove bool,
|
|||
return nil, err
|
||||
}
|
||||
for _, msg := range sdkTx.GetMsgs() {
|
||||
if msg.Type() == msgType {
|
||||
if msg.(legacytx.LegacyMsg).Type() == msgType {
|
||||
matchingTxs = append(matchingTxs, tx)
|
||||
break
|
||||
}
|
||||
|
|
|
@ -18,12 +18,6 @@ const (
|
|||
TypeMsgVote = "vote"
|
||||
TypeMsgVoteWeighted = "weighted_vote"
|
||||
TypeMsgSubmitProposal = "submit_proposal"
|
||||
|
||||
// These are used for querying events by action.
|
||||
TypeSvcMsgDeposit = "/cosmos.gov.v1beta1.Msg/Deposit"
|
||||
TypeSvcMsgVote = "/cosmos.gov.v1beta1.Msg/Vote"
|
||||
TypeSvcMsgVoteWeighted = "/cosmos.gov.v1beta1.Msg/VoteWeighted"
|
||||
TypeSvcMsgSubmitProposal = "/cosmos.gov.v1beta1.Msg/SubmitProposal"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -153,28 +153,22 @@ func delegatorTxsHandlerFn(clientCtx client.Context) http.HandlerFunc {
|
|||
|
||||
// For each case, we search txs for both:
|
||||
// - legacy messages: their Type() is a custom string, e.g. "delegate"
|
||||
// - service Msgs: their Type() is their FQ method name, e.g. "/cosmos.staking.v1beta1.Msg/Delegate"
|
||||
// - service Msgs: their Type() is their FQ method name, e.g. "/cosmos.staking.v1beta1.MsgDelegate"
|
||||
// and we combine the results.
|
||||
switch {
|
||||
case isBondTx:
|
||||
actions = append(actions, types.TypeMsgDelegate)
|
||||
actions = append(actions, types.TypeSvcMsgDelegate)
|
||||
|
||||
case isUnbondTx:
|
||||
actions = append(actions, types.TypeMsgUndelegate)
|
||||
actions = append(actions, types.TypeSvcMsgUndelegate)
|
||||
|
||||
case isRedTx:
|
||||
actions = append(actions, types.TypeMsgBeginRedelegate)
|
||||
actions = append(actions, types.TypeSvcMsgBeginRedelegate)
|
||||
|
||||
case noQuery:
|
||||
actions = append(actions, types.TypeMsgDelegate)
|
||||
actions = append(actions, types.TypeSvcMsgDelegate)
|
||||
actions = append(actions, types.TypeMsgUndelegate)
|
||||
actions = append(actions, types.TypeSvcMsgUndelegate)
|
||||
actions = append(actions, types.TypeMsgBeginRedelegate)
|
||||
actions = append(actions, types.TypeSvcMsgBeginRedelegate)
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
|
|
@ -12,10 +12,6 @@ const gasCostPerIteration = uint64(10)
|
|||
|
||||
var (
|
||||
_ authz.Authorization = &StakeAuthorization{}
|
||||
|
||||
TypeDelegate = "/cosmos.staking.v1beta1.Msg/Delegate"
|
||||
TypeUndelegate = "/cosmos.staking.v1beta1.Msg/Undelegate"
|
||||
TypeBeginRedelegate = "/cosmos.staking.v1beta1.Msg/BeginRedelegate"
|
||||
)
|
||||
|
||||
// NewStakeAuthorization creates a new StakeAuthorization object.
|
||||
|
@ -61,11 +57,11 @@ func (authorization StakeAuthorization) ValidateBasic() error {
|
|||
}
|
||||
|
||||
// Accept implements Authorization.Accept.
|
||||
func (authorization StakeAuthorization) Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated authz.Authorization, delete bool, err error) {
|
||||
func (authorization StakeAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (updated authz.Authorization, delete bool, err error) {
|
||||
var validatorAddress string
|
||||
var amount sdk.Coin
|
||||
|
||||
switch msg := msg.Request.(type) {
|
||||
switch msg := msg.(type) {
|
||||
case *MsgDelegate:
|
||||
validatorAddress = msg.ValidatorAddress
|
||||
amount = msg.Amount
|
||||
|
@ -142,11 +138,11 @@ func validateAndBech32fy(allowed []sdk.ValAddress, denied []sdk.ValAddress) ([]s
|
|||
func normalizeAuthzType(authzType AuthorizationType) (string, error) {
|
||||
switch authzType {
|
||||
case AuthorizationType_AUTHORIZATION_TYPE_DELEGATE:
|
||||
return TypeDelegate, nil
|
||||
return sdk.MsgTypeURL(&MsgDelegate{}), nil
|
||||
case AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE:
|
||||
return TypeUndelegate, nil
|
||||
return sdk.MsgTypeURL(&MsgUndelegate{}), nil
|
||||
case AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE:
|
||||
return TypeBeginRedelegate, nil
|
||||
return sdk.MsgTypeURL(&MsgBeginRedelegate{}), nil
|
||||
default:
|
||||
return "", sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "unknown authorization type %T", authzType)
|
||||
}
|
||||
|
|
|
@ -3,9 +3,8 @@ package types_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -33,7 +32,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
// verify MethodName
|
||||
delAuth, err = stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, delAuth.MethodName(), stakingtypes.TypeDelegate)
|
||||
require.Equal(t, delAuth.MethodName(), sdk.MsgTypeURL(&stakingtypes.MsgDelegate{}))
|
||||
|
||||
// error both allow & deny list
|
||||
_, err = stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{val1}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100)
|
||||
|
@ -41,11 +40,11 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
|
||||
// verify MethodName
|
||||
undelAuth, _ := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, &coin100)
|
||||
require.Equal(t, undelAuth.MethodName(), stakingtypes.TypeUndelegate)
|
||||
require.Equal(t, undelAuth.MethodName(), sdk.MsgTypeURL(&stakingtypes.MsgUndelegate{}))
|
||||
|
||||
// verify MethodName
|
||||
beginRedelAuth, _ := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, &coin100)
|
||||
require.Equal(t, beginRedelAuth.MethodName(), stakingtypes.TypeBeginRedelegate)
|
||||
require.Equal(t, beginRedelAuth.MethodName(), sdk.MsgTypeURL(&stakingtypes.MsgBeginRedelegate{}))
|
||||
|
||||
validators1_2 := []string{val1.String(), val2.String()}
|
||||
|
||||
|
@ -55,7 +54,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
denied []sdk.ValAddress
|
||||
msgType stakingtypes.AuthorizationType
|
||||
limit *sdk.Coin
|
||||
srvMsg sdk.ServiceMsg
|
||||
srvMsg sdk.Msg
|
||||
expectErr bool
|
||||
isDelete bool
|
||||
updatedAuthorization *stakingtypes.StakeAuthorization
|
||||
|
@ -66,7 +65,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgDelegate(delAuth.MethodName(), delAddr, val1, coin100),
|
||||
stakingtypes.NewMsgDelegate(delAddr, val1, coin100),
|
||||
false,
|
||||
true,
|
||||
nil,
|
||||
|
@ -77,7 +76,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgDelegate(delAuth.MethodName(), delAddr, val1, coin50),
|
||||
stakingtypes.NewMsgDelegate(delAddr, val1, coin50),
|
||||
false,
|
||||
false,
|
||||
&stakingtypes.StakeAuthorization{
|
||||
|
@ -91,7 +90,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgDelegate(delAuth.MethodName(), delAddr, val3, coin100),
|
||||
stakingtypes.NewMsgDelegate(delAddr, val3, coin100),
|
||||
true,
|
||||
false,
|
||||
nil,
|
||||
|
@ -102,7 +101,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
|
||||
nil,
|
||||
createSrvMsgDelegate(delAuth.MethodName(), delAddr, val2, coin100),
|
||||
stakingtypes.NewMsgDelegate(delAddr, val2, coin100),
|
||||
false,
|
||||
false,
|
||||
&stakingtypes.StakeAuthorization{
|
||||
|
@ -116,7 +115,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{val1},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
|
||||
nil,
|
||||
createSrvMsgDelegate(delAuth.MethodName(), delAddr, val1, coin100),
|
||||
stakingtypes.NewMsgDelegate(delAddr, val1, coin100),
|
||||
true,
|
||||
false,
|
||||
nil,
|
||||
|
@ -128,7 +127,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin100),
|
||||
stakingtypes.NewMsgUndelegate(delAddr, val1, coin100),
|
||||
false,
|
||||
true,
|
||||
nil,
|
||||
|
@ -139,7 +138,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin50),
|
||||
stakingtypes.NewMsgUndelegate(delAddr, val1, coin50),
|
||||
false,
|
||||
false,
|
||||
&stakingtypes.StakeAuthorization{
|
||||
|
@ -153,7 +152,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val3, coin100),
|
||||
stakingtypes.NewMsgUndelegate(delAddr, val3, coin100),
|
||||
true,
|
||||
false,
|
||||
nil,
|
||||
|
@ -164,7 +163,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE,
|
||||
nil,
|
||||
createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val2, coin100),
|
||||
stakingtypes.NewMsgUndelegate(delAddr, val2, coin100),
|
||||
false,
|
||||
false,
|
||||
&stakingtypes.StakeAuthorization{
|
||||
|
@ -178,7 +177,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{val1},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin100),
|
||||
stakingtypes.NewMsgUndelegate(delAddr, val1, coin100),
|
||||
true,
|
||||
false,
|
||||
nil,
|
||||
|
@ -190,7 +189,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin100),
|
||||
stakingtypes.NewMsgUndelegate(delAddr, val1, coin100),
|
||||
false,
|
||||
true,
|
||||
nil,
|
||||
|
@ -201,7 +200,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val1, coin50),
|
||||
stakingtypes.NewMsgBeginRedelegate(delAddr, val1, val1, coin50),
|
||||
false,
|
||||
false,
|
||||
&stakingtypes.StakeAuthorization{
|
||||
|
@ -215,7 +214,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val3, coin100),
|
||||
stakingtypes.NewMsgBeginRedelegate(delAddr, val3, val3, coin100),
|
||||
true,
|
||||
false,
|
||||
nil,
|
||||
|
@ -226,7 +225,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE,
|
||||
nil,
|
||||
createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val2, coin100),
|
||||
stakingtypes.NewMsgBeginRedelegate(delAddr, val2, val2, coin100),
|
||||
false,
|
||||
false,
|
||||
&stakingtypes.StakeAuthorization{
|
||||
|
@ -240,7 +239,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
[]sdk.ValAddress{val1},
|
||||
stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE,
|
||||
&coin100,
|
||||
createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val1, coin100),
|
||||
stakingtypes.NewMsgBeginRedelegate(delAddr, val1, val1, coin100),
|
||||
true,
|
||||
false,
|
||||
nil,
|
||||
|
@ -266,27 +265,3 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createSrvMsgUndelegate(methodName string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) sdk.ServiceMsg {
|
||||
msg := stakingtypes.NewMsgUndelegate(delAddr, valAddr, amount)
|
||||
return sdk.ServiceMsg{
|
||||
MethodName: methodName,
|
||||
Request: msg,
|
||||
}
|
||||
}
|
||||
|
||||
func createSrvMsgReDelegate(methodName string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) sdk.ServiceMsg {
|
||||
msg := stakingtypes.NewMsgBeginRedelegate(delAddr, valAddr, valAddr, amount)
|
||||
return sdk.ServiceMsg{
|
||||
MethodName: methodName,
|
||||
Request: msg,
|
||||
}
|
||||
}
|
||||
|
||||
func createSrvMsgDelegate(methodName string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) sdk.ServiceMsg {
|
||||
msg := stakingtypes.NewMsgDelegate(delAddr, valAddr, amount)
|
||||
return sdk.ServiceMsg{
|
||||
MethodName: methodName,
|
||||
Request: msg,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,6 @@ const (
|
|||
TypeMsgCreateValidator = "create_validator"
|
||||
TypeMsgDelegate = "delegate"
|
||||
TypeMsgBeginRedelegate = "begin_redelegate"
|
||||
|
||||
// These are used for querying events by action.
|
||||
TypeSvcMsgUndelegate = "/cosmos.staking.v1beta1.Msg/Undelegate"
|
||||
TypeSvcMsgEditValidator = "/cosmos.staking.v1beta1.Msg/EditValidator"
|
||||
TypeSvcMsgCreateValidator = "/cosmos.staking.v1beta1.Msg/CreateValidator"
|
||||
TypeSvcMsgDelegate = "/cosmos.staking.v1beta1.Msg/Delegate"
|
||||
TypeSvcMsgBeginRedelegate = "/cosmos.staking.v1beta1.Msg/BeginRedelegate"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
Loading…
Reference in New Issue