From e81368da783c3116767c5975f1d7fa7c9f2e7f76 Mon Sep 17 00:00:00 2001 From: likhita-809 Date: Thu, 21 Jul 2022 15:56:45 +0530 Subject: [PATCH 1/2] revert proto changes from #12610 --- api/cosmos/bank/v1beta1/tx.pulsar.go | 255 +++++++++++++++++---------- proto/cosmos/bank/v1beta1/tx.proto | 6 +- x/bank/app_test.go | 8 +- x/bank/client/cli/tx.go | 2 +- x/bank/keeper/keeper_test.go | 27 +-- x/bank/keeper/msg_server.go | 8 +- x/bank/keeper/send.go | 35 ++-- x/bank/simulation/operations.go | 98 +++++----- x/bank/simulation/operations_test.go | 9 +- x/bank/types/errors.go | 2 + x/bank/types/msgs.go | 34 ++-- x/bank/types/msgs_test.go | 45 +++-- x/bank/types/tx.pb.go | 113 ++++++------ 13 files changed, 373 insertions(+), 269 deletions(-) diff --git a/api/cosmos/bank/v1beta1/tx.pulsar.go b/api/cosmos/bank/v1beta1/tx.pulsar.go index 78c894e60b8f..84f6af97cc42 100644 --- a/api/cosmos/bank/v1beta1/tx.pulsar.go +++ b/api/cosmos/bank/v1beta1/tx.pulsar.go @@ -994,6 +994,57 @@ func (x *fastReflection_MsgSendResponse) ProtoMethods() *protoiface.Methods { } } +var _ protoreflect.List = (*_MsgMultiSend_1_list)(nil) + +type _MsgMultiSend_1_list struct { + list *[]*Input +} + +func (x *_MsgMultiSend_1_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_MsgMultiSend_1_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfMessage((*x.list)[i].ProtoReflect()) +} + +func (x *_MsgMultiSend_1_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*Input) + (*x.list)[i] = concreteValue +} + +func (x *_MsgMultiSend_1_list) Append(value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*Input) + *x.list = append(*x.list, concreteValue) +} + +func (x *_MsgMultiSend_1_list) AppendMutable() protoreflect.Value { + v := new(Input) + *x.list = append(*x.list, v) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_MsgMultiSend_1_list) Truncate(n int) { + for i := n; i < len(*x.list); i++ { + (*x.list)[i] = nil + } + *x.list = (*x.list)[:n] +} + +func (x *_MsgMultiSend_1_list) NewElement() protoreflect.Value { + v := new(Input) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_MsgMultiSend_1_list) IsValid() bool { + return x.list != nil +} + var _ protoreflect.List = (*_MsgMultiSend_2_list)(nil) type _MsgMultiSend_2_list struct { @@ -1047,14 +1098,14 @@ func (x *_MsgMultiSend_2_list) IsValid() bool { var ( md_MsgMultiSend protoreflect.MessageDescriptor - fd_MsgMultiSend_input protoreflect.FieldDescriptor + fd_MsgMultiSend_inputs protoreflect.FieldDescriptor fd_MsgMultiSend_outputs protoreflect.FieldDescriptor ) func init() { file_cosmos_bank_v1beta1_tx_proto_init() md_MsgMultiSend = File_cosmos_bank_v1beta1_tx_proto.Messages().ByName("MsgMultiSend") - fd_MsgMultiSend_input = md_MsgMultiSend.Fields().ByName("input") + fd_MsgMultiSend_inputs = md_MsgMultiSend.Fields().ByName("inputs") fd_MsgMultiSend_outputs = md_MsgMultiSend.Fields().ByName("outputs") } @@ -1123,9 +1174,9 @@ func (x *fastReflection_MsgMultiSend) Interface() protoreflect.ProtoMessage { // While iterating, mutating operations may only be performed // on the current field descriptor. func (x *fastReflection_MsgMultiSend) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.Input != nil { - value := protoreflect.ValueOfMessage(x.Input.ProtoReflect()) - if !f(fd_MsgMultiSend_input, value) { + if len(x.Inputs) != 0 { + value := protoreflect.ValueOfList(&_MsgMultiSend_1_list{list: &x.Inputs}) + if !f(fd_MsgMultiSend_inputs, value) { return } } @@ -1150,8 +1201,8 @@ func (x *fastReflection_MsgMultiSend) Range(f func(protoreflect.FieldDescriptor, // a repeated field is populated if it is non-empty. func (x *fastReflection_MsgMultiSend) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { - case "cosmos.bank.v1beta1.MsgMultiSend.input": - return x.Input != nil + case "cosmos.bank.v1beta1.MsgMultiSend.inputs": + return len(x.Inputs) != 0 case "cosmos.bank.v1beta1.MsgMultiSend.outputs": return len(x.Outputs) != 0 default: @@ -1170,8 +1221,8 @@ func (x *fastReflection_MsgMultiSend) Has(fd protoreflect.FieldDescriptor) bool // Clear is a mutating operation and unsafe for concurrent use. func (x *fastReflection_MsgMultiSend) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { - case "cosmos.bank.v1beta1.MsgMultiSend.input": - x.Input = nil + case "cosmos.bank.v1beta1.MsgMultiSend.inputs": + x.Inputs = nil case "cosmos.bank.v1beta1.MsgMultiSend.outputs": x.Outputs = nil default: @@ -1190,9 +1241,12 @@ func (x *fastReflection_MsgMultiSend) Clear(fd protoreflect.FieldDescriptor) { // of the value; to obtain a mutable reference, use Mutable. func (x *fastReflection_MsgMultiSend) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { switch descriptor.FullName() { - case "cosmos.bank.v1beta1.MsgMultiSend.input": - value := x.Input - return protoreflect.ValueOfMessage(value.ProtoReflect()) + case "cosmos.bank.v1beta1.MsgMultiSend.inputs": + if len(x.Inputs) == 0 { + return protoreflect.ValueOfList(&_MsgMultiSend_1_list{}) + } + listValue := &_MsgMultiSend_1_list{list: &x.Inputs} + return protoreflect.ValueOfList(listValue) case "cosmos.bank.v1beta1.MsgMultiSend.outputs": if len(x.Outputs) == 0 { return protoreflect.ValueOfList(&_MsgMultiSend_2_list{}) @@ -1219,8 +1273,10 @@ func (x *fastReflection_MsgMultiSend) Get(descriptor protoreflect.FieldDescripto // Set is a mutating operation and unsafe for concurrent use. func (x *fastReflection_MsgMultiSend) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { - case "cosmos.bank.v1beta1.MsgMultiSend.input": - x.Input = value.Message().Interface().(*Input) + case "cosmos.bank.v1beta1.MsgMultiSend.inputs": + lv := value.List() + clv := lv.(*_MsgMultiSend_1_list) + x.Inputs = *clv.list case "cosmos.bank.v1beta1.MsgMultiSend.outputs": lv := value.List() clv := lv.(*_MsgMultiSend_2_list) @@ -1245,11 +1301,12 @@ func (x *fastReflection_MsgMultiSend) Set(fd protoreflect.FieldDescriptor, value // Mutable is a mutating operation and unsafe for concurrent use. func (x *fastReflection_MsgMultiSend) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "cosmos.bank.v1beta1.MsgMultiSend.input": - if x.Input == nil { - x.Input = new(Input) + case "cosmos.bank.v1beta1.MsgMultiSend.inputs": + if x.Inputs == nil { + x.Inputs = []*Input{} } - return protoreflect.ValueOfMessage(x.Input.ProtoReflect()) + value := &_MsgMultiSend_1_list{list: &x.Inputs} + return protoreflect.ValueOfList(value) case "cosmos.bank.v1beta1.MsgMultiSend.outputs": if x.Outputs == nil { x.Outputs = []*Output{} @@ -1269,9 +1326,9 @@ func (x *fastReflection_MsgMultiSend) Mutable(fd protoreflect.FieldDescriptor) p // For lists, maps, and messages, this returns a new, empty, mutable value. func (x *fastReflection_MsgMultiSend) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "cosmos.bank.v1beta1.MsgMultiSend.input": - m := new(Input) - return protoreflect.ValueOfMessage(m.ProtoReflect()) + case "cosmos.bank.v1beta1.MsgMultiSend.inputs": + list := []*Input{} + return protoreflect.ValueOfList(&_MsgMultiSend_1_list{list: &list}) case "cosmos.bank.v1beta1.MsgMultiSend.outputs": list := []*Output{} return protoreflect.ValueOfList(&_MsgMultiSend_2_list{list: &list}) @@ -1344,9 +1401,11 @@ func (x *fastReflection_MsgMultiSend) ProtoMethods() *protoiface.Methods { var n int var l int _ = l - if x.Input != nil { - l = options.Size(x.Input) - n += 1 + l + runtime.Sov(uint64(l)) + if len(x.Inputs) > 0 { + for _, e := range x.Inputs { + l = options.Size(e) + n += 1 + l + runtime.Sov(uint64(l)) + } } if len(x.Outputs) > 0 { for _, e := range x.Outputs { @@ -1399,19 +1458,21 @@ func (x *fastReflection_MsgMultiSend) ProtoMethods() *protoiface.Methods { dAtA[i] = 0x12 } } - if x.Input != nil { - encoded, err := options.Marshal(x.Input) - if err != nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, err + if len(x.Inputs) > 0 { + for iNdEx := len(x.Inputs) - 1; iNdEx >= 0; iNdEx-- { + encoded, err := options.Marshal(x.Inputs[iNdEx]) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0xa } - i -= len(encoded) - copy(dAtA[i:], encoded) - i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) - i-- - dAtA[i] = 0xa } if input.Buf != nil { input.Buf = append(input.Buf, dAtA...) @@ -1464,7 +1525,7 @@ func (x *fastReflection_MsgMultiSend) ProtoMethods() *protoiface.Methods { switch fieldNum { case 1: if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Input", wireType) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Inputs", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1491,10 +1552,8 @@ func (x *fastReflection_MsgMultiSend) ProtoMethods() *protoiface.Methods { if postIndex > l { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } - if x.Input == nil { - x.Input = &Input{} - } - if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Input); err != nil { + x.Inputs = append(x.Inputs, &Input{}) + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Inputs[len(x.Inputs)-1]); err != nil { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex @@ -2870,13 +2929,13 @@ func (*MsgSendResponse) Descriptor() ([]byte, []int) { return file_cosmos_bank_v1beta1_tx_proto_rawDescGZIP(), []int{1} } -// MsgMultiSend represents a single input, multi-out send message. +// MsgMultiSend represents an arbitrary multi-in, multi-out send message. type MsgMultiSend struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Input *Input `protobuf:"bytes,1,opt,name=input,proto3" json:"input,omitempty"` + Inputs []*Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` Outputs []*Output `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"` } @@ -2900,9 +2959,9 @@ func (*MsgMultiSend) Descriptor() ([]byte, []int) { return file_cosmos_bank_v1beta1_tx_proto_rawDescGZIP(), []int{2} } -func (x *MsgMultiSend) GetInput() *Input { +func (x *MsgMultiSend) GetInputs() []*Input { if x != nil { - return x.Input + return x.Inputs } return nil } @@ -3053,59 +3112,59 @@ var file_cosmos_bank_v1beta1_tx_proto_rawDesc = []byte{ 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x19, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x82, 0xe7, 0xb0, 0x2a, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x0c, 0x4d, 0x73, 0x67, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, - 0x65, 0x6e, 0x64, 0x12, 0x36, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x42, 0x04, - 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x3b, 0x0a, 0x07, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, - 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x3a, 0x0e, 0xe8, 0xa0, 0x1f, 0x00, 0x82, 0xe7, - 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x16, 0x0a, 0x14, 0x4d, 0x73, 0x67, 0x4d, - 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x94, 0x01, 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x06, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, - 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x32, 0x90, 0x02, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x4a, 0x0a, 0x04, 0x53, 0x65, - 0x6e, 0x64, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x6e, 0x64, - 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x09, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, - 0x65, 0x6e, 0x64, 0x12, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, - 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4d, 0x75, 0x6c, - 0x74, 0x69, 0x53, 0x65, 0x6e, 0x64, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x62, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, + 0x73, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x0c, 0x4d, 0x73, 0x67, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, + 0x65, 0x6e, 0x64, 0x12, 0x38, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, + 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x42, + 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x3b, 0x0a, + 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x42, 0x04, 0xc8, 0xde, 0x1f, + 0x00, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x3a, 0x0f, 0xe8, 0xa0, 0x1f, 0x00, + 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x4d, + 0x73, 0x67, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x94, 0x01, 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, + 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x04, 0xc8, 0xde, + 0x1f, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, + 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xc2, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3b, 0x62, 0x61, 0x6e, 0x6b, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, - 0x03, 0x43, 0x42, 0x58, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x42, 0x61, - 0x6e, 0x6b, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x5c, 0x42, 0x61, 0x6e, 0x6b, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x42, 0x61, 0x6e, 0x6b, 0x5c, 0x56, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x42, 0x61, 0x6e, - 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x90, 0x02, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x4a, 0x0a, + 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, + 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, + 0x65, 0x6e, 0x64, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, + 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x6e, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x09, 0x4d, 0x75, 0x6c, + 0x74, 0x69, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6e, 0x64, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x4d, 0x73, 0x67, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, + 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xc2, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x30, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x62, 0x61, 0x6e, 0x6b, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0xa2, 0x02, 0x03, 0x43, 0x42, 0x58, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x42, 0x61, 0x6e, 0x6b, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, + 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x42, 0x61, 0x6e, 0x6b, 0x5c, 0x56, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x42, 0x61, 0x6e, + 0x6b, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, + 0x42, 0x61, 0x6e, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3135,7 +3194,7 @@ var file_cosmos_bank_v1beta1_tx_proto_goTypes = []interface{}{ } var file_cosmos_bank_v1beta1_tx_proto_depIdxs = []int32{ 6, // 0: cosmos.bank.v1beta1.MsgSend.amount:type_name -> cosmos.base.v1beta1.Coin - 7, // 1: cosmos.bank.v1beta1.MsgMultiSend.input:type_name -> cosmos.bank.v1beta1.Input + 7, // 1: cosmos.bank.v1beta1.MsgMultiSend.inputs:type_name -> cosmos.bank.v1beta1.Input 8, // 2: cosmos.bank.v1beta1.MsgMultiSend.outputs:type_name -> cosmos.bank.v1beta1.Output 9, // 3: cosmos.bank.v1beta1.MsgUpdateParams.params:type_name -> cosmos.bank.v1beta1.Params 0, // 4: cosmos.bank.v1beta1.Msg.Send:input_type -> cosmos.bank.v1beta1.MsgSend diff --git a/proto/cosmos/bank/v1beta1/tx.proto b/proto/cosmos/bank/v1beta1/tx.proto index 9cd92426d953..48f8d006ff13 100644 --- a/proto/cosmos/bank/v1beta1/tx.proto +++ b/proto/cosmos/bank/v1beta1/tx.proto @@ -40,13 +40,13 @@ message MsgSend { // MsgSendResponse defines the Msg/Send response type. message MsgSendResponse {} -// MsgMultiSend represents a single input, multi-out send message. +// MsgMultiSend represents an arbitrary multi-in, multi-out send message. message MsgMultiSend { - option (cosmos.msg.v1.signer) = "input"; + option (cosmos.msg.v1.signer) = "inputs"; option (gogoproto.equal) = false; - Input input = 1 [(gogoproto.nullable) = false]; + repeated Input inputs = 1 [(gogoproto.nullable) = false]; repeated Output outputs = 2 [(gogoproto.nullable) = false]; } diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 1dcd269b7d4a..89239e94ffd0 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -46,24 +46,24 @@ var ( sendMsg1 = types.NewMsgSend(addr1, addr2, coins) multiSendMsg1 = &types.MsgMultiSend{ - Input: types.NewInput(addr1, coins), + Inputs: []types.Input{types.NewInput(addr1, coins)}, Outputs: []types.Output{types.NewOutput(addr2, coins)}, } multiSendMsg2 = &types.MsgMultiSend{ - Input: types.NewInput(addr1, coins), + Inputs: []types.Input{types.NewInput(addr1, coins)}, Outputs: []types.Output{ types.NewOutput(addr2, halfCoins), types.NewOutput(addr3, halfCoins), }, } multiSendMsg3 = &types.MsgMultiSend{ - Input: types.NewInput(addr2, coins), + Inputs: []types.Input{types.NewInput(addr2, coins)}, Outputs: []types.Output{ types.NewOutput(addr1, coins), }, } multiSendMsg4 = &types.MsgMultiSend{ - Input: types.NewInput(addr1, coins), + Inputs: []types.Input{types.NewInput(addr1, coins)}, Outputs: []types.Output{ types.NewOutput(moduleAccAddr, coins), }, diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index 156bdaf5b8b2..5deb617b8952 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -131,7 +131,7 @@ When using '--dry-run' a key name cannot be used, only a bech32 address. amount = coins.MulInt(totalAddrs) } - msg := types.NewMsgMultiSend(types.NewInput(clientCtx.FromAddress, amount), output) + msg := types.NewMsgMultiSend([]types.Input{types.NewInput(clientCtx.FromAddress, amount)}, output) return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index fd49dc2d51c9..f294ed470c3a 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -361,15 +361,14 @@ func (suite *IntegrationTestSuite) TestInputOutputNewAccount() { suite.Require().Nil(app.AccountKeeper.GetAccount(ctx, addr2)) suite.Require().Empty(app.BankKeeper.GetAllBalances(ctx, addr2)) - input := types.Input{ - Address: addr1.String(), - Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10)), + inputs := []types.Input{ + {Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))}, } outputs := []types.Output{ {Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))}, } - suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, input, outputs)) + suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) expected := sdk.NewCoins(newFooCoin(30), newBarCoin(10)) acc2Balances := app.BankKeeper.GetAllBalances(ctx, addr2) @@ -393,9 +392,8 @@ func (suite *IntegrationTestSuite) TestInputOutputCoins() { acc3 := app.AccountKeeper.NewAccountWithAddress(ctx, addr3) app.AccountKeeper.SetAccount(ctx, acc3) - input := types.Input{ - Address: addr1.String(), - Coins: sdk.NewCoins(newFooCoin(60), newBarCoin(20)), + input := []types.Input{ + {Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(60), newBarCoin(20))}, } outputs := []types.Output{ {Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))}, @@ -407,9 +405,11 @@ func (suite *IntegrationTestSuite) TestInputOutputCoins() { suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) - insufficientInput := types.Input{ - Address: addr1.String(), - Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100)), + insufficientInput := []types.Input{ + { + Address: addr1.String(), + Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100)), + }, } insufficientOutputs := []types.Output{ {Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))}, @@ -613,9 +613,10 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { coins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50), sdk.NewInt64Coin(barDenom, 100)) newCoins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)) newCoins2 := sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100)) - input := types.Input{ - Address: addr.String(), - Coins: coins, + input := []types.Input{ + {Address: addr.String(), + Coins: coins, + }, } outputs := []types.Output{ {Address: addr3.String(), Coins: newCoins}, diff --git a/x/bank/keeper/msg_server.go b/x/bank/keeper/msg_server.go index b33e3394f49b..7555dc506cb6 100644 --- a/x/bank/keeper/msg_server.go +++ b/x/bank/keeper/msg_server.go @@ -76,8 +76,10 @@ func (k msgServer) MultiSend(goCtx context.Context, msg *types.MsgMultiSend) (*t ctx := sdk.UnwrapSDKContext(goCtx) // NOTE: totalIn == totalOut should already have been checked - if err := k.IsSendEnabledCoins(ctx, msg.Input.Coins...); err != nil { - return nil, err + for _, in := range msg.Inputs { + if err := k.IsSendEnabledCoins(ctx, in.Coins...); err != nil { + return nil, err + } } for _, out := range msg.Outputs { @@ -88,7 +90,7 @@ func (k msgServer) MultiSend(goCtx context.Context, msg *types.MsgMultiSend) (*t } } - err := k.InputOutputCoins(ctx, msg.Input, msg.Outputs) + err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs) if err != nil { return nil, err } diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index 16bd31e661ec..88ff044898c2 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -18,7 +18,7 @@ import ( type SendKeeper interface { ViewKeeper - InputOutputCoins(ctx sdk.Context, input types.Input, outputs []types.Output) error + InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error GetParams(ctx sdk.Context) types.Params @@ -120,30 +120,31 @@ func (k BaseSendKeeper) SetParams(ctx sdk.Context, params types.Params) error { // InputOutputCoins performs multi-send functionality. It accepts a series of // inputs that correspond to a series of outputs. It returns an error if the // inputs and outputs don't line up or if any single transfer of tokens fails. -func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, input types.Input, outputs []types.Output) error { +func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error { // Safety check ensuring that when sending coins the keeper must maintain the // Check supply invariant and validity of Coins. - if err := types.ValidateInputsOutputs(input, outputs); err != nil { + if err := types.ValidateInputsOutputs(inputs, outputs); err != nil { return err } - inAddress, err := sdk.AccAddressFromBech32(input.Address) - if err != nil { - return err - } + for _, in := range inputs { + inAddress, err := sdk.AccAddressFromBech32(in.Address) + if err != nil { + return err + } - err = k.subUnlockedCoins(ctx, inAddress, input.Coins) - if err != nil { - return err + err = k.subUnlockedCoins(ctx, inAddress, in.Coins) + if err != nil { + return err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(types.AttributeKeySender, in.Address), + ), + ) } - ctx.EventManager().EmitEvent( - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(types.AttributeKeySender, input.Address), - ), - ) - for _, out := range outputs { outAddress, err := sdk.AccAddressFromBech32(out.Address) if err != nil { diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 76dbdd7297de..f5ab63b2bc7e 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -176,25 +176,40 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - // random number of outputs between [1, 3] + // random number of inputs/outputs between [1, 3] + inputs := make([]types.Input, r.Intn(1)+1) outputs := make([]types.Output, r.Intn(3)+1) + // collect signer privKeys + privs := make([]cryptotypes.PrivKey, len(inputs)) + + // use map to check if address already exists as input + usedAddrs := make(map[string]bool) + var totalSentCoins sdk.Coins - // generate random input fields, ignore to address - from, _, coins, skip := randomSendFields(r, ctx, accs, bk, ak) + for i := range inputs { + // generate random input fields, ignore to address + from, _, coins, skip := randomSendFields(r, ctx, accs, bk, ak) - // if coins slice is empty, we can not create valid types.MsgMultiSend - if len(coins) == 0 { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "empty coins slice"), nil, nil - } + // make sure account is fresh and not used in previous input + for usedAddrs[from.Address.String()] { + from, _, coins, skip = randomSendFields(r, ctx, accs, bk, ak) + } - if skip { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "skip all transfers"), nil, nil - } + if skip { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "skip all transfers"), nil, nil + } - // set next input and accumulate total sent coins - input := types.NewInput(from.Address, coins) - totalSentCoins = totalSentCoins.Add(coins...) + // set input address in used address map + usedAddrs[from.Address.String()] = true + + // set signer privkey + privs[i] = from.PrivKey + + // set next input and accumulate total sent coins + inputs[i] = types.NewInput(from.Address, coins) + totalSentCoins = totalSentCoins.Add(coins...) + } // Check send_enabled status of each sent coin denom if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil { @@ -231,10 +246,10 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope } msg := &types.MsgMultiSend{ - Input: input, + Inputs: inputs, Outputs: outputs, } - err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey}) + err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, privs) if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err } @@ -249,20 +264,22 @@ func SimulateMsgMultiSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keepe r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + inputs := make([]types.Input, 2) outputs := make([]types.Output, moduleAccCount) - + // collect signer privKeys + privs := make([]cryptotypes.PrivKey, len(inputs)) var totalSentCoins sdk.Coins - - sender := accs[0] - spendable := bk.SpendableCoins(ctx, sender.Address) - coins := simtypes.RandSubsetCoins(r, spendable) - input := types.NewInput(sender.Address, coins) - totalSentCoins = totalSentCoins.Add(coins...) - + for i := range inputs { + sender := accs[i] + privs[i] = sender.PrivKey + spendable := bk.SpendableCoins(ctx, sender.Address) + coins := simtypes.RandSubsetCoins(r, spendable) + inputs[i] = types.NewInput(sender.Address, coins) + totalSentCoins = totalSentCoins.Add(coins...) + } if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil { return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, err.Error()), nil, nil } - moduleAccounts := getModuleAccounts(ak, ctx, moduleAccCount) for i := range outputs { var outCoins sdk.Coins @@ -275,12 +292,9 @@ func SimulateMsgMultiSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keepe outCoins = simtypes.RandSubsetCoins(r, totalSentCoins) totalSentCoins = totalSentCoins.Sub(outCoins...) } - outputs[i] = types.NewOutput(moduleAccounts[i].Address, outCoins) } - // remove any output that has no coins - for i := 0; i < len(outputs); { if outputs[i].Coins.Empty() { outputs[i] = outputs[len(outputs)-1] @@ -290,16 +304,14 @@ func SimulateMsgMultiSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keepe i++ } } - msg := &types.MsgMultiSend{ - Input: input, + Inputs: inputs, Outputs: outputs, } - err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{sender.PrivKey}) + err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, privs) if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err } - return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -310,27 +322,29 @@ func sendMsgMultiSend( r *rand.Rand, app *baseapp.BaseApp, bk keeper.Keeper, ak types.AccountKeeper, msg *types.MsgMultiSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey, ) error { - - addr := sdk.MustAccAddressFromBech32(msg.Input.Address) - acc := ak.GetAccount(ctx, addr) - + accountNumbers := make([]uint64, len(msg.Inputs)) + sequenceNumbers := make([]uint64, len(msg.Inputs)) + for i := 0; i < len(msg.Inputs); i++ { + addr := sdk.MustAccAddressFromBech32(msg.Inputs[i].Address) + acc := ak.GetAccount(ctx, addr) + accountNumbers[i] = acc.GetAccountNumber() + sequenceNumbers[i] = acc.GetSequence() + } var ( fees sdk.Coins err error ) - + addr := sdk.MustAccAddressFromBech32(msg.Inputs[0].Address) // feePayer is the first signer, i.e. first input address feePayer := ak.GetAccount(ctx, addr) spendable := bk.SpendableCoins(ctx, feePayer.GetAddress()) - - coins, hasNeg := spendable.SafeSub(msg.Input.Coins...) + coins, hasNeg := spendable.SafeSub(msg.Inputs[0].Coins...) if !hasNeg { fees, err = simtypes.RandomFees(r, ctx, coins) if err != nil { return err } } - txGen := simappparams.MakeTestEncodingConfig().TxConfig tx, err := simtestutil.GenSignedMockTx( r, @@ -339,19 +353,17 @@ func sendMsgMultiSend( fees, simtestutil.DefaultGenTxGas, chainID, - []uint64{acc.GetAccountNumber()}, - []uint64{acc.GetSequence()}, + accountNumbers, + sequenceNumbers, privkeys..., ) if err != nil { return err } - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) if err != nil { return err } - return nil } diff --git a/x/bank/simulation/operations_test.go b/x/bank/simulation/operations_test.go index a75f2563c809..6a0b8c34ac67 100644 --- a/x/bank/simulation/operations_test.go +++ b/x/bank/simulation/operations_test.go @@ -114,11 +114,12 @@ func (suite *SimTestSuite) TestSimulateMsgMultiSend() { types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) require.True(operationMsg.OK) - require.Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.Input.Address) - require.Equal("4896096stake", msg.Input.Coins.String()) - require.Len(msg.Outputs, 3) + require.Len(msg.Inputs, 1) + require.Equal("cosmos1tnh2q55v8wyygtt9srz5safamzdengsnqeycj3", msg.Inputs[0].Address) + require.Equal("114949958stake", msg.Inputs[0].Coins.String()) + require.Len(msg.Outputs, 2) require.Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Outputs[1].Address) - require.Equal("891479stake", msg.Outputs[1].Coins.String()) + require.Equal("107287087stake", msg.Outputs[1].Coins.String()) require.Equal(types.TypeMsgMultiSend, msg.Type()) require.Equal(types.ModuleName, msg.Route()) require.Len(futureOperations, 0) diff --git a/x/bank/types/errors.go b/x/bank/types/errors.go index 00851d165f80..3fca352de3f4 100644 --- a/x/bank/types/errors.go +++ b/x/bank/types/errors.go @@ -6,9 +6,11 @@ import ( // x/bank module sentinel errors var ( + ErrNoInputs = sdkerrors.Register(ModuleName, 2, "no inputs to send transaction") ErrNoOutputs = sdkerrors.Register(ModuleName, 3, "no outputs to send transaction") ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 4, "sum inputs != sum outputs") ErrSendDisabled = sdkerrors.Register(ModuleName, 5, "send transactions are disabled") ErrDenomMetadataNotFound = sdkerrors.Register(ModuleName, 6, "client denom metadata not found") ErrInvalidKey = sdkerrors.Register(ModuleName, 7, "invalid key") + ErrMultipleSenders = sdkerrors.Register(ModuleName, 8, "multiple senders not allowed") ) diff --git a/x/bank/types/msgs.go b/x/bank/types/msgs.go index dedcf151392f..881126f9cbf7 100644 --- a/x/bank/types/msgs.go +++ b/x/bank/types/msgs.go @@ -64,8 +64,8 @@ func (msg MsgSend) GetSigners() []sdk.AccAddress { } // NewMsgMultiSend - construct arbitrary multi-in, multi-out send msg. -func NewMsgMultiSend(in Input, out []Output) *MsgMultiSend { - return &MsgMultiSend{Input: in, Outputs: out} +func NewMsgMultiSend(in []Input, out []Output) *MsgMultiSend { + return &MsgMultiSend{Inputs: in, Outputs: out} } // Route Implements Msg @@ -79,15 +79,19 @@ func (msg MsgMultiSend) ValidateBasic() error { // this just makes sure the input and all the outputs are properly formatted, // not that they actually have the money inside - if err := msg.Input.ValidateBasic(); err != nil { - return err + if len(msg.Inputs) == 0 { + return ErrNoInputs + } + + if len(msg.Inputs) != 1 { + return ErrMultipleSenders } if len(msg.Outputs) == 0 { return ErrNoOutputs } - return ValidateInputsOutputs(msg.Input, msg.Outputs) + return ValidateInputsOutputs(msg.Inputs, msg.Outputs) } // GetSignBytes Implements Msg. @@ -97,8 +101,13 @@ func (msg MsgMultiSend) GetSignBytes() []byte { // GetSigners Implements Msg. func (msg MsgMultiSend) GetSigners() []sdk.AccAddress { - addrs, _ := sdk.AccAddressFromBech32(msg.Input.Address) - return []sdk.AccAddress{addrs} + addrs := make([]sdk.AccAddress, len(msg.Inputs)) + for i, in := range msg.Inputs { + inAddr, _ := sdk.AccAddressFromBech32(in.Address) + addrs[i] = inAddr + } + + return addrs } // ValidateBasic - validate transaction input @@ -155,15 +164,16 @@ func NewOutput(addr sdk.AccAddress, coins sdk.Coins) Output { // ValidateInputsOutputs validates that each respective input and output is // valid and that the sum of inputs is equal to the sum of outputs. -func ValidateInputsOutputs(input Input, outputs []Output) error { +func ValidateInputsOutputs(inputs []Input, outputs []Output) error { var totalIn, totalOut sdk.Coins - if err := input.ValidateBasic(); err != nil { - return err + for _, in := range inputs { + if err := in.ValidateBasic(); err != nil { + return err + } + totalIn = totalIn.Add(in.Coins...) } - totalIn = totalIn.Add(input.Coins...) - for _, out := range outputs { if err := out.ValidateBasic(); err != nil { return err diff --git a/x/bank/types/msgs_test.go b/x/bank/types/msgs_test.go index 27054fc06cb8..d9ce4e60345d 100644 --- a/x/bank/types/msgs_test.go +++ b/x/bank/types/msgs_test.go @@ -70,7 +70,7 @@ func TestMsgMultiSendRoute(t *testing.T) { addr2 := sdk.AccAddress([]byte("output")) coins := sdk.NewCoins(sdk.NewInt64Coin("atom", 10)) msg := MsgMultiSend{ - Input: NewInput(addr1, coins), + Inputs: []Input{NewInput(addr1, coins)}, Outputs: []Output{NewOutput(addr2, coins)}, } @@ -183,13 +183,13 @@ func TestMsgMultiSendValidation(t *testing.T) { tx MsgMultiSend expErrMsg string }{ - {false, MsgMultiSend{}, "invalid input address"}, // no input or output - {false, MsgMultiSend{Input: input1}, "no outputs to send transaction"}, // just input - {false, MsgMultiSend{Outputs: []Output{output1}}, "invalid input address"}, // just output + {false, MsgMultiSend{}, "no inputs to send transaction"}, // no input or output + {false, MsgMultiSend{Inputs: []Input{input1}}, "no outputs to send transaction"}, // just input + {false, MsgMultiSend{Outputs: []Output{output1}}, "no inputs to send transaction"}, // just output { false, MsgMultiSend{ - Input: NewInput(emptyAddr, atom123), // invalid input + Inputs: []Input{NewInput(emptyAddr, atom123)}, // invalid input Outputs: []Output{output1}, }, "invalid input address", @@ -197,7 +197,7 @@ func TestMsgMultiSendValidation(t *testing.T) { { false, MsgMultiSend{ - Input: input1, + Inputs: []Input{input1}, Outputs: []Output{{emptyAddr.String(), atom123}}, // invalid output }, "invalid output address", @@ -205,7 +205,7 @@ func TestMsgMultiSendValidation(t *testing.T) { { false, MsgMultiSend{ - Input: input1, + Inputs: []Input{input1}, Outputs: []Output{output2}, // amounts don't match }, "sum inputs != sum outputs", @@ -213,23 +213,23 @@ func TestMsgMultiSendValidation(t *testing.T) { { true, MsgMultiSend{ - Input: input1, + Inputs: []Input{input1}, Outputs: []Output{output1}, }, "", }, { - true, + false, MsgMultiSend{ - Input: input2, + Inputs: []Input{input1, input2}, Outputs: []Output{output3, output4}, }, - "", + "multiple senders not allowed", }, { true, MsgMultiSend{ - Input: NewInput(addr2, atom123.MulInt(sdk.NewInt(2))), + Inputs: []Input{NewInput(addr2, atom123.MulInt(sdk.NewInt(2)))}, Outputs: []Output{output1, output1}, }, "", @@ -253,22 +253,29 @@ func TestMsgMultiSendGetSignBytes(t *testing.T) { addr2 := sdk.AccAddress([]byte("output")) coins := sdk.NewCoins(sdk.NewInt64Coin("atom", 10)) msg := MsgMultiSend{ - Input: NewInput(addr1, coins), + Inputs: []Input{NewInput(addr1, coins)}, Outputs: []Output{NewOutput(addr2, coins)}, } res := msg.GetSignBytes() - expected := `{"type":"cosmos-sdk/MsgMultiSend","value":{"input":{"address":"cosmos1d9h8qat57ljhcm","coins":[{"amount":"10","denom":"atom"}]},"outputs":[{"address":"cosmos1da6hgur4wsmpnjyg","coins":[{"amount":"10","denom":"atom"}]}]}}` + expected := `{"type":"cosmos-sdk/MsgMultiSend","value":{"inputs":[{"address":"cosmos1d9h8qat57ljhcm","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmos1da6hgur4wsmpnjyg","coins":[{"amount":"10","denom":"atom"}]}]}}` require.Equal(t, expected, string(res)) } func TestMsgMultiSendGetSigners(t *testing.T) { - addr := sdk.AccAddress([]byte("input111111111111111")) - input := NewInput(addr, nil) - msg := NewMsgMultiSend(input, nil) + addrs := make([]string, 3) + inputs := make([]Input, 3) + for i, v := range []string{"input111111111111111", "input222222222222222", "input333333333333333"} { + addr := sdk.AccAddress([]byte(v)) + inputs[i] = NewInput(addr, nil) + addrs[i] = addr.String() + } + msg := NewMsgMultiSend(inputs, nil) + res := msg.GetSigners() - require.Equal(t, 1, len(res)) - require.True(t, addr.Equals(res[0])) + for i, signer := range res { + require.Equal(t, signer.String(), addrs[i]) + } } func TestMsgSendGetSigners(t *testing.T) { diff --git a/x/bank/types/tx.pb.go b/x/bank/types/tx.pb.go index dc9b81020149..80547ca924ba 100644 --- a/x/bank/types/tx.pb.go +++ b/x/bank/types/tx.pb.go @@ -109,9 +109,9 @@ func (m *MsgSendResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgSendResponse proto.InternalMessageInfo -// MsgMultiSend represents a single input, multi-out send message. +// MsgMultiSend represents an arbitrary multi-in, multi-out send message. type MsgMultiSend struct { - Input Input `protobuf:"bytes,1,opt,name=input,proto3" json:"input"` + Inputs []Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs"` Outputs []Output `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs"` } @@ -148,11 +148,11 @@ func (m *MsgMultiSend) XXX_DiscardUnknown() { var xxx_messageInfo_MsgMultiSend proto.InternalMessageInfo -func (m *MsgMultiSend) GetInput() Input { +func (m *MsgMultiSend) GetInputs() []Input { if m != nil { - return m.Input + return m.Inputs } - return Input{} + return nil } func (m *MsgMultiSend) GetOutputs() []Output { @@ -310,41 +310,41 @@ func init() { func init() { proto.RegisterFile("cosmos/bank/v1beta1/tx.proto", fileDescriptor_1d8cb1613481f5b7) } var fileDescriptor_1d8cb1613481f5b7 = []byte{ - // 538 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xbd, 0x6e, 0xd3, 0x50, - 0x14, 0xb6, 0x9b, 0x92, 0x2a, 0x27, 0x51, 0x11, 0x26, 0xa2, 0x89, 0xa9, 0x9c, 0x62, 0x31, 0xa4, - 0x88, 0xda, 0x24, 0x48, 0x45, 0xa4, 0x13, 0xe9, 0x04, 0x52, 0x04, 0x4a, 0xc5, 0x00, 0x4b, 0x65, - 0xc7, 0x17, 0xd7, 0x2a, 0xf6, 0xb5, 0x7c, 0xaf, 0xab, 0x76, 0x65, 0x62, 0xac, 0x04, 0x0f, 0xd0, - 0x99, 0x89, 0x81, 0x87, 0xe8, 0x58, 0x31, 0x31, 0x01, 0x4a, 0x06, 0x78, 0x0b, 0xd0, 0xfd, 0xb1, - 0x93, 0x42, 0x7e, 0x3a, 0x39, 0xca, 0xf7, 0x73, 0xbe, 0xf3, 0x1d, 0x27, 0xb0, 0x3e, 0xc0, 0x24, - 0xc4, 0xc4, 0x76, 0x9d, 0xe8, 0xd0, 0x3e, 0x6a, 0xb9, 0x88, 0x3a, 0x2d, 0x9b, 0x1e, 0x5b, 0x71, - 0x82, 0x29, 0xd6, 0x6e, 0x0a, 0xd4, 0x62, 0xa8, 0x25, 0x51, 0xbd, 0xea, 0x63, 0x1f, 0x73, 0xdc, - 0x66, 0x9f, 0x04, 0x55, 0x37, 0x72, 0x23, 0x82, 0x72, 0xa3, 0x01, 0x0e, 0xa2, 0xff, 0xf0, 0x89, - 0x41, 0xdc, 0x57, 0xe0, 0x75, 0x81, 0xef, 0x0b, 0x63, 0x39, 0x57, 0x40, 0x6b, 0x52, 0x1a, 0x12, - 0xdf, 0x3e, 0x6a, 0xb1, 0x87, 0x00, 0xcc, 0x3f, 0x2a, 0xac, 0xf4, 0x88, 0xbf, 0x87, 0x22, 0x4f, - 0xdb, 0x81, 0xca, 0x9b, 0x04, 0x87, 0xfb, 0x8e, 0xe7, 0x25, 0x88, 0x90, 0x9a, 0xba, 0xa1, 0x36, - 0x4b, 0xdd, 0xda, 0xd7, 0x2f, 0x5b, 0x55, 0x69, 0xf6, 0x44, 0x20, 0x7b, 0x34, 0x09, 0x22, 0xbf, - 0x5f, 0x66, 0x6c, 0xf9, 0x95, 0xf6, 0x08, 0x80, 0xe2, 0x5c, 0xba, 0xb4, 0x40, 0x5a, 0xa2, 0x38, - 0x13, 0x0e, 0xa0, 0xe8, 0x84, 0x38, 0x8d, 0x68, 0xad, 0xb0, 0x51, 0x68, 0x96, 0xdb, 0x75, 0x2b, - 0x6f, 0x8c, 0xa0, 0xac, 0x31, 0x6b, 0x17, 0x07, 0x51, 0xf7, 0xc1, 0xf9, 0xf7, 0x86, 0xf2, 0xe9, - 0x47, 0xa3, 0xe9, 0x07, 0xf4, 0x20, 0x75, 0xad, 0x01, 0x0e, 0xe5, 0x9a, 0xf2, 0xb1, 0x45, 0xbc, - 0x43, 0x9b, 0x9e, 0xc4, 0x88, 0x70, 0x01, 0xe9, 0x4b, 0xeb, 0x4e, 0xfd, 0xfd, 0x59, 0x43, 0xf9, - 0x7d, 0xd6, 0x50, 0xde, 0xfd, 0xfa, 0x7c, 0xef, 0xd2, 0x96, 0xe6, 0x0d, 0xb8, 0x2e, 0x0b, 0xe8, - 0x23, 0x12, 0xe3, 0x88, 0x20, 0xf3, 0x83, 0x0a, 0x95, 0x1e, 0xf1, 0x7b, 0xe9, 0x5b, 0x1a, 0xf0, - 0x66, 0xb6, 0xe1, 0x5a, 0x10, 0xc5, 0x29, 0xe5, 0x95, 0x94, 0xdb, 0xba, 0x35, 0xe5, 0xa8, 0xd6, - 0x53, 0xc6, 0xe8, 0x2e, 0xb3, 0x8c, 0x7d, 0x41, 0xd7, 0x76, 0x60, 0x05, 0xa7, 0x34, 0x4e, 0x29, - 0x6b, 0x84, 0x2d, 0x77, 0x7b, 0xaa, 0xf2, 0x39, 0xe7, 0x48, 0x69, 0xa6, 0xe8, 0xac, 0x66, 0x79, - 0x85, 0x99, 0x79, 0x0b, 0xaa, 0x93, 0xa1, 0xf2, 0xb4, 0x1f, 0x55, 0xbe, 0xc1, 0xcb, 0xd8, 0x73, - 0x28, 0x7a, 0xe1, 0x24, 0x4e, 0x48, 0xb4, 0x6d, 0x28, 0x39, 0x29, 0x3d, 0xc0, 0x49, 0x40, 0x4f, - 0x16, 0xde, 0x71, 0x4c, 0xd5, 0x1e, 0x43, 0x31, 0xe6, 0x0e, 0xfc, 0x82, 0xb3, 0xf2, 0x8a, 0x21, - 0x32, 0xaf, 0x14, 0x74, 0x56, 0x59, 0xd4, 0xb1, 0x95, 0x59, 0x87, 0xb5, 0x7f, 0x52, 0x65, 0x89, - 0xdb, 0xa7, 0x4b, 0x50, 0xe8, 0x11, 0x5f, 0x7b, 0x06, 0xcb, 0xbc, 0xde, 0xf5, 0xa9, 0x53, 0xe4, - 0x55, 0xf4, 0xbb, 0xf3, 0xd0, 0xcc, 0x53, 0x7b, 0x05, 0xa5, 0xf1, 0xbd, 0xee, 0xcc, 0x92, 0xe4, - 0x14, 0x7d, 0x73, 0x21, 0x25, 0xb7, 0x76, 0xa1, 0x72, 0xa9, 0xdc, 0x99, 0x81, 0x26, 0x59, 0xfa, - 0xfd, 0xab, 0xb0, 0xb2, 0x19, 0xdd, 0xdd, 0xf3, 0xa1, 0xa1, 0x5e, 0x0c, 0x0d, 0xf5, 0xe7, 0xd0, - 0x50, 0x4f, 0x47, 0x86, 0x72, 0x31, 0x32, 0x94, 0x6f, 0x23, 0x43, 0x79, 0xbd, 0x39, 0xf7, 0x65, - 0x3f, 0x16, 0xff, 0x06, 0xfc, 0x9d, 0x77, 0x8b, 0xfc, 0x37, 0xfd, 0xf0, 0x6f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x8a, 0x36, 0x66, 0x7a, 0x92, 0x04, 0x00, 0x00, + // 535 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x3b, 0x6f, 0xd3, 0x50, + 0x14, 0xb6, 0x93, 0x2a, 0x55, 0x4e, 0x23, 0x2a, 0x4c, 0x44, 0x13, 0x53, 0x39, 0xc5, 0x62, 0x48, + 0x11, 0xb5, 0x49, 0x91, 0x78, 0xa4, 0x13, 0xe9, 0x04, 0x52, 0x04, 0x4a, 0xc5, 0x00, 0x4b, 0xe5, + 0xc7, 0xc5, 0xb5, 0x8a, 0x7d, 0x2d, 0xdf, 0xeb, 0xaa, 0x5d, 0x99, 0x18, 0x3b, 0x20, 0xe6, 0xce, + 0x4c, 0x0c, 0xfc, 0x88, 0x8e, 0x15, 0x13, 0x13, 0xa0, 0x64, 0x80, 0x7f, 0x01, 0xba, 0x0f, 0x3b, + 0x29, 0xe4, 0xc1, 0x74, 0x2d, 0x7f, 0x8f, 0xf3, 0x9d, 0x73, 0xae, 0x0d, 0xeb, 0x1e, 0x26, 0x11, + 0x26, 0xb6, 0xeb, 0xc4, 0x87, 0xf6, 0x51, 0xc7, 0x45, 0xd4, 0xe9, 0xd8, 0xf4, 0xd8, 0x4a, 0x52, + 0x4c, 0xb1, 0x76, 0x4d, 0xa0, 0x16, 0x43, 0x2d, 0x89, 0xea, 0xf5, 0x00, 0x07, 0x98, 0xe3, 0x36, + 0x7b, 0x12, 0x54, 0xdd, 0x28, 0x8c, 0x08, 0x2a, 0x8c, 0x3c, 0x1c, 0xc6, 0xff, 0xe0, 0x13, 0x85, + 0xb8, 0xaf, 0xc0, 0x9b, 0x02, 0xdf, 0x17, 0xc6, 0xb2, 0xae, 0x80, 0xd6, 0xa4, 0x34, 0x22, 0x81, + 0x7d, 0xd4, 0x61, 0x87, 0x00, 0xcc, 0xdf, 0x2a, 0x2c, 0xf7, 0x49, 0xb0, 0x87, 0x62, 0x5f, 0xdb, + 0x81, 0xda, 0xeb, 0x14, 0x47, 0xfb, 0x8e, 0xef, 0xa7, 0x88, 0x90, 0x86, 0xba, 0xa1, 0xb6, 0xab, + 0xbd, 0xc6, 0x97, 0xcf, 0x5b, 0x75, 0x69, 0xf6, 0x58, 0x20, 0x7b, 0x34, 0x0d, 0xe3, 0x60, 0xb0, + 0xc2, 0xd8, 0xf2, 0x95, 0xf6, 0x00, 0x80, 0xe2, 0x42, 0x5a, 0x5a, 0x20, 0xad, 0x52, 0x9c, 0x0b, + 0x3d, 0xa8, 0x38, 0x11, 0xce, 0x62, 0xda, 0x28, 0x6f, 0x94, 0xdb, 0x2b, 0xdb, 0x4d, 0xab, 0x98, + 0x18, 0x41, 0xf9, 0xc4, 0xac, 0x5d, 0x1c, 0xc6, 0xbd, 0xbb, 0xe7, 0xdf, 0x5a, 0xca, 0xc7, 0xef, + 0xad, 0x76, 0x10, 0xd2, 0x83, 0xcc, 0xb5, 0x3c, 0x1c, 0xc9, 0x36, 0xe5, 0xb1, 0x45, 0xfc, 0x43, + 0x9b, 0x9e, 0x24, 0x88, 0x70, 0x01, 0x19, 0x48, 0xeb, 0x6e, 0xf3, 0xdd, 0x59, 0x4b, 0xf9, 0x75, + 0xd6, 0x52, 0xde, 0xfe, 0xfc, 0x74, 0xfb, 0x52, 0x97, 0xe6, 0x55, 0x58, 0x95, 0x03, 0x18, 0x20, + 0x92, 0xe0, 0x98, 0x20, 0xf3, 0x83, 0x0a, 0xb5, 0x3e, 0x09, 0xfa, 0xd9, 0x1b, 0x1a, 0xf2, 0xc9, + 0x3c, 0x84, 0x4a, 0x18, 0x27, 0x19, 0x65, 0x33, 0x61, 0x19, 0x75, 0x6b, 0xca, 0x56, 0xad, 0x27, + 0x8c, 0xd2, 0x5b, 0x62, 0x21, 0x07, 0x92, 0xaf, 0xed, 0xc0, 0x32, 0xce, 0x28, 0x97, 0x96, 0xb8, + 0xf4, 0xc6, 0x54, 0xe9, 0x33, 0xce, 0x91, 0xda, 0x5c, 0xd1, 0x5d, 0xcd, 0x13, 0x4b, 0x37, 0xf3, + 0x3a, 0xd4, 0x27, 0x73, 0x15, 0x81, 0xdf, 0xab, 0xbc, 0x89, 0x17, 0x89, 0xef, 0x50, 0xf4, 0xdc, + 0x49, 0x9d, 0x88, 0x68, 0xf7, 0xa1, 0xea, 0x64, 0xf4, 0x00, 0xa7, 0x21, 0x3d, 0x59, 0xb8, 0xca, + 0x31, 0x55, 0x7b, 0x04, 0x95, 0x84, 0x3b, 0xf0, 0x25, 0xce, 0x0a, 0x2c, 0x8a, 0xe4, 0xcd, 0x0a, + 0x41, 0xf7, 0x0a, 0xcb, 0x3a, 0xb6, 0x32, 0x9b, 0xb0, 0xf6, 0x57, 0xaa, 0x3c, 0xf1, 0xf6, 0x69, + 0x09, 0xca, 0x7d, 0x12, 0x68, 0x4f, 0x61, 0x89, 0x4f, 0x78, 0x7d, 0x6a, 0x15, 0xb9, 0x18, 0xfd, + 0xd6, 0x3c, 0x34, 0xf7, 0xd4, 0x5e, 0x42, 0x75, 0xbc, 0xb2, 0x9b, 0xb3, 0x24, 0x05, 0x45, 0xdf, + 0x5c, 0x48, 0x29, 0xac, 0x5d, 0xa8, 0x5d, 0x1a, 0xee, 0xcc, 0x40, 0x93, 0x2c, 0xfd, 0xce, 0xff, + 0xb0, 0xf2, 0x1a, 0xbd, 0xdd, 0xf3, 0xa1, 0xa1, 0x5e, 0x0c, 0x0d, 0xf5, 0xc7, 0xd0, 0x50, 0x4f, + 0x47, 0x86, 0x72, 0x31, 0x32, 0x94, 0xaf, 0x23, 0x43, 0x79, 0xb5, 0x39, 0xf7, 0xbe, 0x1f, 0x8b, + 0x1f, 0x02, 0xbf, 0xf6, 0x6e, 0x85, 0x7f, 0xd6, 0xf7, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x7c, + 0xb9, 0xe1, 0x24, 0x95, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -619,16 +619,20 @@ func (m *MsgMultiSend) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x12 } } - { - size, err := m.Input.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if len(m.Inputs) > 0 { + for iNdEx := len(m.Inputs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Inputs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -767,8 +771,12 @@ func (m *MsgMultiSend) Size() (n int) { } var l int _ = l - l = m.Input.Size() - n += 1 + l + sovTx(uint64(l)) + if len(m.Inputs) > 0 { + for _, e := range m.Inputs { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } if len(m.Outputs) > 0 { for _, e := range m.Outputs { l = e.Size() @@ -1046,7 +1054,7 @@ func (m *MsgMultiSend) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Input", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Inputs", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1073,7 +1081,8 @@ func (m *MsgMultiSend) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Input.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Inputs = append(m.Inputs, Input{}) + if err := m.Inputs[len(m.Inputs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex From 760e5322586153b0255a08780fc16d8e9ab938b8 Mon Sep 17 00:00:00 2001 From: likhita-809 Date: Thu, 21 Jul 2022 22:00:59 +0530 Subject: [PATCH 2/2] address review comments --- api/cosmos/bank/v1beta1/tx.pulsar.go | 2 ++ proto/cosmos/bank/v1beta1/tx.proto | 2 ++ x/bank/app_test.go | 13 +++++++++++++ x/bank/types/tx.pb.go | 2 ++ 4 files changed, 19 insertions(+) diff --git a/api/cosmos/bank/v1beta1/tx.pulsar.go b/api/cosmos/bank/v1beta1/tx.pulsar.go index 84f6af97cc42..246fbd81df0d 100644 --- a/api/cosmos/bank/v1beta1/tx.pulsar.go +++ b/api/cosmos/bank/v1beta1/tx.pulsar.go @@ -2935,6 +2935,8 @@ type MsgMultiSend struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Inputs, despite being `repeated`, only allows one sender input. This is + // checked in MsgMultiSend's ValidateBasic. Inputs []*Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` Outputs []*Output `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"` } diff --git a/proto/cosmos/bank/v1beta1/tx.proto b/proto/cosmos/bank/v1beta1/tx.proto index 48f8d006ff13..a67e76d27098 100644 --- a/proto/cosmos/bank/v1beta1/tx.proto +++ b/proto/cosmos/bank/v1beta1/tx.proto @@ -46,6 +46,8 @@ message MsgMultiSend { option (gogoproto.equal) = false; + // Inputs, despite being `repeated`, only allows one sender input. This is + // checked in MsgMultiSend's ValidateBasic. repeated Input inputs = 1 [(gogoproto.nullable) = false]; repeated Output outputs = 2 [(gogoproto.nullable) = false]; } diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 89239e94ffd0..ef5621d34641 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -68,6 +68,10 @@ var ( types.NewOutput(moduleAccAddr, coins), }, } + invalidMultiSendMsg = &types.MsgMultiSend{ + Inputs: []types.Input{types.NewInput(addr1, coins), types.NewInput(addr2, coins)}, + Outputs: []types.Output{}, + } ) func TestSendNotEnoughBalance(t *testing.T) { @@ -154,6 +158,15 @@ func TestMsgMultiSendWithAccounts(t *testing.T) { expPass: false, privKeys: []cryptotypes.PrivKey{priv1}, }, + { + desc: "multiple inputs not allowed", + msgs: []sdk.Msg{invalidMultiSendMsg}, + accNums: []uint64{0}, + accSeqs: []uint64{0}, + expSimPass: false, + expPass: false, + privKeys: []cryptotypes.PrivKey{priv1}, + }, } for _, tc := range testCases { diff --git a/x/bank/types/tx.pb.go b/x/bank/types/tx.pb.go index 80547ca924ba..a0baa198170d 100644 --- a/x/bank/types/tx.pb.go +++ b/x/bank/types/tx.pb.go @@ -111,6 +111,8 @@ var xxx_messageInfo_MsgSendResponse proto.InternalMessageInfo // MsgMultiSend represents an arbitrary multi-in, multi-out send message. type MsgMultiSend struct { + // Inputs, despite being `repeated`, only allows one sender input. This is + // checked in MsgMultiSend's ValidateBasic. Inputs []Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs"` Outputs []Output `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs"` }