Merge commit from fork

* Fix ABS061

(cherry picked from commit f6f56395fd4b919063e19aa94e7178793ac0fd6b)
(cherry picked from commit 34b30b0ed6b3145b94719650eb3246a91ed977ce)

* Review feedback

(cherry picked from commit c892055e7fa86db8382fb2af17bb66342d7e2eeb)

* Check for events

(cherry picked from commit 16fc26041457b01077df4d3d3d25c9eaf00780d2)

* Review feedback

* Remove unecessary code comments

* Update changelog

* Remove duplicate headline after merge
This commit is contained in:
Alexander Peters 2025-03-12 15:51:25 +01:00 committed by GitHub
parent b3cad5938d
commit 2f09f3af69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1077 additions and 61 deletions

View File

@ -50,8 +50,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (gRPC) [#23844](https://github.com/cosmos/cosmos-sdk/pull/23844) Add debug log prints for each gRPC request.
### Bug Fixes
* (x/group) [GHSA-47ww-ff84-4jrg](https://github.com/cosmos/cosmos-sdk/security/advisories/GHSA-47ww-ff84-4jrg) Fix x/group can halt when erroring in EndBlocker
* (x/distribution) [#23934](https://github.com/cosmos/cosmos-sdk/pull/23934) Fix vulnerability in `incrementReferenceCount` in distribution.
* (baseapp) [#23879](https://github.com/cosmos/cosmos-sdk/pull/23879) Ensure finalize block response is not empty in the defer check of FinalizeBlock to avoid panic by nil pointer.
* (query) [#23883](https://github.com/cosmos/cosmos-sdk/pull/23883) Fix NPE in query pagination.

View File

@ -4388,6 +4388,474 @@ func (x *fastReflection_EventProposalPruned) ProtoMethods() *protoiface.Methods
}
}
var (
md_EventTallyError protoreflect.MessageDescriptor
fd_EventTallyError_proposal_id protoreflect.FieldDescriptor
fd_EventTallyError_error_message protoreflect.FieldDescriptor
)
func init() {
file_cosmos_group_v1_events_proto_init()
md_EventTallyError = File_cosmos_group_v1_events_proto.Messages().ByName("EventTallyError")
fd_EventTallyError_proposal_id = md_EventTallyError.Fields().ByName("proposal_id")
fd_EventTallyError_error_message = md_EventTallyError.Fields().ByName("error_message")
}
var _ protoreflect.Message = (*fastReflection_EventTallyError)(nil)
type fastReflection_EventTallyError EventTallyError
func (x *EventTallyError) ProtoReflect() protoreflect.Message {
return (*fastReflection_EventTallyError)(x)
}
func (x *EventTallyError) slowProtoReflect() protoreflect.Message {
mi := &file_cosmos_group_v1_events_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
var _fastReflection_EventTallyError_messageType fastReflection_EventTallyError_messageType
var _ protoreflect.MessageType = fastReflection_EventTallyError_messageType{}
type fastReflection_EventTallyError_messageType struct{}
func (x fastReflection_EventTallyError_messageType) Zero() protoreflect.Message {
return (*fastReflection_EventTallyError)(nil)
}
func (x fastReflection_EventTallyError_messageType) New() protoreflect.Message {
return new(fastReflection_EventTallyError)
}
func (x fastReflection_EventTallyError_messageType) Descriptor() protoreflect.MessageDescriptor {
return md_EventTallyError
}
// Descriptor returns message descriptor, which contains only the protobuf
// type information for the message.
func (x *fastReflection_EventTallyError) Descriptor() protoreflect.MessageDescriptor {
return md_EventTallyError
}
// Type returns the message type, which encapsulates both Go and protobuf
// type information. If the Go type information is not needed,
// it is recommended that the message descriptor be used instead.
func (x *fastReflection_EventTallyError) Type() protoreflect.MessageType {
return _fastReflection_EventTallyError_messageType
}
// New returns a newly allocated and mutable empty message.
func (x *fastReflection_EventTallyError) New() protoreflect.Message {
return new(fastReflection_EventTallyError)
}
// Interface unwraps the message reflection interface and
// returns the underlying ProtoMessage interface.
func (x *fastReflection_EventTallyError) Interface() protoreflect.ProtoMessage {
return (*EventTallyError)(x)
}
// Range iterates over every populated field in an undefined order,
// calling f for each field descriptor and value encountered.
// Range returns immediately if f returns false.
// While iterating, mutating operations may only be performed
// on the current field descriptor.
func (x *fastReflection_EventTallyError) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
if x.ProposalId != uint64(0) {
value := protoreflect.ValueOfUint64(x.ProposalId)
if !f(fd_EventTallyError_proposal_id, value) {
return
}
}
if x.ErrorMessage != "" {
value := protoreflect.ValueOfString(x.ErrorMessage)
if !f(fd_EventTallyError_error_message, value) {
return
}
}
}
// Has reports whether a field is populated.
//
// Some fields have the property of nullability where it is possible to
// distinguish between the default value of a field and whether the field
// was explicitly populated with the default value. Singular message fields,
// member fields of a oneof, and proto2 scalar fields are nullable. Such
// fields are populated only if explicitly set.
//
// In other cases (aside from the nullable cases above),
// a proto3 scalar field is populated if it contains a non-zero value, and
// a repeated field is populated if it is non-empty.
func (x *fastReflection_EventTallyError) Has(fd protoreflect.FieldDescriptor) bool {
switch fd.FullName() {
case "cosmos.group.v1.EventTallyError.proposal_id":
return x.ProposalId != uint64(0)
case "cosmos.group.v1.EventTallyError.error_message":
return x.ErrorMessage != ""
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.group.v1.EventTallyError"))
}
panic(fmt.Errorf("message cosmos.group.v1.EventTallyError does not contain field %s", fd.FullName()))
}
}
// Clear clears the field such that a subsequent Has call reports false.
//
// Clearing an extension field clears both the extension type and value
// associated with the given field number.
//
// Clear is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_EventTallyError) Clear(fd protoreflect.FieldDescriptor) {
switch fd.FullName() {
case "cosmos.group.v1.EventTallyError.proposal_id":
x.ProposalId = uint64(0)
case "cosmos.group.v1.EventTallyError.error_message":
x.ErrorMessage = ""
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.group.v1.EventTallyError"))
}
panic(fmt.Errorf("message cosmos.group.v1.EventTallyError does not contain field %s", fd.FullName()))
}
}
// Get retrieves the value for a field.
//
// For unpopulated scalars, it returns the default value, where
// the default value of a bytes scalar is guaranteed to be a copy.
// For unpopulated composite types, it returns an empty, read-only view
// of the value; to obtain a mutable reference, use Mutable.
func (x *fastReflection_EventTallyError) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value {
switch descriptor.FullName() {
case "cosmos.group.v1.EventTallyError.proposal_id":
value := x.ProposalId
return protoreflect.ValueOfUint64(value)
case "cosmos.group.v1.EventTallyError.error_message":
value := x.ErrorMessage
return protoreflect.ValueOfString(value)
default:
if descriptor.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.group.v1.EventTallyError"))
}
panic(fmt.Errorf("message cosmos.group.v1.EventTallyError does not contain field %s", descriptor.FullName()))
}
}
// Set stores the value for a field.
//
// For a field belonging to a oneof, it implicitly clears any other field
// that may be currently set within the same oneof.
// For extension fields, it implicitly stores the provided ExtensionType.
// When setting a composite type, it is unspecified whether the stored value
// aliases the source's memory in any way. If the composite value is an
// empty, read-only value, then it panics.
//
// Set is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_EventTallyError) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) {
switch fd.FullName() {
case "cosmos.group.v1.EventTallyError.proposal_id":
x.ProposalId = value.Uint()
case "cosmos.group.v1.EventTallyError.error_message":
x.ErrorMessage = value.Interface().(string)
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.group.v1.EventTallyError"))
}
panic(fmt.Errorf("message cosmos.group.v1.EventTallyError does not contain field %s", fd.FullName()))
}
}
// Mutable returns a mutable reference to a composite type.
//
// If the field is unpopulated, it may allocate a composite value.
// For a field belonging to a oneof, it implicitly clears any other field
// that may be currently set within the same oneof.
// For extension fields, it implicitly stores the provided ExtensionType
// if not already stored.
// It panics if the field does not contain a composite type.
//
// Mutable is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_EventTallyError) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
switch fd.FullName() {
case "cosmos.group.v1.EventTallyError.proposal_id":
panic(fmt.Errorf("field proposal_id of message cosmos.group.v1.EventTallyError is not mutable"))
case "cosmos.group.v1.EventTallyError.error_message":
panic(fmt.Errorf("field error_message of message cosmos.group.v1.EventTallyError is not mutable"))
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.group.v1.EventTallyError"))
}
panic(fmt.Errorf("message cosmos.group.v1.EventTallyError does not contain field %s", fd.FullName()))
}
}
// NewField returns a new value that is assignable to the field
// for the given descriptor. For scalars, this returns the default value.
// For lists, maps, and messages, this returns a new, empty, mutable value.
func (x *fastReflection_EventTallyError) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
switch fd.FullName() {
case "cosmos.group.v1.EventTallyError.proposal_id":
return protoreflect.ValueOfUint64(uint64(0))
case "cosmos.group.v1.EventTallyError.error_message":
return protoreflect.ValueOfString("")
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.group.v1.EventTallyError"))
}
panic(fmt.Errorf("message cosmos.group.v1.EventTallyError does not contain field %s", fd.FullName()))
}
}
// WhichOneof reports which field within the oneof is populated,
// returning nil if none are populated.
// It panics if the oneof descriptor does not belong to this message.
func (x *fastReflection_EventTallyError) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
switch d.FullName() {
default:
panic(fmt.Errorf("%s is not a oneof field in cosmos.group.v1.EventTallyError", d.FullName()))
}
panic("unreachable")
}
// GetUnknown retrieves the entire list of unknown fields.
// The caller may only mutate the contents of the RawFields
// if the mutated bytes are stored back into the message with SetUnknown.
func (x *fastReflection_EventTallyError) GetUnknown() protoreflect.RawFields {
return x.unknownFields
}
// SetUnknown stores an entire list of unknown fields.
// The raw fields must be syntactically valid according to the wire format.
// An implementation may panic if this is not the case.
// Once stored, the caller must not mutate the content of the RawFields.
// An empty RawFields may be passed to clear the fields.
//
// SetUnknown is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_EventTallyError) SetUnknown(fields protoreflect.RawFields) {
x.unknownFields = fields
}
// IsValid reports whether the message is valid.
//
// An invalid message is an empty, read-only value.
//
// An invalid message often corresponds to a nil pointer of the concrete
// message type, but the details are implementation dependent.
// Validity is not part of the protobuf data model, and may not
// be preserved in marshaling or other operations.
func (x *fastReflection_EventTallyError) IsValid() bool {
return x != nil
}
// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations.
// This method may return nil.
//
// The returned methods type is identical to
// "google.golang.org/protobuf/runtime/protoiface".Methods.
// Consult the protoiface package documentation for details.
func (x *fastReflection_EventTallyError) ProtoMethods() *protoiface.Methods {
size := func(input protoiface.SizeInput) protoiface.SizeOutput {
x := input.Message.Interface().(*EventTallyError)
if x == nil {
return protoiface.SizeOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Size: 0,
}
}
options := runtime.SizeInputToOptions(input)
_ = options
var n int
var l int
_ = l
if x.ProposalId != 0 {
n += 1 + runtime.Sov(uint64(x.ProposalId))
}
l = len(x.ErrorMessage)
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
if x.unknownFields != nil {
n += len(x.unknownFields)
}
return protoiface.SizeOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Size: n,
}
}
marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
x := input.Message.Interface().(*EventTallyError)
if x == nil {
return protoiface.MarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Buf: input.Buf,
}, nil
}
options := runtime.MarshalInputToOptions(input)
_ = options
size := options.Size(x)
dAtA := make([]byte, size)
i := len(dAtA)
_ = i
var l int
_ = l
if x.unknownFields != nil {
i -= len(x.unknownFields)
copy(dAtA[i:], x.unknownFields)
}
if len(x.ErrorMessage) > 0 {
i -= len(x.ErrorMessage)
copy(dAtA[i:], x.ErrorMessage)
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ErrorMessage)))
i--
dAtA[i] = 0x12
}
if x.ProposalId != 0 {
i = runtime.EncodeVarint(dAtA, i, uint64(x.ProposalId))
i--
dAtA[i] = 0x8
}
if input.Buf != nil {
input.Buf = append(input.Buf, dAtA...)
} else {
input.Buf = dAtA
}
return protoiface.MarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Buf: input.Buf,
}, nil
}
unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
x := input.Message.Interface().(*EventTallyError)
if x == nil {
return protoiface.UnmarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Flags: input.Flags,
}, nil
}
options := runtime.UnmarshalInputToOptions(input)
_ = options
dAtA := input.Buf
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
}
if iNdEx >= l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventTallyError: wiretype end group for non-group")
}
if fieldNum <= 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventTallyError: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType)
}
x.ProposalId = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
}
if iNdEx >= l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
x.ProposalId |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ErrorMessage", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
}
if iNdEx >= l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if postIndex > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
x.ErrorMessage = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := runtime.Skip(dAtA[iNdEx:])
if err != nil {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if (iNdEx + skippy) > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
if !options.DiscardUnknown {
x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
}
iNdEx += skippy
}
}
if iNdEx > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil
}
return &protoiface.Methods{
NoUnkeyedLiterals: struct{}{},
Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown,
Size: size,
Marshal: marshal,
Unmarshal: unmarshal,
Merge: nil,
CheckInitialized: nil,
}
}
// Since: cosmos-sdk 0.46
// Code generated by protoc-gen-go. DO NOT EDIT.
@ -4818,6 +5286,52 @@ func (x *EventProposalPruned) GetTallyResult() *TallyResult {
return nil
}
// EventTallyError is an event emitted when a proposal tally failed with an error.
type EventTallyError struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// proposal_id is the unique ID of the proposal.
ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"`
// error_message is the raw error output
ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"`
}
func (x *EventTallyError) Reset() {
*x = EventTallyError{}
if protoimpl.UnsafeEnabled {
mi := &file_cosmos_group_v1_events_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EventTallyError) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EventTallyError) ProtoMessage() {}
// Deprecated: Use EventTallyError.ProtoReflect.Descriptor instead.
func (*EventTallyError) Descriptor() ([]byte, []int) {
return file_cosmos_group_v1_events_proto_rawDescGZIP(), []int{10}
}
func (x *EventTallyError) GetProposalId() uint64 {
if x != nil {
return x.ProposalId
}
return 0
}
func (x *EventTallyError) GetErrorMessage() string {
if x != nil {
return x.ErrorMessage
}
return ""
}
var File_cosmos_group_v1_events_proto protoreflect.FileDescriptor
var file_cosmos_group_v1_events_proto_rawDesc = []byte{
@ -4878,18 +5392,24 @@ var file_cosmos_group_v1_events_proto_rawDesc = []byte{
0x6c, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x76,
0x31, 0x2e, 0x54, 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0b, 0x74,
0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0xaa, 0x01, 0x0a, 0x13, 0x63,
0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2e,
0x76, 0x31, 0x42, 0x0b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
0x01, 0x5a, 0x28, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70,
0x2f, 0x76, 0x31, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x47,
0x58, 0xaa, 0x02, 0x0f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70,
0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47, 0x72, 0x6f,
0x75, 0x70, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47,
0x72, 0x6f, 0x75, 0x70, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64,
0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x47, 0x72,
0x6f, 0x75, 0x70, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x57, 0x0a, 0x0f, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x54, 0x61, 0x6c, 0x6c, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1f, 0x0a,
0x0b, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x23,
0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x42, 0xaa, 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d,
0x6f, 0x73, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x63, 0x6f, 0x73, 0x6d,
0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73,
0x6d, 0x6f, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x72, 0x6f,
0x75, 0x70, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x47, 0x58, 0xaa, 0x02, 0x0f, 0x43, 0x6f, 0x73,
0x6d, 0x6f, 0x73, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x43,
0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x5c, 0x56, 0x31, 0xe2, 0x02,
0x1b, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x5c, 0x56, 0x31,
0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x43,
0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x3a, 0x3a, 0x56, 0x31,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -4904,7 +5424,7 @@ func file_cosmos_group_v1_events_proto_rawDescGZIP() []byte {
return file_cosmos_group_v1_events_proto_rawDescData
}
var file_cosmos_group_v1_events_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_cosmos_group_v1_events_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_cosmos_group_v1_events_proto_goTypes = []interface{}{
(*EventCreateGroup)(nil), // 0: cosmos.group.v1.EventCreateGroup
(*EventUpdateGroup)(nil), // 1: cosmos.group.v1.EventUpdateGroup
@ -4916,14 +5436,15 @@ var file_cosmos_group_v1_events_proto_goTypes = []interface{}{
(*EventExec)(nil), // 7: cosmos.group.v1.EventExec
(*EventLeaveGroup)(nil), // 8: cosmos.group.v1.EventLeaveGroup
(*EventProposalPruned)(nil), // 9: cosmos.group.v1.EventProposalPruned
(ProposalExecutorResult)(0), // 10: cosmos.group.v1.ProposalExecutorResult
(ProposalStatus)(0), // 11: cosmos.group.v1.ProposalStatus
(*TallyResult)(nil), // 12: cosmos.group.v1.TallyResult
(*EventTallyError)(nil), // 10: cosmos.group.v1.EventTallyError
(ProposalExecutorResult)(0), // 11: cosmos.group.v1.ProposalExecutorResult
(ProposalStatus)(0), // 12: cosmos.group.v1.ProposalStatus
(*TallyResult)(nil), // 13: cosmos.group.v1.TallyResult
}
var file_cosmos_group_v1_events_proto_depIdxs = []int32{
10, // 0: cosmos.group.v1.EventExec.result:type_name -> cosmos.group.v1.ProposalExecutorResult
11, // 1: cosmos.group.v1.EventProposalPruned.status:type_name -> cosmos.group.v1.ProposalStatus
12, // 2: cosmos.group.v1.EventProposalPruned.tally_result:type_name -> cosmos.group.v1.TallyResult
11, // 0: cosmos.group.v1.EventExec.result:type_name -> cosmos.group.v1.ProposalExecutorResult
12, // 1: cosmos.group.v1.EventProposalPruned.status:type_name -> cosmos.group.v1.ProposalStatus
13, // 2: cosmos.group.v1.EventProposalPruned.tally_result:type_name -> cosmos.group.v1.TallyResult
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
@ -5058,6 +5579,18 @@ func file_cosmos_group_v1_events_proto_init() {
return nil
}
}
file_cosmos_group_v1_events_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EventTallyError); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -5065,7 +5598,7 @@ func file_cosmos_group_v1_events_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_cosmos_group_v1_events_proto_rawDesc,
NumEnums: 0,
NumMessages: 10,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -92,3 +92,13 @@ message EventProposalPruned {
// tally_result is the proposal tally result (when applicable).
TallyResult tally_result = 3;
}
// EventTallyError is an event emitted when a proposal tally failed with an error.
message EventTallyError {
// proposal_id is the unique ID of the proposal.
uint64 proposal_id = 1;
// error_message is the raw error output
string error_message = 2;
}

View File

@ -528,6 +528,61 @@ func (m *EventProposalPruned) GetTallyResult() *TallyResult {
return nil
}
// EventTallyError is an event emitted when a proposal tally failed with an error.
type EventTallyError struct {
// proposal_id is the unique ID of the proposal.
ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"`
// error_message is the raw error output
ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"`
}
func (m *EventTallyError) Reset() { *m = EventTallyError{} }
func (m *EventTallyError) String() string { return proto.CompactTextString(m) }
func (*EventTallyError) ProtoMessage() {}
func (*EventTallyError) Descriptor() ([]byte, []int) {
return fileDescriptor_e8d753981546f032, []int{10}
}
func (m *EventTallyError) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *EventTallyError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_EventTallyError.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *EventTallyError) XXX_Merge(src proto.Message) {
xxx_messageInfo_EventTallyError.Merge(m, src)
}
func (m *EventTallyError) XXX_Size() int {
return m.Size()
}
func (m *EventTallyError) XXX_DiscardUnknown() {
xxx_messageInfo_EventTallyError.DiscardUnknown(m)
}
var xxx_messageInfo_EventTallyError proto.InternalMessageInfo
func (m *EventTallyError) GetProposalId() uint64 {
if m != nil {
return m.ProposalId
}
return 0
}
func (m *EventTallyError) GetErrorMessage() string {
if m != nil {
return m.ErrorMessage
}
return ""
}
func init() {
proto.RegisterType((*EventCreateGroup)(nil), "cosmos.group.v1.EventCreateGroup")
proto.RegisterType((*EventUpdateGroup)(nil), "cosmos.group.v1.EventUpdateGroup")
@ -539,40 +594,43 @@ func init() {
proto.RegisterType((*EventExec)(nil), "cosmos.group.v1.EventExec")
proto.RegisterType((*EventLeaveGroup)(nil), "cosmos.group.v1.EventLeaveGroup")
proto.RegisterType((*EventProposalPruned)(nil), "cosmos.group.v1.EventProposalPruned")
proto.RegisterType((*EventTallyError)(nil), "cosmos.group.v1.EventTallyError")
}
func init() { proto.RegisterFile("cosmos/group/v1/events.proto", fileDescriptor_e8d753981546f032) }
var fileDescriptor_e8d753981546f032 = []byte{
// 442 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0x4f, 0xef, 0xd2, 0x30,
0x18, 0xc7, 0xe9, 0x4f, 0x02, 0x52, 0x8c, 0x98, 0xfa, 0x27, 0x03, 0xc9, 0x20, 0xc4, 0x44, 0x0e,
0xb2, 0x05, 0x4c, 0xd4, 0x93, 0x44, 0x0c, 0x31, 0x24, 0x1c, 0xc8, 0xf0, 0x4f, 0xe2, 0x05, 0xc7,
0xda, 0x8c, 0xc5, 0x41, 0x97, 0xb6, 0x9b, 0x70, 0xf4, 0x1d, 0xf8, 0x52, 0x3c, 0xf8, 0x22, 0x3c,
0x12, 0x4f, 0x1e, 0x0d, 0xbc, 0x11, 0xb3, 0xae, 0x03, 0x82, 0x31, 0x23, 0xf9, 0x9d, 0x68, 0xfb,
0xfd, 0x7c, 0xbf, 0x3c, 0x4f, 0x9f, 0x15, 0xd6, 0x1d, 0xca, 0x97, 0x94, 0x9b, 0x2e, 0xa3, 0x61,
0x60, 0x46, 0x5d, 0x93, 0x44, 0x64, 0x25, 0xb8, 0x11, 0x30, 0x2a, 0x28, 0xaa, 0x24, 0xaa, 0x21,
0x55, 0x23, 0xea, 0xd6, 0xaa, 0xc9, 0xc1, 0x4c, 0xca, 0xa6, 0x52, 0xe5, 0xa6, 0xf6, 0xf0, 0x3c,
0x49, 0x6c, 0x02, 0xa2, 0xc4, 0x56, 0x07, 0xde, 0x19, 0xc6, 0xc1, 0xaf, 0x19, 0xb1, 0x05, 0x79,
0x13, 0x23, 0xa8, 0x0a, 0x6f, 0x4a, 0x76, 0xe6, 0x61, 0x0d, 0x34, 0x41, 0x3b, 0x6f, 0x15, 0xe5,
0x7e, 0x84, 0x0f, 0xf8, 0xbb, 0x00, 0x5f, 0x82, 0x8f, 0xe1, 0x83, 0xf3, 0xf4, 0x09, 0xf5, 0x3d,
0x67, 0x83, 0x7a, 0xb0, 0x68, 0x63, 0xcc, 0x08, 0xe7, 0xd2, 0x53, 0x1a, 0x68, 0xbf, 0x7e, 0x74,
0xee, 0xa9, 0xba, 0x5f, 0x25, 0xca, 0x54, 0x30, 0x6f, 0xe5, 0x5a, 0x29, 0x78, 0x48, 0x3b, 0xf9,
0xf3, 0x6b, 0xa4, 0x3d, 0x83, 0x77, 0x65, 0xda, 0x34, 0x9c, 0x2f, 0x3d, 0x31, 0x61, 0x34, 0xa0,
0xdc, 0xf6, 0x51, 0x03, 0x96, 0x03, 0xb5, 0x3e, 0x36, 0x04, 0xd3, 0xa3, 0x11, 0x6e, 0xbd, 0x80,
0xf7, 0xa5, 0xef, 0x83, 0x27, 0x16, 0x98, 0xd9, 0x5f, 0x2e, 0x77, 0x3e, 0x81, 0x25, 0xe9, 0x7c,
0x4f, 0x05, 0xc9, 0xa6, 0xbf, 0x02, 0x85, 0x0f, 0xd7, 0xc4, 0xc9, 0xc4, 0x51, 0x1f, 0x16, 0x18,
0xe1, 0xa1, 0x2f, 0xb4, 0xab, 0x26, 0x68, 0xdf, 0xee, 0x3d, 0x36, 0xce, 0x3e, 0x11, 0x23, 0x2d,
0x34, 0xce, 0x0b, 0x05, 0x65, 0x96, 0xc4, 0x2d, 0x65, 0x43, 0x08, 0xe6, 0x7d, 0xea, 0x72, 0xed,
0x46, 0x7c, 0x81, 0x96, 0x5c, 0xb7, 0x3e, 0xc1, 0x8a, 0x2c, 0x61, 0x4c, 0xec, 0x28, 0x73, 0xda,
0xa7, 0x53, 0xb8, 0xba, 0x74, 0x0a, 0xdf, 0x81, 0x1a, 0x43, 0x5a, 0xdd, 0x84, 0x85, 0x2b, 0x82,
0xb3, 0xfb, 0x7d, 0x0e, 0x0b, 0x5c, 0xd8, 0x22, 0xe4, 0xaa, 0xdf, 0xc6, 0x7f, 0xfb, 0x9d, 0x4a,
0xcc, 0x52, 0x38, 0xea, 0xc3, 0x5b, 0xc2, 0xf6, 0xfd, 0xcd, 0x4c, 0x5d, 0x57, 0xdc, 0x6f, 0xb9,
0x57, 0xff, 0xc7, 0xfe, 0x36, 0x86, 0xd4, 0x1d, 0x95, 0xc5, 0x71, 0x33, 0x78, 0xf9, 0x73, 0xa7,
0x83, 0xed, 0x4e, 0x07, 0x7f, 0x76, 0x3a, 0xf8, 0xb6, 0xd7, 0x73, 0xdb, 0xbd, 0x9e, 0xfb, 0xbd,
0xd7, 0x73, 0x1f, 0x1f, 0xb9, 0x9e, 0x58, 0x84, 0x73, 0xc3, 0xa1, 0x4b, 0xf5, 0x04, 0xd5, 0x4f,
0x87, 0xe3, 0xcf, 0xe6, 0x3a, 0x79, 0x81, 0xf3, 0x82, 0x7c, 0x79, 0x4f, 0xff, 0x06, 0x00, 0x00,
0xff, 0xff, 0xa5, 0x1a, 0x1c, 0xb9, 0xe2, 0x03, 0x00, 0x00,
// 476 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0x4d, 0x6b, 0x13, 0x41,
0x18, 0xc7, 0x33, 0xb5, 0xa4, 0xf6, 0x49, 0xb5, 0x32, 0xbe, 0x90, 0xd6, 0xb2, 0x2d, 0x51, 0xb0,
0x07, 0xb3, 0x4b, 0x23, 0xa8, 0x27, 0x8b, 0x95, 0x20, 0x85, 0x0a, 0x61, 0xa3, 0x16, 0xbc, 0xc4,
0x49, 0x66, 0xd8, 0x2e, 0xee, 0x66, 0x96, 0x99, 0xd9, 0xb5, 0x39, 0xfa, 0x0d, 0xfc, 0x28, 0x1e,
0xfc, 0x10, 0x1e, 0x8b, 0x27, 0x8f, 0x92, 0x7c, 0x11, 0xd9, 0x67, 0x67, 0xdb, 0x10, 0x91, 0x0d,
0x78, 0xca, 0xcc, 0xf3, 0xfc, 0xfe, 0xff, 0x3c, 0x2f, 0x3b, 0xb0, 0x33, 0x92, 0x3a, 0x96, 0xda,
0x0b, 0x94, 0x4c, 0x13, 0x2f, 0x3b, 0xf0, 0x44, 0x26, 0xc6, 0x46, 0xbb, 0x89, 0x92, 0x46, 0xd2,
0xcd, 0x22, 0xeb, 0x62, 0xd6, 0xcd, 0x0e, 0xb6, 0xb7, 0x8a, 0xc0, 0x00, 0xd3, 0x9e, 0xcd, 0xe2,
0x65, 0xfb, 0xfe, 0xa2, 0x93, 0x99, 0x24, 0xc2, 0x26, 0x5b, 0x6d, 0xb8, 0xd5, 0xcd, 0x8d, 0x5f,
0x29, 0xc1, 0x8c, 0x78, 0x9d, 0x23, 0x74, 0x0b, 0xae, 0x23, 0x3b, 0x08, 0x79, 0x93, 0xec, 0x91,
0xfd, 0x55, 0x7f, 0x0d, 0xef, 0xc7, 0xfc, 0x12, 0x7f, 0x97, 0xf0, 0x65, 0xf0, 0x13, 0xb8, 0xb7,
0xe8, 0xde, 0x93, 0x51, 0x38, 0x9a, 0xd0, 0x0e, 0xac, 0x31, 0xce, 0x95, 0xd0, 0x1a, 0x35, 0xeb,
0x47, 0xcd, 0x9f, 0xdf, 0xdb, 0x77, 0x6c, 0xdd, 0x2f, 0x8b, 0x4c, 0xdf, 0xa8, 0x70, 0x1c, 0xf8,
0x25, 0x78, 0xe9, 0x36, 0xf7, 0xe7, 0xff, 0xe1, 0xf6, 0x14, 0x6e, 0xa3, 0x5b, 0x3f, 0x1d, 0xc6,
0xa1, 0xe9, 0x29, 0x99, 0x48, 0xcd, 0x22, 0xba, 0x0b, 0x8d, 0xc4, 0x9e, 0xaf, 0x1a, 0x82, 0x32,
0x74, 0xcc, 0x5b, 0xcf, 0xe1, 0x2e, 0xea, 0x4e, 0x43, 0x73, 0xc6, 0x15, 0xfb, 0xbc, 0xbc, 0xf2,
0x31, 0xac, 0xa3, 0xf2, 0xbd, 0x34, 0xa2, 0x9a, 0xfe, 0x42, 0x2c, 0xde, 0x3d, 0x17, 0xa3, 0x4a,
0x9c, 0x1e, 0x42, 0x5d, 0x09, 0x9d, 0x46, 0xa6, 0xb9, 0xb2, 0x47, 0xf6, 0x6f, 0x76, 0x1e, 0xb9,
0x0b, 0x9f, 0x88, 0x5b, 0x16, 0x9a, 0xfb, 0xa5, 0x46, 0x2a, 0x1f, 0x71, 0xdf, 0xca, 0x28, 0x85,
0xd5, 0x48, 0x06, 0xba, 0x79, 0x2d, 0x1f, 0xa0, 0x8f, 0xe7, 0xd6, 0x47, 0xd8, 0xc4, 0x12, 0x4e,
0x04, 0xcb, 0x2a, 0xb7, 0x3d, 0xbf, 0x85, 0x95, 0x65, 0xb7, 0xf0, 0x8d, 0xd8, 0x35, 0x94, 0xd5,
0xf5, 0x54, 0x3a, 0x16, 0xbc, 0xba, 0xdf, 0x67, 0x50, 0xd7, 0x86, 0x99, 0x54, 0xdb, 0x7e, 0x77,
0xff, 0xd9, 0x6f, 0x1f, 0x31, 0xdf, 0xe2, 0xf4, 0x10, 0x36, 0x0c, 0x8b, 0xa2, 0xc9, 0xc0, 0x8e,
0x2b, 0xef, 0xb7, 0xd1, 0xd9, 0xf9, 0x4b, 0xfe, 0x36, 0x87, 0xec, 0x8c, 0x1a, 0xe6, 0xea, 0xd2,
0x3a, 0xb5, 0x43, 0x41, 0xa0, 0xab, 0x94, 0x54, 0xd5, 0xd5, 0x3e, 0x80, 0x1b, 0x22, 0x27, 0x07,
0xb1, 0xd0, 0x9a, 0x05, 0xa2, 0x18, 0x90, 0xbf, 0x81, 0xc1, 0x37, 0x45, 0xec, 0xe8, 0xc5, 0x8f,
0xa9, 0x43, 0x2e, 0xa6, 0x0e, 0xf9, 0x3d, 0x75, 0xc8, 0xd7, 0x99, 0x53, 0xbb, 0x98, 0x39, 0xb5,
0x5f, 0x33, 0xa7, 0xf6, 0xe1, 0x61, 0x10, 0x9a, 0xb3, 0x74, 0xe8, 0x8e, 0x64, 0x6c, 0xdf, 0xb6,
0xfd, 0x69, 0x6b, 0xfe, 0xc9, 0x3b, 0x2f, 0x9e, 0xf6, 0xb0, 0x8e, 0x4f, 0xfa, 0xc9, 0x9f, 0x00,
0x00, 0x00, 0xff, 0xff, 0x14, 0x0c, 0xb7, 0x93, 0x3b, 0x04, 0x00, 0x00,
}
func (m *EventCreateGroup) Marshal() (dAtA []byte, err error) {
@ -895,6 +953,41 @@ func (m *EventProposalPruned) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *EventTallyError) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *EventTallyError) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *EventTallyError) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.ErrorMessage) > 0 {
i -= len(m.ErrorMessage)
copy(dAtA[i:], m.ErrorMessage)
i = encodeVarintEvents(dAtA, i, uint64(len(m.ErrorMessage)))
i--
dAtA[i] = 0x12
}
if m.ProposalId != 0 {
i = encodeVarintEvents(dAtA, i, uint64(m.ProposalId))
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func encodeVarintEvents(dAtA []byte, offset int, v uint64) int {
offset -= sovEvents(v)
base := offset
@ -1046,6 +1139,22 @@ func (m *EventProposalPruned) Size() (n int) {
return n
}
func (m *EventTallyError) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.ProposalId != 0 {
n += 1 + sovEvents(uint64(m.ProposalId))
}
l = len(m.ErrorMessage)
if l > 0 {
n += 1 + l + sovEvents(uint64(l))
}
return n
}
func sovEvents(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
@ -1906,6 +2015,107 @@ func (m *EventProposalPruned) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *EventTallyError) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: EventTallyError: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: EventTallyError: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType)
}
m.ProposalId = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ProposalId |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ErrorMessage", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ErrorMessage = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipEvents(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvents
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipEvents(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0

View File

@ -781,33 +781,40 @@ func (k Keeper) Vote(goCtx context.Context, msg *group.MsgVote) (*group.MsgVoteR
// doTallyAndUpdate performs a tally, and, if the tally result is final, then:
// - updates the proposal's `Status` and `FinalTallyResult` fields,
// - prune all the votes.
func (k Keeper) doTallyAndUpdate(ctx sdk.Context, p *group.Proposal, groupInfo group.GroupInfo, policyInfo group.GroupPolicyInfo) error {
func (k Keeper) doTallyAndUpdate(ctx sdk.Context, proposal *group.Proposal, groupInfo group.GroupInfo, policyInfo group.GroupPolicyInfo) error {
policy, err := policyInfo.GetDecisionPolicy()
if err != nil {
return err
}
tallyResult, err := k.Tally(ctx, *p, policyInfo.GroupId)
if err != nil {
return err
var result group.DecisionPolicyResult
tallyResult, err := k.Tally(ctx, *proposal, policyInfo.GroupId)
if err == nil {
result, err = policy.Allow(tallyResult, groupInfo.TotalWeight)
}
result, err := policy.Allow(tallyResult, groupInfo.TotalWeight)
if err != nil {
return errorsmod.Wrap(err, "policy allow")
if err := k.pruneVotes(ctx, proposal.Id); err != nil {
return err
}
proposal.Status = group.PROPOSAL_STATUS_REJECTED
return ctx.EventManager().EmitTypedEvents(
&group.EventTallyError{
ProposalId: proposal.Id,
ErrorMessage: err.Error(),
})
}
// If the result was final (i.e. enough votes to pass) or if the voting
// period ended, then we consider the proposal as final.
if isFinal := result.Final || ctx.BlockTime().After(p.VotingPeriodEnd); isFinal {
if err := k.pruneVotes(ctx, p.Id); err != nil {
if isFinal := result.Final || ctx.BlockTime().After(proposal.VotingPeriodEnd); isFinal {
if err := k.pruneVotes(ctx, proposal.Id); err != nil {
return err
}
p.FinalTallyResult = tallyResult
proposal.FinalTallyResult = tallyResult
if result.Allow {
p.Status = group.PROPOSAL_STATUS_ACCEPTED
proposal.Status = group.PROPOSAL_STATUS_ACCEPTED
} else {
p.Status = group.PROPOSAL_STATUS_REJECTED
proposal.Status = group.PROPOSAL_STATUS_REJECTED
}
}

View File

@ -0,0 +1,254 @@
package keeper
import (
"bytes"
"context"
"errors"
"fmt"
"testing"
"time"
"github.com/cosmos/gogoproto/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
coreaddress "cosmossdk.io/core/address"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
"github.com/cosmos/cosmos-sdk/x/group"
"github.com/cosmos/cosmos-sdk/x/group/internal/math"
)
func TestDoTallyAndUpdate(t *testing.T) {
var (
myAddr = sdk.AccAddress(bytes.Repeat([]byte{0x01}, 20))
myOtherAddr = sdk.AccAddress(bytes.Repeat([]byte{0x02}, 20))
)
encCfg := moduletestutil.MakeTestEncodingConfig()
group.RegisterInterfaces(encCfg.InterfaceRegistry)
storeKey := storetypes.NewKVStoreKey(group.StoreKey)
testCtx := testutil.DefaultContextWithDB(t, storeKey, storetypes.NewTransientStoreKey("transient_test"))
myAccountKeeper := &mockAccountKeeper{
AddressCodecFn: func() coreaddress.Codec {
return address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix())
},
}
groupKeeper := NewKeeper(storeKey, encCfg.Codec, nil, myAccountKeeper, group.DefaultConfig())
noEventsFn := func(proposalID uint64) sdk.Events { return sdk.Events{} }
type memberVote struct {
address string
weight string
option group.VoteOption
}
specs := map[string]struct {
votes []memberVote
policy group.DecisionPolicy
expStatus group.ProposalStatus
expVotesCleared bool
expEvents func(proposalID uint64) sdk.Events
}{
"proposal accepted": {
votes: []memberVote{
{address: myAddr.String(), option: group.VOTE_OPTION_YES, weight: "2"},
{address: myOtherAddr.String(), option: group.VOTE_OPTION_NO, weight: "1"},
},
policy: mockDecisionPolicy{
AllowFn: func(tallyResult group.TallyResult, totalPower string) (group.DecisionPolicyResult, error) {
return group.DecisionPolicyResult{Allow: true, Final: true}, nil
},
},
expStatus: group.PROPOSAL_STATUS_ACCEPTED,
expVotesCleared: true,
expEvents: noEventsFn,
},
"proposal rejected": {
votes: []memberVote{
{address: myAddr.String(), option: group.VOTE_OPTION_YES, weight: "1"},
{address: myOtherAddr.String(), option: group.VOTE_OPTION_NO, weight: "2"},
},
policy: mockDecisionPolicy{
AllowFn: func(tallyResult group.TallyResult, totalPower string) (group.DecisionPolicyResult, error) {
return group.DecisionPolicyResult{Allow: false, Final: true}, nil
},
},
expStatus: group.PROPOSAL_STATUS_REJECTED,
expVotesCleared: true,
expEvents: noEventsFn,
},
"proposal in flight": {
votes: []memberVote{
{address: myAddr.String(), option: group.VOTE_OPTION_YES, weight: "1"},
{address: myOtherAddr.String(), option: group.VOTE_OPTION_NO, weight: "1"},
},
policy: mockDecisionPolicy{
AllowFn: func(tallyResult group.TallyResult, totalPower string) (group.DecisionPolicyResult, error) {
return group.DecisionPolicyResult{Allow: false, Final: false}, nil
},
},
expStatus: group.PROPOSAL_STATUS_SUBMITTED,
expVotesCleared: false,
expEvents: noEventsFn,
},
"policy errors": {
votes: []memberVote{
{address: myAddr.String(), option: group.VOTE_OPTION_YES, weight: "1"},
{address: myOtherAddr.String(), option: group.VOTE_OPTION_NO, weight: "2"},
},
policy: mockDecisionPolicy{
AllowFn: func(tallyResult group.TallyResult, totalPower string) (group.DecisionPolicyResult, error) {
return group.DecisionPolicyResult{}, errors.New("my test error")
},
},
expStatus: group.PROPOSAL_STATUS_REJECTED,
expVotesCleared: true,
expEvents: func(proposalID uint64) sdk.Events {
return sdk.Events{
sdk.NewEvent("cosmos.group.v1.EventTallyError",
sdk.Attribute{Key: "error_message", Value: `"my test error"`},
sdk.Attribute{Key: "proposal_id", Value: fmt.Sprintf(`"%d"`, proposalID)},
),
}
},
},
}
var (
groupID uint64
proposalId uint64
)
for name, spec := range specs {
groupID++
proposalId++
t.Run(name, func(t *testing.T) {
em := sdk.NewEventManager()
ctx := testCtx.Ctx.WithEventManager(em)
totalWeight, err := math.NewDecFromString("0")
require.NoError(t, err)
// given a group, policy and persisted votes
for _, v := range spec.votes {
err := groupKeeper.groupMemberTable.Create(ctx.KVStore(storeKey), &group.GroupMember{
GroupId: groupID,
Member: &group.Member{Address: v.address, Weight: v.weight},
})
require.NoError(t, err)
err = groupKeeper.voteTable.Create(ctx.KVStore(storeKey), &group.Vote{
ProposalId: proposalId,
Voter: v.address,
Option: v.option,
})
require.NoError(t, err)
}
myGroupInfo := group.GroupInfo{
TotalWeight: totalWeight.String(),
}
myPolicy := group.GroupPolicyInfo{GroupId: groupID}
err = myPolicy.SetDecisionPolicy(spec.policy)
require.NoError(t, err)
myProposal := &group.Proposal{
Id: proposalId,
Status: group.PROPOSAL_STATUS_SUBMITTED,
VotingPeriodEnd: ctx.BlockTime().Add(time.Hour),
}
// when
gotErr := groupKeeper.doTallyAndUpdate(ctx, myProposal, myGroupInfo, myPolicy)
// then
require.NoError(t, gotErr)
assert.Equal(t, spec.expStatus, myProposal.Status)
require.Equal(t, spec.expEvents(proposalId), em.Events())
// and persistent state updated
persistedVotes, err := groupKeeper.votesByProposal(ctx, groupID)
require.NoError(t, err)
if spec.expVotesCleared {
assert.Empty(t, persistedVotes)
} else {
assert.Len(t, persistedVotes, len(spec.votes))
}
})
}
}
var _ group.AccountKeeper = &mockAccountKeeper{}
// mockAccountKeeper is a mock implementation of the AccountKeeper interface for testing purposes.
type mockAccountKeeper struct {
AddressCodecFn func() coreaddress.Codec
}
func (m mockAccountKeeper) AddressCodec() coreaddress.Codec {
if m.AddressCodecFn == nil {
panic("not expected to be called")
}
return m.AddressCodecFn()
}
func (m mockAccountKeeper) NewAccount(ctx context.Context, i sdk.AccountI) sdk.AccountI {
panic("not expected to be called")
}
func (m mockAccountKeeper) GetAccount(ctx context.Context, address sdk.AccAddress) sdk.AccountI {
panic("not expected to be called")
}
func (m mockAccountKeeper) SetAccount(ctx context.Context, i sdk.AccountI) {
panic("not expected to be called")
}
func (m mockAccountKeeper) RemoveAccount(ctx context.Context, acc sdk.AccountI) {
panic("not expected to be called")
}
// mockDecisionPolicy is a mock implementation of a decision policy for testing purposes.
type mockDecisionPolicy struct {
fakeProtoType
AllowFn func(tallyResult group.TallyResult, totalPower string) (group.DecisionPolicyResult, error)
}
func (m mockDecisionPolicy) Allow(tallyResult group.TallyResult, totalPower string) (group.DecisionPolicyResult, error) {
if m.AllowFn == nil {
panic("not expected to be called")
}
return m.AllowFn(tallyResult, totalPower)
}
func (m mockDecisionPolicy) GetVotingPeriod() time.Duration {
panic("not expected to be called")
}
func (m mockDecisionPolicy) GetMinExecutionPeriod() time.Duration {
panic("not expected to be called")
}
func (m mockDecisionPolicy) ValidateBasic() error {
panic("not expected to be called")
}
func (m mockDecisionPolicy) Validate(g group.GroupInfo, config group.Config) error {
panic("not expected to be called")
}
var (
_ proto.Marshaler = (*fakeProtoType)(nil)
_ proto.Message = (*fakeProtoType)(nil)
)
// fakeProtoType is a struct used for mocking and testing purposes.
// Custom types can be converted into Any and back via internal CachedValue only.
type fakeProtoType struct{}
func (a fakeProtoType) Reset() {}
func (a fakeProtoType) String() string {
return "testing"
}
func (a fakeProtoType) Marshal() ([]byte, error) {
return nil, nil
}
func (a fakeProtoType) ProtoMessage() {}