diff --git a/api/uexecutor/v1/query.pulsar.go b/api/uexecutor/v1/query.pulsar.go index f47b0f70a..66eb0136f 100644 --- a/api/uexecutor/v1/query.pulsar.go +++ b/api/uexecutor/v1/query.pulsar.go @@ -11209,6 +11209,2066 @@ func (x *fastReflection_QueryAllPendingOutboundsResponse) ProtoMethods() *protoi } } +var ( + md_QueryInboundKeysRequest protoreflect.MessageDescriptor + fd_QueryInboundKeysRequest_inbound protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryInboundKeysRequest = File_uexecutor_v1_query_proto.Messages().ByName("QueryInboundKeysRequest") + fd_QueryInboundKeysRequest_inbound = md_QueryInboundKeysRequest.Fields().ByName("inbound") +} + +var _ protoreflect.Message = (*fastReflection_QueryInboundKeysRequest)(nil) + +type fastReflection_QueryInboundKeysRequest QueryInboundKeysRequest + +func (x *QueryInboundKeysRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryInboundKeysRequest)(x) +} + +func (x *QueryInboundKeysRequest) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[23] + 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_QueryInboundKeysRequest_messageType fastReflection_QueryInboundKeysRequest_messageType +var _ protoreflect.MessageType = fastReflection_QueryInboundKeysRequest_messageType{} + +type fastReflection_QueryInboundKeysRequest_messageType struct{} + +func (x fastReflection_QueryInboundKeysRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryInboundKeysRequest)(nil) +} +func (x fastReflection_QueryInboundKeysRequest_messageType) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysRequest) +} +func (x fastReflection_QueryInboundKeysRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryInboundKeysRequest) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysRequest +} + +// 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_QueryInboundKeysRequest) Type() protoreflect.MessageType { + return _fastReflection_QueryInboundKeysRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryInboundKeysRequest) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryInboundKeysRequest) Interface() protoreflect.ProtoMessage { + return (*QueryInboundKeysRequest)(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_QueryInboundKeysRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Inbound != nil { + value := protoreflect.ValueOfMessage(x.Inbound.ProtoReflect()) + if !f(fd_QueryInboundKeysRequest_inbound, 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_QueryInboundKeysRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + return x.Inbound != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest 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_QueryInboundKeysRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + x.Inbound = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest 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_QueryInboundKeysRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + value := x.Inbound + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest 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_QueryInboundKeysRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + x.Inbound = value.Message().Interface().(*Inbound) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest 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_QueryInboundKeysRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + if x.Inbound == nil { + x.Inbound = new(Inbound) + } + return protoreflect.ValueOfMessage(x.Inbound.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest 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_QueryInboundKeysRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + m := new(Inbound) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest 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_QueryInboundKeysRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryInboundKeysRequest", 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_QueryInboundKeysRequest) 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_QueryInboundKeysRequest) 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_QueryInboundKeysRequest) 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_QueryInboundKeysRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryInboundKeysRequest) + 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.Inbound != nil { + l = options.Size(x.Inbound) + 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().(*QueryInboundKeysRequest) + 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 x.Inbound != nil { + encoded, err := options.Marshal(x.Inbound) + 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 + } + 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().(*QueryInboundKeysRequest) + 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: QueryInboundKeysRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryInboundKeysRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Inbound", wireType) + } + var msglen int + 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++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + 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 + } + if x.Inbound == nil { + x.Inbound = &Inbound{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Inbound); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + 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, + } +} + +var ( + md_QueryInboundKeysResponse protoreflect.MessageDescriptor + fd_QueryInboundKeysResponse_utx_id protoreflect.FieldDescriptor + fd_QueryInboundKeysResponse_ballot_id protoreflect.FieldDescriptor + fd_QueryInboundKeysResponse_canonical_inbound protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryInboundKeysResponse = File_uexecutor_v1_query_proto.Messages().ByName("QueryInboundKeysResponse") + fd_QueryInboundKeysResponse_utx_id = md_QueryInboundKeysResponse.Fields().ByName("utx_id") + fd_QueryInboundKeysResponse_ballot_id = md_QueryInboundKeysResponse.Fields().ByName("ballot_id") + fd_QueryInboundKeysResponse_canonical_inbound = md_QueryInboundKeysResponse.Fields().ByName("canonical_inbound") +} + +var _ protoreflect.Message = (*fastReflection_QueryInboundKeysResponse)(nil) + +type fastReflection_QueryInboundKeysResponse QueryInboundKeysResponse + +func (x *QueryInboundKeysResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryInboundKeysResponse)(x) +} + +func (x *QueryInboundKeysResponse) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[24] + 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_QueryInboundKeysResponse_messageType fastReflection_QueryInboundKeysResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryInboundKeysResponse_messageType{} + +type fastReflection_QueryInboundKeysResponse_messageType struct{} + +func (x fastReflection_QueryInboundKeysResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryInboundKeysResponse)(nil) +} +func (x fastReflection_QueryInboundKeysResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysResponse) +} +func (x fastReflection_QueryInboundKeysResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryInboundKeysResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysResponse +} + +// 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_QueryInboundKeysResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryInboundKeysResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryInboundKeysResponse) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryInboundKeysResponse) Interface() protoreflect.ProtoMessage { + return (*QueryInboundKeysResponse)(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_QueryInboundKeysResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.UtxId != "" { + value := protoreflect.ValueOfString(x.UtxId) + if !f(fd_QueryInboundKeysResponse_utx_id, value) { + return + } + } + if x.BallotId != "" { + value := protoreflect.ValueOfString(x.BallotId) + if !f(fd_QueryInboundKeysResponse_ballot_id, value) { + return + } + } + if x.CanonicalInbound != nil { + value := protoreflect.ValueOfMessage(x.CanonicalInbound.ProtoReflect()) + if !f(fd_QueryInboundKeysResponse_canonical_inbound, 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_QueryInboundKeysResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + return x.UtxId != "" + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + return x.BallotId != "" + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + return x.CanonicalInbound != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse 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_QueryInboundKeysResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + x.UtxId = "" + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + x.BallotId = "" + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + x.CanonicalInbound = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse 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_QueryInboundKeysResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + value := x.UtxId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + value := x.BallotId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + value := x.CanonicalInbound + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse 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_QueryInboundKeysResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + x.UtxId = value.Interface().(string) + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + x.BallotId = value.Interface().(string) + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + x.CanonicalInbound = value.Message().Interface().(*Inbound) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse 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_QueryInboundKeysResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + if x.CanonicalInbound == nil { + x.CanonicalInbound = new(Inbound) + } + return protoreflect.ValueOfMessage(x.CanonicalInbound.ProtoReflect()) + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + panic(fmt.Errorf("field utx_id of message uexecutor.v1.QueryInboundKeysResponse is not mutable")) + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + panic(fmt.Errorf("field ballot_id of message uexecutor.v1.QueryInboundKeysResponse is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse 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_QueryInboundKeysResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + m := new(Inbound) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse 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_QueryInboundKeysResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryInboundKeysResponse", 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_QueryInboundKeysResponse) 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_QueryInboundKeysResponse) 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_QueryInboundKeysResponse) 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_QueryInboundKeysResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryInboundKeysResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.UtxId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.BallotId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.CanonicalInbound != nil { + l = options.Size(x.CanonicalInbound) + 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().(*QueryInboundKeysResponse) + 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 x.CanonicalInbound != nil { + encoded, err := options.Marshal(x.CanonicalInbound) + 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] = 0x1a + } + if len(x.BallotId) > 0 { + i -= len(x.BallotId) + copy(dAtA[i:], x.BallotId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.BallotId))) + i-- + dAtA[i] = 0x12 + } + if len(x.UtxId) > 0 { + i -= len(x.UtxId) + copy(dAtA[i:], x.UtxId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.UtxId))) + i-- + dAtA[i] = 0xa + } + 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().(*QueryInboundKeysResponse) + 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: QueryInboundKeysResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryInboundKeysResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field UtxId", 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.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field BallotId", 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.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field CanonicalInbound", wireType) + } + var msglen int + 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++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + 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 + } + if x.CanonicalInbound == nil { + x.CanonicalInbound = &Inbound{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.CanonicalInbound); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + 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, + } +} + +var ( + md_QueryOutboundBallotKeyRequest protoreflect.MessageDescriptor + fd_QueryOutboundBallotKeyRequest_utx_id protoreflect.FieldDescriptor + fd_QueryOutboundBallotKeyRequest_outbound_id protoreflect.FieldDescriptor + fd_QueryOutboundBallotKeyRequest_observed_tx protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryOutboundBallotKeyRequest = File_uexecutor_v1_query_proto.Messages().ByName("QueryOutboundBallotKeyRequest") + fd_QueryOutboundBallotKeyRequest_utx_id = md_QueryOutboundBallotKeyRequest.Fields().ByName("utx_id") + fd_QueryOutboundBallotKeyRequest_outbound_id = md_QueryOutboundBallotKeyRequest.Fields().ByName("outbound_id") + fd_QueryOutboundBallotKeyRequest_observed_tx = md_QueryOutboundBallotKeyRequest.Fields().ByName("observed_tx") +} + +var _ protoreflect.Message = (*fastReflection_QueryOutboundBallotKeyRequest)(nil) + +type fastReflection_QueryOutboundBallotKeyRequest QueryOutboundBallotKeyRequest + +func (x *QueryOutboundBallotKeyRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyRequest)(x) +} + +func (x *QueryOutboundBallotKeyRequest) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[25] + 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_QueryOutboundBallotKeyRequest_messageType fastReflection_QueryOutboundBallotKeyRequest_messageType +var _ protoreflect.MessageType = fastReflection_QueryOutboundBallotKeyRequest_messageType{} + +type fastReflection_QueryOutboundBallotKeyRequest_messageType struct{} + +func (x fastReflection_QueryOutboundBallotKeyRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyRequest)(nil) +} +func (x fastReflection_QueryOutboundBallotKeyRequest_messageType) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyRequest) +} +func (x fastReflection_QueryOutboundBallotKeyRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyRequest +} + +// 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_QueryOutboundBallotKeyRequest) Type() protoreflect.MessageType { + return _fastReflection_QueryOutboundBallotKeyRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryOutboundBallotKeyRequest) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Interface() protoreflect.ProtoMessage { + return (*QueryOutboundBallotKeyRequest)(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_QueryOutboundBallotKeyRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.UtxId != "" { + value := protoreflect.ValueOfString(x.UtxId) + if !f(fd_QueryOutboundBallotKeyRequest_utx_id, value) { + return + } + } + if x.OutboundId != "" { + value := protoreflect.ValueOfString(x.OutboundId) + if !f(fd_QueryOutboundBallotKeyRequest_outbound_id, value) { + return + } + } + if x.ObservedTx != nil { + value := protoreflect.ValueOfMessage(x.ObservedTx.ProtoReflect()) + if !f(fd_QueryOutboundBallotKeyRequest_observed_tx, 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_QueryOutboundBallotKeyRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + return x.UtxId != "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + return x.OutboundId != "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + return x.ObservedTx != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest 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_QueryOutboundBallotKeyRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + x.UtxId = "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + x.OutboundId = "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + x.ObservedTx = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest 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_QueryOutboundBallotKeyRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + value := x.UtxId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + value := x.OutboundId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + value := x.ObservedTx + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest 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_QueryOutboundBallotKeyRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + x.UtxId = value.Interface().(string) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + x.OutboundId = value.Interface().(string) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + x.ObservedTx = value.Message().Interface().(*OutboundObservation) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest 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_QueryOutboundBallotKeyRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + if x.ObservedTx == nil { + x.ObservedTx = new(OutboundObservation) + } + return protoreflect.ValueOfMessage(x.ObservedTx.ProtoReflect()) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + panic(fmt.Errorf("field utx_id of message uexecutor.v1.QueryOutboundBallotKeyRequest is not mutable")) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + panic(fmt.Errorf("field outbound_id of message uexecutor.v1.QueryOutboundBallotKeyRequest is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest 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_QueryOutboundBallotKeyRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + m := new(OutboundObservation) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest 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_QueryOutboundBallotKeyRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryOutboundBallotKeyRequest", 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_QueryOutboundBallotKeyRequest) 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_QueryOutboundBallotKeyRequest) 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_QueryOutboundBallotKeyRequest) 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_QueryOutboundBallotKeyRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryOutboundBallotKeyRequest) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.UtxId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.OutboundId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.ObservedTx != nil { + l = options.Size(x.ObservedTx) + 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().(*QueryOutboundBallotKeyRequest) + 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 x.ObservedTx != nil { + encoded, err := options.Marshal(x.ObservedTx) + 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] = 0x1a + } + if len(x.OutboundId) > 0 { + i -= len(x.OutboundId) + copy(dAtA[i:], x.OutboundId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.OutboundId))) + i-- + dAtA[i] = 0x12 + } + if len(x.UtxId) > 0 { + i -= len(x.UtxId) + copy(dAtA[i:], x.UtxId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.UtxId))) + i-- + dAtA[i] = 0xa + } + 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().(*QueryOutboundBallotKeyRequest) + 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: QueryOutboundBallotKeyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryOutboundBallotKeyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field UtxId", 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.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field OutboundId", 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.OutboundId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ObservedTx", wireType) + } + var msglen int + 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++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + 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 + } + if x.ObservedTx == nil { + x.ObservedTx = &OutboundObservation{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.ObservedTx); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + 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, + } +} + +var ( + md_QueryOutboundBallotKeyResponse protoreflect.MessageDescriptor + fd_QueryOutboundBallotKeyResponse_ballot_id protoreflect.FieldDescriptor + fd_QueryOutboundBallotKeyResponse_canonical_observed_tx protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryOutboundBallotKeyResponse = File_uexecutor_v1_query_proto.Messages().ByName("QueryOutboundBallotKeyResponse") + fd_QueryOutboundBallotKeyResponse_ballot_id = md_QueryOutboundBallotKeyResponse.Fields().ByName("ballot_id") + fd_QueryOutboundBallotKeyResponse_canonical_observed_tx = md_QueryOutboundBallotKeyResponse.Fields().ByName("canonical_observed_tx") +} + +var _ protoreflect.Message = (*fastReflection_QueryOutboundBallotKeyResponse)(nil) + +type fastReflection_QueryOutboundBallotKeyResponse QueryOutboundBallotKeyResponse + +func (x *QueryOutboundBallotKeyResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyResponse)(x) +} + +func (x *QueryOutboundBallotKeyResponse) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[26] + 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_QueryOutboundBallotKeyResponse_messageType fastReflection_QueryOutboundBallotKeyResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryOutboundBallotKeyResponse_messageType{} + +type fastReflection_QueryOutboundBallotKeyResponse_messageType struct{} + +func (x fastReflection_QueryOutboundBallotKeyResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyResponse)(nil) +} +func (x fastReflection_QueryOutboundBallotKeyResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyResponse) +} +func (x fastReflection_QueryOutboundBallotKeyResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyResponse +} + +// 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_QueryOutboundBallotKeyResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryOutboundBallotKeyResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryOutboundBallotKeyResponse) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Interface() protoreflect.ProtoMessage { + return (*QueryOutboundBallotKeyResponse)(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_QueryOutboundBallotKeyResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.BallotId != "" { + value := protoreflect.ValueOfString(x.BallotId) + if !f(fd_QueryOutboundBallotKeyResponse_ballot_id, value) { + return + } + } + if x.CanonicalObservedTx != nil { + value := protoreflect.ValueOfMessage(x.CanonicalObservedTx.ProtoReflect()) + if !f(fd_QueryOutboundBallotKeyResponse_canonical_observed_tx, 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_QueryOutboundBallotKeyResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + return x.BallotId != "" + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + return x.CanonicalObservedTx != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse 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_QueryOutboundBallotKeyResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + x.BallotId = "" + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + x.CanonicalObservedTx = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse 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_QueryOutboundBallotKeyResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + value := x.BallotId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + value := x.CanonicalObservedTx + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse 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_QueryOutboundBallotKeyResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + x.BallotId = value.Interface().(string) + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + x.CanonicalObservedTx = value.Message().Interface().(*OutboundObservation) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse 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_QueryOutboundBallotKeyResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + if x.CanonicalObservedTx == nil { + x.CanonicalObservedTx = new(OutboundObservation) + } + return protoreflect.ValueOfMessage(x.CanonicalObservedTx.ProtoReflect()) + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + panic(fmt.Errorf("field ballot_id of message uexecutor.v1.QueryOutboundBallotKeyResponse is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse 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_QueryOutboundBallotKeyResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + m := new(OutboundObservation) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse 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_QueryOutboundBallotKeyResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryOutboundBallotKeyResponse", 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_QueryOutboundBallotKeyResponse) 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_QueryOutboundBallotKeyResponse) 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_QueryOutboundBallotKeyResponse) 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_QueryOutboundBallotKeyResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryOutboundBallotKeyResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.BallotId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.CanonicalObservedTx != nil { + l = options.Size(x.CanonicalObservedTx) + 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().(*QueryOutboundBallotKeyResponse) + 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 x.CanonicalObservedTx != nil { + encoded, err := options.Marshal(x.CanonicalObservedTx) + 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] = 0x12 + } + if len(x.BallotId) > 0 { + i -= len(x.BallotId) + copy(dAtA[i:], x.BallotId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.BallotId))) + i-- + dAtA[i] = 0xa + } + 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().(*QueryOutboundBallotKeyResponse) + 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: QueryOutboundBallotKeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryOutboundBallotKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field BallotId", 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.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field CanonicalObservedTx", wireType) + } + var msglen int + 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++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + 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 + } + if x.CanonicalObservedTx == nil { + x.CanonicalObservedTx = &OutboundObservation{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.CanonicalObservedTx); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + 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, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -12133,6 +14193,188 @@ func (x *QueryAllPendingOutboundsResponse) GetPagination() *v1beta1.PageResponse return nil } +// InboundKeys: derive canonical UTX id + inbound ballot id from an inbound. +type QueryInboundKeysRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Inbound *Inbound `protobuf:"bytes,1,opt,name=inbound,proto3" json:"inbound,omitempty"` +} + +func (x *QueryInboundKeysRequest) Reset() { + *x = QueryInboundKeysRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryInboundKeysRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryInboundKeysRequest) ProtoMessage() {} + +// Deprecated: Use QueryInboundKeysRequest.ProtoReflect.Descriptor instead. +func (*QueryInboundKeysRequest) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{23} +} + +func (x *QueryInboundKeysRequest) GetInbound() *Inbound { + if x != nil { + return x.Inbound + } + return nil +} + +type QueryInboundKeysResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` // canonical UniversalTx key + BallotId string `protobuf:"bytes,2,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` // canonical inbound ballot key + CanonicalInbound *Inbound `protobuf:"bytes,3,opt,name=canonical_inbound,json=canonicalInbound,proto3" json:"canonical_inbound,omitempty"` // the canonicalized inbound the chain derived the keys from +} + +func (x *QueryInboundKeysResponse) Reset() { + *x = QueryInboundKeysResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryInboundKeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryInboundKeysResponse) ProtoMessage() {} + +// Deprecated: Use QueryInboundKeysResponse.ProtoReflect.Descriptor instead. +func (*QueryInboundKeysResponse) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{24} +} + +func (x *QueryInboundKeysResponse) GetUtxId() string { + if x != nil { + return x.UtxId + } + return "" +} + +func (x *QueryInboundKeysResponse) GetBallotId() string { + if x != nil { + return x.BallotId + } + return "" +} + +func (x *QueryInboundKeysResponse) GetCanonicalInbound() *Inbound { + if x != nil { + return x.CanonicalInbound + } + return nil +} + +// OutboundBallotKey: derive the canonical outbound ballot id for an observation. +type QueryOutboundBallotKeyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` // UniversalTx the outbound belongs to + OutboundId string `protobuf:"bytes,2,opt,name=outbound_id,json=outboundId,proto3" json:"outbound_id,omitempty"` // outbound being observed + ObservedTx *OutboundObservation `protobuf:"bytes,3,opt,name=observed_tx,json=observedTx,proto3" json:"observed_tx,omitempty"` // the observation being voted +} + +func (x *QueryOutboundBallotKeyRequest) Reset() { + *x = QueryOutboundBallotKeyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryOutboundBallotKeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryOutboundBallotKeyRequest) ProtoMessage() {} + +// Deprecated: Use QueryOutboundBallotKeyRequest.ProtoReflect.Descriptor instead. +func (*QueryOutboundBallotKeyRequest) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{25} +} + +func (x *QueryOutboundBallotKeyRequest) GetUtxId() string { + if x != nil { + return x.UtxId + } + return "" +} + +func (x *QueryOutboundBallotKeyRequest) GetOutboundId() string { + if x != nil { + return x.OutboundId + } + return "" +} + +func (x *QueryOutboundBallotKeyRequest) GetObservedTx() *OutboundObservation { + if x != nil { + return x.ObservedTx + } + return nil +} + +type QueryOutboundBallotKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BallotId string `protobuf:"bytes,1,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` // canonical outbound ballot key + CanonicalObservedTx *OutboundObservation `protobuf:"bytes,2,opt,name=canonical_observed_tx,json=canonicalObservedTx,proto3" json:"canonical_observed_tx,omitempty"` // observation after canonicalization +} + +func (x *QueryOutboundBallotKeyResponse) Reset() { + *x = QueryOutboundBallotKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryOutboundBallotKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryOutboundBallotKeyResponse) ProtoMessage() {} + +// Deprecated: Use QueryOutboundBallotKeyResponse.ProtoReflect.Descriptor instead. +func (*QueryOutboundBallotKeyResponse) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{26} +} + +func (x *QueryOutboundBallotKeyResponse) GetBallotId() string { + if x != nil { + return x.BallotId + } + return "" +} + +func (x *QueryOutboundBallotKeyResponse) GetCanonicalObservedTx() *OutboundObservation { + if x != nil { + return x.CanonicalObservedTx + } + return nil +} + var File_uexecutor_v1_query_proto protoreflect.FileDescriptor var file_uexecutor_v1_query_proto_rawDesc = []byte{ @@ -12317,117 +14559,169 @@ var file_uexecutor_v1_query_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, - 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xa8, 0x0c, 0x0a, 0x05, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x12, 0x6b, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x20, 0x2e, 0x75, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4a, 0x0a, 0x17, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x07, 0x69, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x92, 0x01, 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x15, 0x0a, 0x06, 0x75, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x75, 0x74, 0x78, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x6c, 0x6c, + 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x6c, + 0x6c, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x11, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, + 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x10, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, + 0x61, 0x6c, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x9b, 0x01, 0x0a, 0x1d, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, 0x6f, + 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x75, + 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x75, 0x74, 0x78, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, + 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x62, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x78, 0x22, 0x94, 0x01, 0x0a, 0x1e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, + 0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, + 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x55, 0x0a, 0x15, 0x63, 0x61, 0x6e, 0x6f, 0x6e, + 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x74, 0x78, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4f, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x63, 0x61, 0x6e, 0x6f, 0x6e, + 0x69, 0x63, 0x61, 0x6c, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x78, 0x32, 0xcd, + 0x0e, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x6b, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x12, 0x20, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, + 0x14, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, - 0x99, 0x01, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x0e, - 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x12, 0x28, + 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, + 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, + 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x6c, 0x54, 0x78, 0x12, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, - 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, - 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8a, 0x01, - 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, - 0x12, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x22, 0x12, 0x20, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, + 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0x8a, 0x01, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x12, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x55, 0x6e, + 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x6c, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, - 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, - 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x6e, 0x69, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, 0x12, 0x7f, 0x0a, 0x08, 0x47, 0x61, - 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x75, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, - 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, - 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x0c, - 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x75, + 0x6c, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, + 0x76, 0x31, 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, + 0x12, 0x7f, 0x0a, 0x08, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, - 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x73, 0x12, - 0x83, 0x01, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x23, 0x2e, + 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x23, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, + 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, + 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x0c, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, + 0x65, 0x73, 0x12, 0x26, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, + 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x75, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x70, + 0x72, 0x69, 0x63, 0x65, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, + 0x65, 0x74, 0x61, 0x12, 0x23, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, + 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0d, + 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x12, 0x27, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, - 0x12, 0x23, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0d, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x12, 0x27, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, - 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, - 0x31, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x73, 0x12, 0xa7, 0x01, - 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x73, 0x12, 0xa7, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, + 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, + 0x2c, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, + 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2f, + 0x7b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, + 0x0a, 0x13, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x75, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x99, 0x01, + 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x6f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, 0x0a, 0x13, 0x41, 0x6c, 0x6c, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, - 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, - 0x76, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x73, 0x42, 0xb2, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x73, 0x68, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x70, 0x75, 0x73, - 0x68, 0x2d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x55, 0x58, 0x58, 0xaa, - 0x02, 0x0c, 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x0c, 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, - 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x55, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, + 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x0b, 0x49, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x25, 0x2e, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, + 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, + 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x12, + 0x9c, 0x01, 0x0a, 0x11, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, + 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x2b, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, + 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x75, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0xb2, + 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, + 0x73, 0x68, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x70, 0x75, 0x73, 0x68, 0x2d, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x55, 0x58, 0x58, 0xaa, 0x02, 0x0c, 0x55, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x55, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x55, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x3a, + 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -12442,7 +14736,7 @@ func file_uexecutor_v1_query_proto_rawDescGZIP() []byte { return file_uexecutor_v1_query_proto_rawDescData } -var file_uexecutor_v1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_uexecutor_v1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_uexecutor_v1_query_proto_goTypes = []interface{}{ (*QueryGasPriceRequest)(nil), // 0: uexecutor.v1.QueryGasPriceRequest (*QueryGasPriceResponse)(nil), // 1: uexecutor.v1.QueryGasPriceResponse @@ -12467,72 +14761,86 @@ var file_uexecutor_v1_query_proto_goTypes = []interface{}{ (*QueryGetPendingOutboundResponse)(nil), // 20: uexecutor.v1.QueryGetPendingOutboundResponse (*QueryAllPendingOutboundsRequest)(nil), // 21: uexecutor.v1.QueryAllPendingOutboundsRequest (*QueryAllPendingOutboundsResponse)(nil), // 22: uexecutor.v1.QueryAllPendingOutboundsResponse - (*GasPrice)(nil), // 23: uexecutor.v1.GasPrice - (*v1beta1.PageRequest)(nil), // 24: cosmos.base.query.v1beta1.PageRequest - (*v1beta1.PageResponse)(nil), // 25: cosmos.base.query.v1beta1.PageResponse - (*ChainMeta)(nil), // 26: uexecutor.v1.ChainMeta - (*Params)(nil), // 27: uexecutor.v1.Params - (*PendingInboundEntry)(nil), // 28: uexecutor.v1.PendingInboundEntry - (*ExpiredInboundEntry)(nil), // 29: uexecutor.v1.ExpiredInboundEntry - (*UniversalTxLegacy)(nil), // 30: uexecutor.v1.UniversalTxLegacy - (*UniversalTx)(nil), // 31: uexecutor.v1.UniversalTx - (*OutboundObservationVariant)(nil), // 32: uexecutor.v1.OutboundObservationVariant - (*OutboundTx)(nil), // 33: uexecutor.v1.OutboundTx + (*QueryInboundKeysRequest)(nil), // 23: uexecutor.v1.QueryInboundKeysRequest + (*QueryInboundKeysResponse)(nil), // 24: uexecutor.v1.QueryInboundKeysResponse + (*QueryOutboundBallotKeyRequest)(nil), // 25: uexecutor.v1.QueryOutboundBallotKeyRequest + (*QueryOutboundBallotKeyResponse)(nil), // 26: uexecutor.v1.QueryOutboundBallotKeyResponse + (*GasPrice)(nil), // 27: uexecutor.v1.GasPrice + (*v1beta1.PageRequest)(nil), // 28: cosmos.base.query.v1beta1.PageRequest + (*v1beta1.PageResponse)(nil), // 29: cosmos.base.query.v1beta1.PageResponse + (*ChainMeta)(nil), // 30: uexecutor.v1.ChainMeta + (*Params)(nil), // 31: uexecutor.v1.Params + (*PendingInboundEntry)(nil), // 32: uexecutor.v1.PendingInboundEntry + (*ExpiredInboundEntry)(nil), // 33: uexecutor.v1.ExpiredInboundEntry + (*UniversalTxLegacy)(nil), // 34: uexecutor.v1.UniversalTxLegacy + (*UniversalTx)(nil), // 35: uexecutor.v1.UniversalTx + (*OutboundObservationVariant)(nil), // 36: uexecutor.v1.OutboundObservationVariant + (*OutboundTx)(nil), // 37: uexecutor.v1.OutboundTx + (*Inbound)(nil), // 38: uexecutor.v1.Inbound + (*OutboundObservation)(nil), // 39: uexecutor.v1.OutboundObservation } var file_uexecutor_v1_query_proto_depIdxs = []int32{ - 23, // 0: uexecutor.v1.QueryGasPriceResponse.gas_price:type_name -> uexecutor.v1.GasPrice - 24, // 1: uexecutor.v1.QueryAllGasPricesRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 23, // 2: uexecutor.v1.QueryAllGasPricesResponse.gas_prices:type_name -> uexecutor.v1.GasPrice - 25, // 3: uexecutor.v1.QueryAllGasPricesResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 26, // 4: uexecutor.v1.QueryChainMetaResponse.chain_meta:type_name -> uexecutor.v1.ChainMeta - 24, // 5: uexecutor.v1.QueryAllChainMetasRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 26, // 6: uexecutor.v1.QueryAllChainMetasResponse.chain_metas:type_name -> uexecutor.v1.ChainMeta - 25, // 7: uexecutor.v1.QueryAllChainMetasResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 27, // 8: uexecutor.v1.QueryParamsResponse.params:type_name -> uexecutor.v1.Params - 24, // 9: uexecutor.v1.QueryAllPendingInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 28, // 10: uexecutor.v1.QueryAllPendingInboundsResponse.entries:type_name -> uexecutor.v1.PendingInboundEntry - 25, // 11: uexecutor.v1.QueryAllPendingInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 24, // 12: uexecutor.v1.QueryAllExpiredInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 29, // 13: uexecutor.v1.QueryAllExpiredInboundsResponse.entries:type_name -> uexecutor.v1.ExpiredInboundEntry - 25, // 14: uexecutor.v1.QueryAllExpiredInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 30, // 15: uexecutor.v1.QueryGetUniversalTxResponse.universal_tx:type_name -> uexecutor.v1.UniversalTxLegacy - 24, // 16: uexecutor.v1.QueryAllUniversalTxRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 31, // 17: uexecutor.v1.QueryAllUniversalTxResponse.universal_txs:type_name -> uexecutor.v1.UniversalTx - 25, // 18: uexecutor.v1.QueryAllUniversalTxResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 32, // 19: uexecutor.v1.PendingOutboundEntry.variants:type_name -> uexecutor.v1.OutboundObservationVariant + 27, // 0: uexecutor.v1.QueryGasPriceResponse.gas_price:type_name -> uexecutor.v1.GasPrice + 28, // 1: uexecutor.v1.QueryAllGasPricesRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 27, // 2: uexecutor.v1.QueryAllGasPricesResponse.gas_prices:type_name -> uexecutor.v1.GasPrice + 29, // 3: uexecutor.v1.QueryAllGasPricesResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 30, // 4: uexecutor.v1.QueryChainMetaResponse.chain_meta:type_name -> uexecutor.v1.ChainMeta + 28, // 5: uexecutor.v1.QueryAllChainMetasRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 30, // 6: uexecutor.v1.QueryAllChainMetasResponse.chain_metas:type_name -> uexecutor.v1.ChainMeta + 29, // 7: uexecutor.v1.QueryAllChainMetasResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 31, // 8: uexecutor.v1.QueryParamsResponse.params:type_name -> uexecutor.v1.Params + 28, // 9: uexecutor.v1.QueryAllPendingInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 32, // 10: uexecutor.v1.QueryAllPendingInboundsResponse.entries:type_name -> uexecutor.v1.PendingInboundEntry + 29, // 11: uexecutor.v1.QueryAllPendingInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 28, // 12: uexecutor.v1.QueryAllExpiredInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 33, // 13: uexecutor.v1.QueryAllExpiredInboundsResponse.entries:type_name -> uexecutor.v1.ExpiredInboundEntry + 29, // 14: uexecutor.v1.QueryAllExpiredInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 34, // 15: uexecutor.v1.QueryGetUniversalTxResponse.universal_tx:type_name -> uexecutor.v1.UniversalTxLegacy + 28, // 16: uexecutor.v1.QueryAllUniversalTxRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 35, // 17: uexecutor.v1.QueryAllUniversalTxResponse.universal_txs:type_name -> uexecutor.v1.UniversalTx + 29, // 18: uexecutor.v1.QueryAllUniversalTxResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 36, // 19: uexecutor.v1.PendingOutboundEntry.variants:type_name -> uexecutor.v1.OutboundObservationVariant 18, // 20: uexecutor.v1.QueryGetPendingOutboundResponse.entry:type_name -> uexecutor.v1.PendingOutboundEntry - 33, // 21: uexecutor.v1.QueryGetPendingOutboundResponse.outbound:type_name -> uexecutor.v1.OutboundTx - 24, // 22: uexecutor.v1.QueryAllPendingOutboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 37, // 21: uexecutor.v1.QueryGetPendingOutboundResponse.outbound:type_name -> uexecutor.v1.OutboundTx + 28, // 22: uexecutor.v1.QueryAllPendingOutboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest 18, // 23: uexecutor.v1.QueryAllPendingOutboundsResponse.entries:type_name -> uexecutor.v1.PendingOutboundEntry - 33, // 24: uexecutor.v1.QueryAllPendingOutboundsResponse.outbounds:type_name -> uexecutor.v1.OutboundTx - 25, // 25: uexecutor.v1.QueryAllPendingOutboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 8, // 26: uexecutor.v1.Query.Params:input_type -> uexecutor.v1.QueryParamsRequest - 10, // 27: uexecutor.v1.Query.AllPendingInbounds:input_type -> uexecutor.v1.QueryAllPendingInboundsRequest - 14, // 28: uexecutor.v1.Query.GetUniversalTx:input_type -> uexecutor.v1.QueryGetUniversalTxRequest - 16, // 29: uexecutor.v1.Query.AllUniversalTx:input_type -> uexecutor.v1.QueryAllUniversalTxRequest - 0, // 30: uexecutor.v1.Query.GasPrice:input_type -> uexecutor.v1.QueryGasPriceRequest - 2, // 31: uexecutor.v1.Query.AllGasPrices:input_type -> uexecutor.v1.QueryAllGasPricesRequest - 4, // 32: uexecutor.v1.Query.ChainMeta:input_type -> uexecutor.v1.QueryChainMetaRequest - 6, // 33: uexecutor.v1.Query.AllChainMetas:input_type -> uexecutor.v1.QueryAllChainMetasRequest - 19, // 34: uexecutor.v1.Query.GetPendingOutbound:input_type -> uexecutor.v1.QueryGetPendingOutboundRequest - 21, // 35: uexecutor.v1.Query.AllPendingOutbounds:input_type -> uexecutor.v1.QueryAllPendingOutboundsRequest - 12, // 36: uexecutor.v1.Query.AllExpiredInbounds:input_type -> uexecutor.v1.QueryAllExpiredInboundsRequest - 9, // 37: uexecutor.v1.Query.Params:output_type -> uexecutor.v1.QueryParamsResponse - 11, // 38: uexecutor.v1.Query.AllPendingInbounds:output_type -> uexecutor.v1.QueryAllPendingInboundsResponse - 15, // 39: uexecutor.v1.Query.GetUniversalTx:output_type -> uexecutor.v1.QueryGetUniversalTxResponse - 17, // 40: uexecutor.v1.Query.AllUniversalTx:output_type -> uexecutor.v1.QueryAllUniversalTxResponse - 1, // 41: uexecutor.v1.Query.GasPrice:output_type -> uexecutor.v1.QueryGasPriceResponse - 3, // 42: uexecutor.v1.Query.AllGasPrices:output_type -> uexecutor.v1.QueryAllGasPricesResponse - 5, // 43: uexecutor.v1.Query.ChainMeta:output_type -> uexecutor.v1.QueryChainMetaResponse - 7, // 44: uexecutor.v1.Query.AllChainMetas:output_type -> uexecutor.v1.QueryAllChainMetasResponse - 20, // 45: uexecutor.v1.Query.GetPendingOutbound:output_type -> uexecutor.v1.QueryGetPendingOutboundResponse - 22, // 46: uexecutor.v1.Query.AllPendingOutbounds:output_type -> uexecutor.v1.QueryAllPendingOutboundsResponse - 13, // 47: uexecutor.v1.Query.AllExpiredInbounds:output_type -> uexecutor.v1.QueryAllExpiredInboundsResponse - 37, // [37:48] is the sub-list for method output_type - 26, // [26:37] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 37, // 24: uexecutor.v1.QueryAllPendingOutboundsResponse.outbounds:type_name -> uexecutor.v1.OutboundTx + 29, // 25: uexecutor.v1.QueryAllPendingOutboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 38, // 26: uexecutor.v1.QueryInboundKeysRequest.inbound:type_name -> uexecutor.v1.Inbound + 38, // 27: uexecutor.v1.QueryInboundKeysResponse.canonical_inbound:type_name -> uexecutor.v1.Inbound + 39, // 28: uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx:type_name -> uexecutor.v1.OutboundObservation + 39, // 29: uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx:type_name -> uexecutor.v1.OutboundObservation + 8, // 30: uexecutor.v1.Query.Params:input_type -> uexecutor.v1.QueryParamsRequest + 10, // 31: uexecutor.v1.Query.AllPendingInbounds:input_type -> uexecutor.v1.QueryAllPendingInboundsRequest + 14, // 32: uexecutor.v1.Query.GetUniversalTx:input_type -> uexecutor.v1.QueryGetUniversalTxRequest + 16, // 33: uexecutor.v1.Query.AllUniversalTx:input_type -> uexecutor.v1.QueryAllUniversalTxRequest + 0, // 34: uexecutor.v1.Query.GasPrice:input_type -> uexecutor.v1.QueryGasPriceRequest + 2, // 35: uexecutor.v1.Query.AllGasPrices:input_type -> uexecutor.v1.QueryAllGasPricesRequest + 4, // 36: uexecutor.v1.Query.ChainMeta:input_type -> uexecutor.v1.QueryChainMetaRequest + 6, // 37: uexecutor.v1.Query.AllChainMetas:input_type -> uexecutor.v1.QueryAllChainMetasRequest + 19, // 38: uexecutor.v1.Query.GetPendingOutbound:input_type -> uexecutor.v1.QueryGetPendingOutboundRequest + 21, // 39: uexecutor.v1.Query.AllPendingOutbounds:input_type -> uexecutor.v1.QueryAllPendingOutboundsRequest + 12, // 40: uexecutor.v1.Query.AllExpiredInbounds:input_type -> uexecutor.v1.QueryAllExpiredInboundsRequest + 23, // 41: uexecutor.v1.Query.InboundKeys:input_type -> uexecutor.v1.QueryInboundKeysRequest + 25, // 42: uexecutor.v1.Query.OutboundBallotKey:input_type -> uexecutor.v1.QueryOutboundBallotKeyRequest + 9, // 43: uexecutor.v1.Query.Params:output_type -> uexecutor.v1.QueryParamsResponse + 11, // 44: uexecutor.v1.Query.AllPendingInbounds:output_type -> uexecutor.v1.QueryAllPendingInboundsResponse + 15, // 45: uexecutor.v1.Query.GetUniversalTx:output_type -> uexecutor.v1.QueryGetUniversalTxResponse + 17, // 46: uexecutor.v1.Query.AllUniversalTx:output_type -> uexecutor.v1.QueryAllUniversalTxResponse + 1, // 47: uexecutor.v1.Query.GasPrice:output_type -> uexecutor.v1.QueryGasPriceResponse + 3, // 48: uexecutor.v1.Query.AllGasPrices:output_type -> uexecutor.v1.QueryAllGasPricesResponse + 5, // 49: uexecutor.v1.Query.ChainMeta:output_type -> uexecutor.v1.QueryChainMetaResponse + 7, // 50: uexecutor.v1.Query.AllChainMetas:output_type -> uexecutor.v1.QueryAllChainMetasResponse + 20, // 51: uexecutor.v1.Query.GetPendingOutbound:output_type -> uexecutor.v1.QueryGetPendingOutboundResponse + 22, // 52: uexecutor.v1.Query.AllPendingOutbounds:output_type -> uexecutor.v1.QueryAllPendingOutboundsResponse + 13, // 53: uexecutor.v1.Query.AllExpiredInbounds:output_type -> uexecutor.v1.QueryAllExpiredInboundsResponse + 24, // 54: uexecutor.v1.Query.InboundKeys:output_type -> uexecutor.v1.QueryInboundKeysResponse + 26, // 55: uexecutor.v1.Query.OutboundBallotKey:output_type -> uexecutor.v1.QueryOutboundBallotKeyResponse + 43, // [43:56] is the sub-list for method output_type + 30, // [30:43] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_uexecutor_v1_query_proto_init() } @@ -12821,6 +15129,54 @@ func file_uexecutor_v1_query_proto_init() { return nil } } + file_uexecutor_v1_query_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryInboundKeysRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_uexecutor_v1_query_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryInboundKeysResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_uexecutor_v1_query_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryOutboundBallotKeyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_uexecutor_v1_query_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryOutboundBallotKeyResponse); 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{ @@ -12828,7 +15184,7 @@ func file_uexecutor_v1_query_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_uexecutor_v1_query_proto_rawDesc, NumEnums: 0, - NumMessages: 23, + NumMessages: 27, NumExtensions: 0, NumServices: 1, }, diff --git a/api/uexecutor/v1/query_grpc.pb.go b/api/uexecutor/v1/query_grpc.pb.go index 0247c9fde..430ab0a9c 100644 --- a/api/uexecutor/v1/query_grpc.pb.go +++ b/api/uexecutor/v1/query_grpc.pb.go @@ -30,6 +30,8 @@ const ( Query_GetPendingOutbound_FullMethodName = "/uexecutor.v1.Query/GetPendingOutbound" Query_AllPendingOutbounds_FullMethodName = "/uexecutor.v1.Query/AllPendingOutbounds" Query_AllExpiredInbounds_FullMethodName = "/uexecutor.v1.Query/AllExpiredInbounds" + Query_InboundKeys_FullMethodName = "/uexecutor.v1.Query/InboundKeys" + Query_OutboundBallotKey_FullMethodName = "/uexecutor.v1.Query/OutboundBallotKey" ) // QueryClient is the client API for Query service. @@ -60,6 +62,14 @@ type QueryClient interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(ctx context.Context, in *QueryAllExpiredInboundsRequest, opts ...grpc.CallOption) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) } type queryClient struct { @@ -169,6 +179,24 @@ func (c *queryClient) AllExpiredInbounds(ctx context.Context, in *QueryAllExpire return out, nil } +func (c *queryClient) InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) { + out := new(QueryInboundKeysResponse) + err := c.cc.Invoke(ctx, Query_InboundKeys_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) { + out := new(QueryOutboundBallotKeyResponse) + err := c.cc.Invoke(ctx, Query_OutboundBallotKey_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. // All implementations must embed UnimplementedQueryServer // for forward compatibility @@ -197,6 +225,14 @@ type QueryServer interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(context.Context, *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(context.Context, *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(context.Context, *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) mustEmbedUnimplementedQueryServer() } @@ -237,6 +273,12 @@ func (UnimplementedQueryServer) AllPendingOutbounds(context.Context, *QueryAllPe func (UnimplementedQueryServer) AllExpiredInbounds(context.Context, *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllExpiredInbounds not implemented") } +func (UnimplementedQueryServer) InboundKeys(context.Context, *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InboundKeys not implemented") +} +func (UnimplementedQueryServer) OutboundBallotKey(context.Context, *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method OutboundBallotKey not implemented") +} func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} // UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. @@ -448,6 +490,42 @@ func _Query_AllExpiredInbounds_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Query_InboundKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryInboundKeysRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).InboundKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Query_InboundKeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).InboundKeys(ctx, req.(*QueryInboundKeysRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_OutboundBallotKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryOutboundBallotKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).OutboundBallotKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Query_OutboundBallotKey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).OutboundBallotKey(ctx, req.(*QueryOutboundBallotKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Query_ServiceDesc is the grpc.ServiceDesc for Query service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -499,6 +577,14 @@ var Query_ServiceDesc = grpc.ServiceDesc{ MethodName: "AllExpiredInbounds", Handler: _Query_AllExpiredInbounds_Handler, }, + { + MethodName: "InboundKeys", + Handler: _Query_InboundKeys_Handler, + }, + { + MethodName: "OutboundBallotKey", + Handler: _Query_OutboundBallotKey_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/query.proto", diff --git a/proto/uexecutor/v1/query.proto b/proto/uexecutor/v1/query.proto index 753204ac0..555d870ad 100755 --- a/proto/uexecutor/v1/query.proto +++ b/proto/uexecutor/v1/query.proto @@ -69,6 +69,22 @@ service Query { rpc AllExpiredInbounds(QueryAllExpiredInboundsRequest) returns (QueryAllExpiredInboundsResponse) { option (google.api.http).get = "/uexecutor/v1/expired_inbounds"; } + + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + rpc InboundKeys(QueryInboundKeysRequest) returns (QueryInboundKeysResponse) { + option (google.api.http).post = "/uexecutor/v1/inbound_keys"; + option (google.api.http).body = "*"; + } + + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + rpc OutboundBallotKey(QueryOutboundBallotKeyRequest) returns (QueryOutboundBallotKeyResponse) { + option (google.api.http).post = "/uexecutor/v1/outbound_ballot_key"; + option (google.api.http).body = "*"; + } } // ========================== @@ -195,3 +211,26 @@ message QueryAllPendingOutboundsResponse { repeated OutboundTx outbounds = 2; cosmos.base.query.v1beta1.PageResponse pagination = 3; } + +// InboundKeys: derive canonical UTX id + inbound ballot id from an inbound. +message QueryInboundKeysRequest { + Inbound inbound = 1; +} + +message QueryInboundKeysResponse { + string utx_id = 1; // canonical UniversalTx key + string ballot_id = 2; // canonical inbound ballot key + Inbound canonical_inbound = 3; // the canonicalized inbound the chain derived the keys from +} + +// OutboundBallotKey: derive the canonical outbound ballot id for an observation. +message QueryOutboundBallotKeyRequest { + string utx_id = 1; // UniversalTx the outbound belongs to + string outbound_id = 2; // outbound being observed + OutboundObservation observed_tx = 3; // the observation being voted +} + +message QueryOutboundBallotKeyResponse { + string ballot_id = 1; // canonical outbound ballot key + OutboundObservation canonical_observed_tx = 2; // observation after canonicalization +} diff --git a/test/integration/uexecutor/execute_inbound_gas_test.go b/test/integration/uexecutor/execute_inbound_gas_test.go index 67b82107d..b01de0073 100644 --- a/test/integration/uexecutor/execute_inbound_gas_test.go +++ b/test/integration/uexecutor/execute_inbound_gas_test.go @@ -11,6 +11,7 @@ import ( "github.com/pushchain/push-chain-node/app" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" uregistrytypes "github.com/pushchain/push-chain-node/x/uregistry/types" uvalidatortypes "github.com/pushchain/push-chain-node/x/uvalidator/types" @@ -348,7 +349,9 @@ func TestInboundGas(t *testing.T) { for _, ob := range utx.OutboundTx { if ob.TxType == uexecutortypes.TxType_INBOUND_REVERT { - require.Equal(t, inbound.Sender, ob.Recipient, + // Stored inbound fields are canonicalized at vote ingress, so the + // fallback recipient is the EIP-55 form of the sender. + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), ob.Recipient, "revert outbound recipient should fall back to Sender when RevertInstructions is nil") return } diff --git a/test/integration/uexecutor/inbound_ballot_convergence_test.go b/test/integration/uexecutor/inbound_ballot_convergence_test.go new file mode 100644 index 000000000..12a27633a --- /dev/null +++ b/test/integration/uexecutor/inbound_ballot_convergence_test.go @@ -0,0 +1,180 @@ +package integrationtest + +import ( + "strings" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + utils "github.com/pushchain/push-chain-node/test/utils" + uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" + uvalidatortypes "github.com/pushchain/push-chain-node/x/uvalidator/types" +) + +// Ballot-convergence regression: validators observing the SAME bridge event +// but submitting different string encodings (EIP-55 vs lowercase vs +// 0X-uppercase) must aggregate on ONE ballot and finalize. Pre-fix, the +// ballot key hashed the full proto encoding, so each encoding variant +// produced its own ballot and quorum never formed. +func TestVoteInbound_EncodingVariantsConvergeOnOneBallot(t *testing.T) { + app, ctx, vals, baseInbound, coreVals := setupInboundBridgeTest(t, 4) + + // Same logical event in three different encodings. + const txLower = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + variants := make([]uexecutortypes.Inbound, 3) + for i := range variants { + v := *baseInbound + v.RevertInstructions = &uexecutortypes.RevertInstructions{ + FundRecipient: baseInbound.RevertInstructions.FundRecipient, + } + variants[i] = v + } + + // Voter 0: all lowercase. + variants[0].TxHash = txLower + variants[0].Sender = strings.ToLower(baseInbound.Sender) + variants[0].AssetAddr = strings.ToLower(baseInbound.AssetAddr) + variants[0].Recipient = strings.ToLower(baseInbound.Recipient) + variants[0].RevertInstructions.FundRecipient = strings.ToLower(baseInbound.RevertInstructions.FundRecipient) + + // Voter 1: as produced by the EVM client (EIP-55 mixed case). + variants[1].TxHash = "0xB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD" + + // Voter 2: 0X-uppercase everything. + variants[2].TxHash = "0X" + strings.ToUpper(txLower[2:]) + variants[2].Sender = "0X" + strings.ToUpper(baseInbound.Sender[2:]) + variants[2].AssetAddr = "0X" + strings.ToUpper(baseInbound.AssetAddr[2:]) + + // Vote with 3 of 4 validators (votesNeeded = (2*4)/3+1 = 3), each using a + // different encoding of the same event. + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + require.NoError(t, utils.ExecVoteInbound(t, ctx, app, vals[i], coreValAcc, &variants[i]), + "vote %d with encoding variant must be accepted", i) + + // Mid-flight (after the first two votes): the audit trail must show a + // SINGLE variant — both encodings recorded as the same observation. + if i == 1 { + utxKey := uexecutortypes.GetInboundUniversalTxKey(variants[0]) + entry, err := app.UexecutorKeeper.PendingInbounds.Get(ctx, utxKey) + require.NoError(t, err) + require.Len(t, entry.Variants, 1, + "different encodings of the same event must record as ONE variant, not fragment") + require.Len(t, entry.Variants[0].Voters, 2) + } + } + + // Quorum reached on the single converged ballot → inbound executed. + isPending, err := app.UexecutorKeeper.IsPendingInbound(ctx, variants[2]) + require.NoError(t, err) + require.False(t, isPending, "ballot must finalize — encodings converged on one ballot") + + // Exactly one UTX exists, under the canonical key, regardless of which + // encoding is used to derive it. + utxCount := 0 + require.NoError(t, app.UexecutorKeeper.UniversalTx.Walk(ctx, nil, func(_ string, _ uexecutortypes.UniversalTx) (bool, error) { + utxCount++ + return false, nil + })) + require.Equal(t, 1, utxCount, "one event must yield exactly one UniversalTx") + + for i, v := range variants { + utx, found, err := app.UexecutorKeeper.GetUniversalTx(ctx, uexecutortypes.GetInboundUniversalTxKey(v)) + require.NoError(t, err) + require.True(t, found, "variant %d must derive the canonical UTX key", i) + // Stored inbound carries canonical forms (EIP-55 addresses, lowercase hash). + require.Equal(t, txLower, utx.InboundTx.TxHash) + require.Equal(t, baseInbound.AssetAddr, utx.InboundTx.AssetAddr, + "stored asset address must be the canonical EIP-55 form") + } +} + +// Outbound twin of the convergence test: three validators observe the same +// destination-chain tx but submit the hash in different encodings. The +// canonical outbound digest must aggregate them on one ballot and finalize. +func TestVoteOutbound_EncodingVariantsConvergeOnOneBallot(t *testing.T) { + app, ctx, _, utxId, outbound, coreVals := setupOutboundVotingTest(t, 4) + + const destLower = "0x46cec75af4cb022d4f234e4d4b9b35e3aae66048007a06a7c1de6b9b76d27a39" + encodings := []string{ + destLower, // canonical lowercase + "0x46CEC75AF4CB022D4F234E4D4B9B35E3AAE66048007A06A7C1DE6B9B76D27A39", // uppercase body + "46cec75af4cb022d4f234e4d4b9b35e3aae66048007a06a7c1de6b9b76d27a39", // no prefix + } + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + + obs := uexecutortypes.OutboundObservation{ + Success: true, + BlockHeight: 42, + TxHash: encodings[i], + GasFeeUsed: outbound.GasFee, + } + require.NoError(t, app.UexecutorKeeper.VoteOutbound(ctx, valAddr, utxId, outbound.Id, obs), + "vote %d with encoding %q must be accepted", i, encodings[i]) + } + + // One ballot → quorum → outbound observed, with the canonical hash stored. + utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.Equal(t, uexecutortypes.Status_OBSERVED, utx.OutboundTx[0].OutboundStatus, + "equivalent encodings must aggregate on one ballot and finalize") + require.NotNil(t, utx.OutboundTx[0].ObservedTx) + require.Equal(t, destLower, utx.OutboundTx[0].ObservedTx.TxHash, + "stored observation must carry the canonical 0x-lowercase hash") +} + +// TestInboundBallotKey_StoreAndFetchAcrossEncodings demonstrates the full +// key lifecycle: derive a ballot key from one encoding of an event, store a +// ballot under it, then derive the key again from a DIFFERENT encoding of the +// same event and fetch the stored ballot back. This is what lets a second +// validator's differently-encoded vote find the first validator's ballot. +func TestInboundBallotKey_StoreAndFetchAcrossEncodings(t *testing.T) { + chainApp, ctx, _, baseInbound, _ := setupInboundBridgeTest(t, 1) + + // Encoding A: all lowercase. Derive the key and store a ballot under it. + a := *baseInbound + a.TxHash = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + a.Sender = strings.ToLower(baseInbound.Sender) + a.AssetAddr = strings.ToLower(baseInbound.AssetAddr) + + keyA, err := uexecutortypes.GetInboundBallotKey(a) + require.NoError(t, err) + t.Logf("derived ballot key (encoding A) = %s", keyA) + + stored := uvalidatortypes.Ballot{ + Id: keyA, + BallotType: uvalidatortypes.BallotObservationType_BALLOT_OBSERVATION_TYPE_INBOUND_TX, + EligibleVoters: []string{"cosmosvaloper1aaa"}, + Votes: []uvalidatortypes.VoteResult{uvalidatortypes.VoteResult_VOTE_RESULT_SUCCESS}, + VotingThreshold: 1, + Status: uvalidatortypes.BallotStatus_BALLOT_STATUS_PENDING, + BlockHeightCreated: ctx.BlockHeight(), + BlockHeightExpiry: ctx.BlockHeight() + 100, + } + require.NoError(t, chainApp.UvalidatorKeeper.SetBallot(ctx, stored)) + + // Encoding B: 0X-uppercase tx hash, EIP-55 addresses — same logical event. + b := *baseInbound + b.TxHash = "0X" + strings.ToUpper(a.TxHash[2:]) + b.Sender = baseInbound.Sender + b.AssetAddr = baseInbound.AssetAddr + + keyB, err := uexecutortypes.GetInboundBallotKey(b) + require.NoError(t, err) + t.Logf("derived ballot key (encoding B) = %s", keyB) + + require.Equal(t, keyA, keyB, "different encodings of the same event derive the same key") + + // Fetch the ballot stored under encoding A's key, using encoding B's key. + fetched, err := chainApp.UvalidatorKeeper.GetBallot(ctx, keyB) + require.NoError(t, err) + require.Equal(t, keyA, fetched.Id, "encoding B's key fetches the ballot stored under encoding A") + require.Equal(t, uvalidatortypes.BallotStatus_BALLOT_STATUS_PENDING, fetched.Status) +} diff --git a/test/integration/uexecutor/query_keys_test.go b/test/integration/uexecutor/query_keys_test.go new file mode 100644 index 000000000..a3512135a --- /dev/null +++ b/test/integration/uexecutor/query_keys_test.go @@ -0,0 +1,135 @@ +package integrationtest + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + uexecutorkeeper "github.com/pushchain/push-chain-node/x/uexecutor/keeper" + uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// The InboundKeys / OutboundBallotKey queries let off-chain validators read the +// canonical UTX id + ballot ids from the chain instead of re-implementing the +// canonicalization + digest rules. These tests exercise each query. + +func TestQueryInboundKeys_MatchesDerivation(t *testing.T) { + app, ctx, _, inbound, _ := setupInboundBridgeTest(t, 1) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + resp, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: inbound}) + require.NoError(t, err) + + // The returned keys must equal direct derivation from the canonical inbound. + canon := *inbound + canon.Canonicalize() + require.Equal(t, uexecutortypes.GetInboundUniversalTxKey(canon), resp.UtxId) + wantBallot, err := uexecutortypes.GetInboundBallotKey(canon) + require.NoError(t, err) + require.Equal(t, wantBallot, resp.BallotId) + + // Response echoes the canonical form the chain derived from. + require.NotNil(t, resp.CanonicalInbound) + require.Equal(t, canon.AssetAddr, resp.CanonicalInbound.AssetAddr) + require.Len(t, resp.UtxId, 64) + require.Len(t, resp.BallotId, 64) +} + +func TestQueryInboundKeys_EncodingVariantsAgree(t *testing.T) { + app, ctx, _, inbound, _ := setupInboundBridgeTest(t, 1) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + lower := *inbound + lower.AssetAddr = strings.ToLower(inbound.AssetAddr) + lower.Sender = strings.ToLower(inbound.Sender) + + upper := *inbound + upper.AssetAddr = "0X" + strings.ToUpper(strings.TrimPrefix(inbound.AssetAddr, "0x")) + + rl, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: &lower}) + require.NoError(t, err) + ru, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: &upper}) + require.NoError(t, err) + + require.Equal(t, rl.UtxId, ru.UtxId, "encoding variants must yield one UTX id") + require.Equal(t, rl.BallotId, ru.BallotId, "encoding variants must yield one ballot id") +} + +func TestQueryInboundKeys_NilRejected(t *testing.T) { + app, ctx, _, _, _ := setupInboundBridgeTest(t, 1) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + _, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: nil}) + require.Error(t, err) + require.Contains(t, err.Error(), "inbound is required") +} + +func TestQueryOutboundBallotKey_MatchesDerivation(t *testing.T) { + app, ctx, _, utxId, outbound, _ := setupOutboundVotingTest(t, 4) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + obs := &uexecutortypes.OutboundObservation{ + Success: true, + BlockHeight: 42, + TxHash: "0XB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD", // mixed/upper + GasFeeUsed: outbound.GasFee, + } + + resp, err := q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{ + UtxId: utxId, + OutboundId: outbound.Id, + ObservedTx: obs, + }) + require.NoError(t, err) + + // Equals derivation from the canonicalized observation (lowercased hash). + canonObs := *obs + canonObs.TxHash = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + want, err := uexecutortypes.GetOutboundBallotKey(utxId, outbound.Id, canonObs) + require.NoError(t, err) + require.Equal(t, want, resp.BallotId) + + require.NotNil(t, resp.CanonicalObservedTx) + require.Equal(t, canonObs.TxHash, resp.CanonicalObservedTx.TxHash, "query returns the canonical hash") + require.Len(t, resp.BallotId, 64) +} + +func TestQueryOutboundBallotKey_EncodingVariantsAgree(t *testing.T) { + app, ctx, _, utxId, outbound, _ := setupOutboundVotingTest(t, 4) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + mk := func(hash string) *uexecutortypes.QueryOutboundBallotKeyRequest { + return &uexecutortypes.QueryOutboundBallotKeyRequest{ + UtxId: utxId, OutboundId: outbound.Id, + ObservedTx: &uexecutortypes.OutboundObservation{Success: true, BlockHeight: 7, TxHash: hash, GasFeeUsed: "100"}, + } + } + a, err := q.OutboundBallotKey(ctx, mk("0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd")) + require.NoError(t, err) + b, err := q.OutboundBallotKey(ctx, mk("b28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd")) // no 0x + require.NoError(t, err) + require.Equal(t, a.BallotId, b.BallotId, "encoding variants must yield one outbound ballot id") +} + +func TestQueryOutboundBallotKey_Errors(t *testing.T) { + app, ctx, _, utxId, outbound, _ := setupOutboundVotingTest(t, 4) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + obs := &uexecutortypes.OutboundObservation{Success: true, BlockHeight: 1, TxHash: "0xaa", GasFeeUsed: "1"} + + // nil observation + _, err := q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{UtxId: utxId, OutboundId: outbound.Id}) + require.Error(t, err) + require.Contains(t, err.Error(), "observed_tx is required") + + // unknown utx + _, err = q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{UtxId: "does-not-exist", OutboundId: outbound.Id, ObservedTx: obs}) + require.Error(t, err) + require.Contains(t, err.Error(), "not found") + + // known utx, unknown outbound + _, err = q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{UtxId: utxId, OutboundId: "no-such-outbound", ObservedTx: obs}) + require.Error(t, err) + require.Contains(t, err.Error(), "not found") +} diff --git a/test/integration/uexecutor/query_v2_test.go b/test/integration/uexecutor/query_v2_test.go index 610925543..6fc447e53 100644 --- a/test/integration/uexecutor/query_v2_test.go +++ b/test/integration/uexecutor/query_v2_test.go @@ -9,6 +9,7 @@ import ( "google.golang.org/grpc/status" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutorkeeper "github.com/pushchain/push-chain-node/x/uexecutor/keeper" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" typesv2 "github.com/pushchain/push-chain-node/x/uexecutor/typesv2" @@ -65,7 +66,7 @@ func TestGetUniversalTxV2(t *testing.T) { require.NotNil(t, utx.InboundTx) require.Equal(t, inbound.SourceChain, utx.InboundTx.SourceChain) require.Equal(t, inbound.TxHash, utx.InboundTx.TxHash) - require.Equal(t, inbound.Sender, utx.InboundTx.Sender) + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), utx.InboundTx.Sender) require.Equal(t, inbound.Amount, utx.InboundTx.Amount) require.Equal(t, inbound.AssetAddr, utx.InboundTx.AssetAddr) diff --git a/test/integration/uexecutor/rescue_funds_test.go b/test/integration/uexecutor/rescue_funds_test.go index 378d88b27..0fa054361 100644 --- a/test/integration/uexecutor/rescue_funds_test.go +++ b/test/integration/uexecutor/rescue_funds_test.go @@ -17,6 +17,7 @@ import ( "github.com/pushchain/push-chain-node/app" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" ) @@ -80,7 +81,7 @@ func setupRescueFundsTest( *app.ChainApp, sdk.Context, []string, // universalVals - string, // utxId of the failed CEA UTX + string, // utxId of the failed CEA UTX []stakingtypes.Validator, ) { t.Helper() @@ -205,7 +206,7 @@ func TestRescueFunds(t *testing.T) { rescueOb := findRescueOutbound(utx) require.NotNil(t, rescueOb) // Falls back to original inbound sender - require.Equal(t, utils.GetDefaultAddresses().DefaultTestAddr, rescueOb.Recipient) + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(utils.GetDefaultAddresses().DefaultTestAddr), rescueOb.Recipient) }) t.Run("rescue is rejected for non-CEA inbound with no reverted auto-revert", func(t *testing.T) { diff --git a/test/integration/uexecutor/revert_stuck_inbound_test.go b/test/integration/uexecutor/revert_stuck_inbound_test.go index 74d26d3e8..d5dc8e8cc 100644 --- a/test/integration/uexecutor/revert_stuck_inbound_test.go +++ b/test/integration/uexecutor/revert_stuck_inbound_test.go @@ -8,6 +8,7 @@ import ( "github.com/pushchain/push-chain-node/app" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutorkeeper "github.com/pushchain/push-chain-node/x/uexecutor/keeper" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" uregistrytypes "github.com/pushchain/push-chain-node/x/uregistry/types" @@ -41,9 +42,9 @@ func setupRevertStuckInbound(t *testing.T) (chainApp *app.ChainApp, ctx sdk.Cont usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr tokenConfig := uregistrytypes.TokenConfig{ - Chain: "eip155:11155111", - Address: usdcAddress.String(), - Name: "USD Coin", Symbol: "USDC", Decimals: 6, Enabled: true, + Chain: "eip155:11155111", + Address: usdcAddress.String(), + Name: "USD Coin", Symbol: "USDC", Decimals: 6, Enabled: true, LiquidityCap: "1000000000000000000000000", TokenType: 1, NativeRepresentation: &uregistrytypes.NativeRepresentation{ ContractAddress: prc20Address.String(), @@ -130,7 +131,7 @@ func TestRevertStuckInbound_HappyPath_ExpiredBallot_CreatesRevertOutbound(t *tes "recipient must use RevertInstructions.FundRecipient when set") require.Equal(t, inbound.Amount, ob.Amount, "full amount refunded") require.Equal(t, inbound.AssetAddr, ob.ExternalAssetAddr, "external asset addr must match the original deposit asset") - require.Equal(t, inbound.Sender, ob.Sender, "sender field carries original depositor") + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), ob.Sender, "sender field carries original depositor") // --- PendingOutbounds index assertions --- pending, err := chainApp.UexecutorKeeper.PendingOutbounds.Get(ctx, ob.Id) @@ -157,7 +158,7 @@ func TestRevertStuckInbound_RecipientFallback_UsesSender(t *testing.T) { utx, _, _ := chainApp.UexecutorKeeper.GetUniversalTx(ctx, resp.UtxId) require.Len(t, utx.OutboundTx, 1) - require.Equal(t, inbound.Sender, utx.OutboundTx[0].Recipient, + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), utx.OutboundTx[0].Recipient, "with no RevertInstructions, refund goes to original sender") } diff --git a/test/integration/utss/fund_migration_test.go b/test/integration/utss/fund_migration_test.go index 36f7877a4..ad43c0096 100644 --- a/test/integration/utss/fund_migration_test.go +++ b/test/integration/utss/fund_migration_test.go @@ -272,7 +272,7 @@ func TestVoteFundMigration(t *testing.T) { migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) require.NoError(t, err) - txHash := "0xdeadbeef1234567890" + txHash := "0xdeadbeef12345678deadbeef12345678deadbeef12345678deadbeef12345678" // Vote with all validators (2/3 quorum needed, so 3 votes for 3 validators) for i, val := range universalVals { @@ -320,7 +320,7 @@ func TestVoteFundMigration(t *testing.T) { migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) require.NoError(t, err) - txHash := "0xfailedtx" + txHash := "" // Vote failure with all validators for _, val := range universalVals { @@ -338,7 +338,7 @@ func TestVoteFundMigration(t *testing.T) { app, ctx, universalVals, _ := setupFundMigrationTest(t, 3, false) valAddr, _ := sdk.ValAddressFromBech32(universalVals[0]) - err := app.UtssKeeper.VoteFundMigration(ctx, valAddr, 999, "0xtx", true) + err := app.UtssKeeper.VoteFundMigration(ctx, valAddr, 999, "0x1111111111111111111111111111111111111111111111111111111111111111", true) require.ErrorContains(t, err, "not found") }) @@ -351,12 +351,12 @@ func TestVoteFundMigration(t *testing.T) { // Finalize it first for _, val := range universalVals { valAddr, _ := sdk.ValAddressFromBech32(val) - _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xtx", true) + _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0x1111111111111111111111111111111111111111111111111111111111111111", true) } // Try to vote again valAddr, _ := sdk.ValAddressFromBech32(universalVals[0]) - err = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xtx2", true) + err = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0x2222222222222222222222222222222222222222222222222222222222222222", true) require.ErrorContains(t, err, "already finalized") }) } @@ -391,7 +391,7 @@ func TestFundMigrationQueries(t *testing.T) { // Finalize it for _, val := range universalVals { valAddr, _ := sdk.ValAddressFromBech32(val) - _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xtx", true) + _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0x1111111111111111111111111111111111111111111111111111111111111111", true) } // Should be removed from pending @@ -403,3 +403,53 @@ func TestFundMigrationQueries(t *testing.T) { require.Equal(t, 0, pendingCount) }) } + +// TestVoteFundMigration_EquivalentHashEncodingsConverge is the F-2026-17041 +// regression: three validators submit the SAME migration tx hash in three +// different encodings (EIP-55-style mixed case, lowercase, no 0x prefix). +// Canonicalization in VoteFundMigration must land all votes on ONE ballot, +// finalizing the migration — pre-fix each encoding produced its own ballot +// and quorum never formed. +func TestVoteFundMigration_EquivalentHashEncodingsConverge(t *testing.T) { + app, ctx, universalVals, oldKeyId := setupFundMigrationTest(t, 3, false) + + migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) + require.NoError(t, err) + + canonical := "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + encodings := []string{ + "0xB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD", // uppercase + "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", // lowercase + "b28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", // no prefix + } + require.Len(t, universalVals, 3) + + for i, val := range universalVals { + valAddr, err := sdk.ValAddressFromBech32(val) + require.NoError(t, err) + require.NoError(t, app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, encodings[i], true), + "vote %d with encoding %q must be accepted", i, encodings[i]) + } + + // All three encodings converged on one ballot → quorum reached → COMPLETED. + migration, err := app.UtssKeeper.FundMigrations.Get(ctx, migrationId) + require.NoError(t, err) + require.Equal(t, utsstypes.FundMigrationStatus_FUND_MIGRATION_STATUS_COMPLETED, migration.Status, + "equivalent encodings must aggregate on one ballot and finalize") + require.Equal(t, canonical, migration.TxHash, + "stored tx hash must be the canonical 0x-lowercase form") +} + +// TestVoteFundMigration_MalformedHashRejected: strict per-namespace +// validation rejects garbage hashes for EVM chains instead of keying a +// ballot off them. +func TestVoteFundMigration_MalformedHashRejected(t *testing.T) { + app, ctx, universalVals, oldKeyId := setupFundMigrationTest(t, 3, false) + + migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) + require.NoError(t, err) + + valAddr, _ := sdk.ValAddressFromBech32(universalVals[0]) + err = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xnot-a-real-hash", true) + require.ErrorContains(t, err, "invalid tx hash") +} diff --git a/utils/canonical.go b/utils/canonical.go new file mode 100644 index 000000000..64c5bc62f --- /dev/null +++ b/utils/canonical.go @@ -0,0 +1,201 @@ +package utils + +import ( + "encoding/hex" + "fmt" + "strings" + + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/mr-tron/base58" +) + +// Per-CAIP-2-namespace canonical forms for ballot/storage keys: eip155 +// addresses → EIP-55, eip155 hashes → 0x-lowercase, solana → base58 preserved +// (case-significant) / hex lowercased, other → trimmed. One form per value so +// encoding variance can't fragment votes or duplicate rows. +const ( + namespaceEVM = "eip155" + namespaceSolana = "solana" +) + +const base58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + +// CAIP2Namespace returns the namespace component of a CAIP-2 chain id +// ("eip155:1" → "eip155"). Returns "" when the id has no namespace. +func CAIP2Namespace(chain string) string { + parts := strings.SplitN(strings.TrimSpace(chain), ":", 2) + if len(parts) != 2 { + return "" + } + return parts[0] +} + +func isHexString(s string) bool { + if s == "" { + return false + } + _, err := hex.DecodeString(s) + return err == nil +} + +func isBase58String(s string) bool { + if s == "" { + return false + } + for _, c := range s { + if !strings.ContainsRune(base58Alphabet, c) { + return false + } + } + return true +} + +// strip0x removes a leading "0x"/"0X" and reports whether one was present. +func strip0x(s string) (string, bool) { + if len(s) >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { + return s[2:], true + } + return s, false +} + +// CanonicalizeEVMAddress validates s as a 20-byte hex address (with or +// without 0x) and returns the EIP-55 checksummed, 0x-prefixed form. +func CanonicalizeEVMAddress(s string) (string, error) { + s = strings.TrimSpace(s) + if !ethcommon.IsHexAddress(s) { + return "", fmt.Errorf("invalid EVM address %q: must be 20-byte hex", s) + } + return ethcommon.HexToAddress(s).Hex(), nil +} + +// CanonicalizeEVMHash validates s as a 32-byte hex hash (with or without 0x) +// and returns the 0x-prefixed lowercase form. +func CanonicalizeEVMHash(s string) (string, error) { + s = strings.TrimSpace(s) + body, _ := strip0x(s) + if len(body) != 64 || !isHexString(body) { + return "", fmt.Errorf("invalid EVM tx hash %q: must be 32-byte hex", s) + } + return "0x" + strings.ToLower(body), nil +} + +// CanonicalizeHexBlob lenient-canonicalizes free-length hex payloads +// (raw_payload, verification_data): valid hex (with or without 0x, even +// length) → 0x-prefixed lowercase; anything else is returned trimmed as-is. +func CanonicalizeHexBlob(s string) string { + s = strings.TrimSpace(s) + if s == "" { + return "" + } + body, _ := strip0x(s) + if len(body)%2 == 0 && isHexString(body) { + return "0x" + strings.ToLower(body) + } + return s +} + +// canonicalizeSolanaValue: hex inputs lowercase (0x kept); base58 inputs are +// charset-validated and preserved as-is (base58 is case-significant — +// lowercasing would corrupt the value). +func canonicalizeSolanaValue(s string) (string, error) { + s = strings.TrimSpace(s) + if body, had0x := strip0x(s); had0x && len(body)%2 == 0 && isHexString(body) { + return "0x" + strings.ToLower(body), nil + } + if isBase58String(s) { + return s, nil + } + return "", fmt.Errorf("invalid solana value %q: neither 0x-hex nor base58", s) +} + +// canonicalizeSolanaTxHash additionally unifies base58-encoded 64-byte +// signatures into 0x-lowercase-hex, matching the form the reference client +// submits, so hex and base58 encodings of the same signature converge. +func canonicalizeSolanaTxHash(s string) (string, error) { + canon, err := canonicalizeSolanaValue(s) + if err != nil { + return "", err + } + if strings.HasPrefix(canon, "0x") { + return canon, nil + } + if raw, decErr := base58.Decode(canon); decErr == nil && len(raw) == 64 { + return "0x" + hex.EncodeToString(raw), nil + } + return canon, nil +} + +// CanonicalizeAddressByNamespace canonicalizes an address for the given +// CAIP-2 chain. Empty input passes through (optional fields). +func CanonicalizeAddressByNamespace(chain, addr string) (string, error) { + addr = strings.TrimSpace(addr) + if addr == "" { + return "", nil + } + switch CAIP2Namespace(chain) { + case namespaceEVM: + return CanonicalizeEVMAddress(addr) + case namespaceSolana: + return canonicalizeSolanaValue(addr) + default: + return addr, nil + } +} + +// CanonicalizeTxHashByNamespace canonicalizes a transaction hash/signature +// for the given CAIP-2 chain. Empty input passes through (e.g. failed +// outbound observations carry no hash). +func CanonicalizeTxHashByNamespace(chain, txHash string) (string, error) { + txHash = strings.TrimSpace(txHash) + if txHash == "" { + return "", nil + } + switch CAIP2Namespace(chain) { + case namespaceEVM: + return CanonicalizeEVMHash(txHash) + case namespaceSolana: + return canonicalizeSolanaTxHash(txHash) + default: + return txHash, nil + } +} + +// Lenient variants for the vote-ingress / key-derivation path: canonical form +// when the value parses, trimmed input otherwise (never an error). Used there +// because that path must never drop a vote — a malformed inbound still has to +// produce an on-chain UTX record (with a failed PCTx / revert), and +// execution-level validation, not key derivation, is what rejects it. Honest +// observers of the same value still converge (same trimmed string), and the +// injective hashFields digest keeps even malformed values collision-safe. +// Strict (error-returning) variants are for admin/config paths where bad input +// should be rejected before it is persisted. + +// LenientCanonicalizeAddress canonicalizes addr for chain, falling back to +// the trimmed input when it does not parse. +func LenientCanonicalizeAddress(chain, addr string) string { + canon, err := CanonicalizeAddressByNamespace(chain, addr) + if err != nil { + return strings.TrimSpace(addr) + } + return canon +} + +// LenientCanonicalizeTxHash canonicalizes txHash for chain, falling back to +// the trimmed input when it does not parse. +func LenientCanonicalizeTxHash(chain, txHash string) string { + canon, err := CanonicalizeTxHashByNamespace(chain, txHash) + if err != nil { + return strings.TrimSpace(txHash) + } + return canon +} + +// LenientCanonicalizeEVMAddress canonicalizes a Push-Chain (EVM) address to +// EIP-55, falling back to the trimmed input when it does not parse. +func LenientCanonicalizeEVMAddress(addr string) string { + canon, err := CanonicalizeEVMAddress(addr) + if err != nil { + return strings.TrimSpace(addr) + } + return canon +} diff --git a/utils/canonical_test.go b/utils/canonical_test.go new file mode 100644 index 000000000..15ba309eb --- /dev/null +++ b/utils/canonical_test.go @@ -0,0 +1,136 @@ +package utils_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/utils" +) + +const ( + eip55Addr = "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed" + lowerAddr = "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed" + upperAddr = "0X5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED" + noPfxAddr = "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed" + mixedHash = "0xB28F49668e7e76dc96D7aaBE5b7f63FEcfbd1c3574774c05e8204e749fd96fbd" + lowerHash = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + noPfxHash = "b28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + solPubkey = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" + solSig = "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7" +) + +func TestCanonicalizeEVMAddress_EquivalentEncodingsConverge(t *testing.T) { + for _, in := range []string{eip55Addr, lowerAddr, upperAddr, noPfxAddr, " " + eip55Addr + " "} { + got, err := utils.CanonicalizeEVMAddress(in) + require.NoError(t, err, "input %q", in) + require.Equal(t, eip55Addr, got, "input %q must canonicalize to EIP-55", in) + } +} + +func TestCanonicalizeEVMAddress_RejectsMalformed(t *testing.T) { + for _, in := range []string{"", "0x12", "0xZZaeb6053f3e94c9b9a09f33669435e7ef1beaed", lowerAddr + "ab", "not-an-address"} { + _, err := utils.CanonicalizeEVMAddress(in) + require.Error(t, err, "input %q must be rejected", in) + } +} + +func TestCanonicalizeEVMHash_EquivalentEncodingsConverge(t *testing.T) { + upper0X := "0X" + "B28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD" + for _, in := range []string{mixedHash, lowerHash, noPfxHash, upper0X, " " + lowerHash + " "} { + got, err := utils.CanonicalizeEVMHash(in) + require.NoError(t, err, "input %q", in) + require.Equal(t, lowerHash, got, "input %q must canonicalize to 0x-lowercase", in) + } +} + +func TestCanonicalizeEVMHash_Keeps0xPrefix(t *testing.T) { + got, err := utils.CanonicalizeEVMHash(noPfxHash) + require.NoError(t, err) + require.Equal(t, "0x", got[:2], "canonical hash form must keep the 0x prefix") +} + +func TestCanonicalizeEVMHash_RejectsMalformed(t *testing.T) { + for _, in := range []string{"", "0x1234", lowerHash + "00", "0xZZ" + noPfxHash[2:]} { + _, err := utils.CanonicalizeEVMHash(in) + require.Error(t, err, "input %q must be rejected", in) + } +} + +func TestCanonicalizeAddressByNamespace_Solana_PreservesBase58Case(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("solana:mainnet", solPubkey) + require.NoError(t, err) + require.Equal(t, solPubkey, got, "base58 pubkeys are case-significant and must not be altered") +} + +func TestCanonicalizeAddressByNamespace_Solana_HexLowercased(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("solana:devnet", "0xABCDEF12") + require.NoError(t, err) + require.Equal(t, "0xabcdef12", got) +} + +func TestCanonicalizeAddressByNamespace_EVM(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("eip155:1", lowerAddr) + require.NoError(t, err) + require.Equal(t, eip55Addr, got) +} + +func TestCanonicalizeAddressByNamespace_EmptyPassthrough(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("eip155:1", "") + require.NoError(t, err) + require.Equal(t, "", got) +} + +func TestCanonicalizeAddressByNamespace_UnknownNamespaceTrims(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("cosmos:push", " push1abc ") + require.NoError(t, err) + require.Equal(t, "push1abc", got) +} + +func TestCanonicalizeTxHashByNamespace_EVM(t *testing.T) { + got, err := utils.CanonicalizeTxHashByNamespace("eip155:11155111", mixedHash) + require.NoError(t, err) + require.Equal(t, lowerHash, got) +} + +func TestCanonicalizeTxHashByNamespace_Solana_Base58SigConvergesWithHex(t *testing.T) { + // The reference client converts base58 signatures to 0x-hex before + // submitting; a client submitting raw base58 must land on the same form. + fromB58, err := utils.CanonicalizeTxHashByNamespace("solana:devnet", solSig) + require.NoError(t, err) + require.Equal(t, "0x", fromB58[:2], "64-byte base58 signature should converge to 0x-hex") + require.Len(t, fromB58, 2+128) + + again, err := utils.CanonicalizeTxHashByNamespace("solana:devnet", fromB58) + require.NoError(t, err) + require.Equal(t, fromB58, again, "canonicalization must be idempotent") +} + +func TestCanonicalizeTxHashByNamespace_Solana_NonSigBase58Preserved(t *testing.T) { + // 32-byte base58 values (pubkey-length) are not signatures; preserved as-is. + got, err := utils.CanonicalizeTxHashByNamespace("solana:devnet", solPubkey) + require.NoError(t, err) + require.Equal(t, solPubkey, got) +} + +func TestCanonicalizeTxHashByNamespace_EmptyPassthrough(t *testing.T) { + got, err := utils.CanonicalizeTxHashByNamespace("eip155:1", "") + require.NoError(t, err) + require.Equal(t, "", got) +} + +func TestCanonicalizeHexBlob(t *testing.T) { + require.Equal(t, "0xabcd12", utils.CanonicalizeHexBlob("0xABCD12")) + require.Equal(t, "0xabcd12", utils.CanonicalizeHexBlob("ABCD12")) + require.Equal(t, "", utils.CanonicalizeHexBlob(" ")) + // Non-hex content is preserved trimmed, never mangled. + require.Equal(t, "not-hex", utils.CanonicalizeHexBlob(" not-hex ")) + // Odd-length hex strings are not valid byte blobs; preserved. + require.Equal(t, "0xabc", utils.CanonicalizeHexBlob("0xabc")) +} + +func TestCAIP2Namespace(t *testing.T) { + require.Equal(t, "eip155", utils.CAIP2Namespace("eip155:1")) + require.Equal(t, "solana", utils.CAIP2Namespace("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1")) + require.Equal(t, "", utils.CAIP2Namespace("no-colon")) +} diff --git a/x/uexecutor/keeper/admin_revert.go b/x/uexecutor/keeper/admin_revert.go index 2f77e52f8..d7a606941 100644 --- a/x/uexecutor/keeper/admin_revert.go +++ b/x/uexecutor/keeper/admin_revert.go @@ -26,6 +26,10 @@ import ( func (k Keeper) RevertStuckInbound(ctx context.Context, inbound types.Inbound) (utxId, outboundId string, err error) { sdkCtx := sdk.UnwrapSDKContext(ctx) + // Same canonical form as the vote path, so the admin-supplied payload + // derives the same ballot key / UTX key the votes did. + inbound.Canonicalize() + if vErr := inbound.ValidateBasic(); vErr != nil { return "", "", errors.Wrap(sdkErrors.ErrInvalidRequest, vErr.Error()) } diff --git a/x/uexecutor/keeper/ballot_hooks.go b/x/uexecutor/keeper/ballot_hooks.go index 23ebec19e..85e53c5e4 100644 --- a/x/uexecutor/keeper/ballot_hooks.go +++ b/x/uexecutor/keeper/ballot_hooks.go @@ -2,10 +2,7 @@ package keeper import ( "context" - "encoding/hex" - "errors" - "cosmossdk.io/collections" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pushchain/push-chain-node/x/uexecutor/types" @@ -77,46 +74,41 @@ func (h BallotHooks) afterInboundBallotTerminal( ballotID string, status uvalidatortypes.BallotStatus, ) error { - // Decode ballot ID → Inbound (ballot ID for INBOUND_TX is hex(marshal(Inbound))). - bz, err := hex.DecodeString(ballotID) + // Ballot IDs are one-way canonical digests (not reversible), so locate + // the owning audit-trail entry by scanning PendingInbounds for the + // variant carrying this ballot ID. The pending set is small and + // transient, and this hook only fires on terminal transitions. + var ( + utxKey string + entry types.PendingInboundEntry + found bool + ) + err := h.k.PendingInbounds.Walk(ctx, nil, func(key string, e types.PendingInboundEntry) (bool, error) { + for _, v := range e.Variants { + if v.BallotId == ballotID { + utxKey, entry, found = key, e, true + return true, nil + } + } + return false, nil + }) if err != nil { - h.k.Logger().Warn("ballot terminal hook: cannot hex-decode inbound ballot id", - "ballot_id", ballotID, "err", err.Error()) - return nil + return err } - var inbound types.Inbound - if err := inbound.Unmarshal(bz); err != nil { - h.k.Logger().Warn("ballot terminal hook: cannot unmarshal inbound from ballot id", - "ballot_id", ballotID, "err", err.Error()) + if !found { + // Entry was already cleared (e.g. the consensus-success path in + // VoteInbound already removed it before this hook fires), or the + // ballot does not belong to a tracked inbound. Nothing to do. return nil } - utxKey := types.GetInboundUniversalTxKey(inbound) - - entry, err := h.k.PendingInbounds.Get(ctx, utxKey) - if err != nil { - if errors.Is(err, collections.ErrNotFound) { - // Entry was already cleared (e.g. the consensus-success path in - // VoteInbound already removed it before this hook fires). Nothing - // to do. - return nil - } - return err - } // Mark this variant's terminal status. - found := false for i := range entry.Variants { if entry.Variants[i].BallotId == ballotID { entry.Variants[i].TerminalStatus = status - found = true break } } - if !found { - h.k.Logger().Warn("ballot terminal hook: inbound variant not found in pending entry", - "ballot_id", ballotID, "utx_key", utxKey) - return nil - } // If any variant is still PENDING, persist the updated entry and wait. for _, v := range entry.Variants { diff --git a/x/uexecutor/keeper/msg_vote_inbound.go b/x/uexecutor/keeper/msg_vote_inbound.go index 0d584bf87..a20a2651d 100644 --- a/x/uexecutor/keeper/msg_vote_inbound.go +++ b/x/uexecutor/keeper/msg_vote_inbound.go @@ -16,6 +16,10 @@ import ( // query what happened to their cross-chain tx instead of having funds silently stuck // in the gateway contract. func (k Keeper) VoteInbound(ctx context.Context, universalValidator sdk.ValAddress, inbound types.Inbound) error { + // Canonicalize first so every derived key + the stored inbound use one + // representation per logical event. + inbound.Canonicalize() + k.Logger().Info("vote inbound received", "validator", universalValidator.String(), "source_chain", inbound.SourceChain, diff --git a/x/uexecutor/keeper/msg_vote_outbound.go b/x/uexecutor/keeper/msg_vote_outbound.go index 4b7a31b2a..ae9a5b726 100644 --- a/x/uexecutor/keeper/msg_vote_outbound.go +++ b/x/uexecutor/keeper/msg_vote_outbound.go @@ -3,8 +3,10 @@ package keeper import ( "context" "fmt" + "strings" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pushchain/push-chain-node/utils" "github.com/pushchain/push-chain-node/x/uexecutor/types" ) @@ -51,6 +53,12 @@ func (k Keeper) VoteOutbound( return fmt.Errorf("outbound %s not found in UniversalTx %s", outboundId, utxId) } + // Canonicalize the observed tx hash for the destination chain so encoding + // variants of the same observation land on one ballot. + observedTx.TxHash = utils.LenientCanonicalizeTxHash(outbound.DestinationChain, observedTx.TxHash) + observedTx.GasFeeUsed = strings.TrimSpace(observedTx.GasFeeUsed) + observedTx.ErrorMsg = strings.TrimSpace(observedTx.ErrorMsg) + // Prevent double-finalization if outbound.OutboundStatus != types.Status_PENDING { k.Logger().Warn("vote outbound rejected: outbound already finalized", diff --git a/x/uexecutor/keeper/query_keys.go b/x/uexecutor/keeper/query_keys.go new file mode 100644 index 000000000..503c22678 --- /dev/null +++ b/x/uexecutor/keeper/query_keys.go @@ -0,0 +1,88 @@ +package keeper + +import ( + "context" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/pushchain/push-chain-node/utils" + "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// InboundKeys derives the canonical UTX id and inbound ballot id for the given +// inbound, applying the same canonicalization the vote path uses. Lets off-chain +// validators read the keys from the chain instead of re-implementing the rules. +func (k Querier) InboundKeys(goCtx context.Context, req *types.QueryInboundKeysRequest) (*types.QueryInboundKeysResponse, error) { + if req == nil || req.Inbound == nil { + return nil, status.Error(codes.InvalidArgument, "inbound is required") + } + + inbound := *req.Inbound + inbound.Canonicalize() + + ballotID, err := types.GetInboundBallotKey(inbound) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to derive inbound ballot key: %v", err) + } + + return &types.QueryInboundKeysResponse{ + UtxId: types.GetInboundUniversalTxKey(inbound), + BallotId: ballotID, + CanonicalInbound: &inbound, + }, nil +} + +// OutboundBallotKey derives the canonical outbound ballot id for the given +// observation. The observed tx hash is canonicalized against the outbound's +// destination chain, which is looked up from the stored UTX/outbound so the +// caller can't supply the wrong chain. +func (k Querier) OutboundBallotKey(goCtx context.Context, req *types.QueryOutboundBallotKeyRequest) (*types.QueryOutboundBallotKeyResponse, error) { + if req == nil || req.ObservedTx == nil { + return nil, status.Error(codes.InvalidArgument, "observed_tx is required") + } + if strings.TrimSpace(req.UtxId) == "" || strings.TrimSpace(req.OutboundId) == "" { + return nil, status.Error(codes.InvalidArgument, "utx_id and outbound_id are required") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + // k.Keeper.GetUniversalTx (3 returns), not the shadowing Querier gRPC method. + utx, found, err := k.Keeper.GetUniversalTx(ctx, req.UtxId) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load universal tx: %v", err) + } + if !found { + return nil, status.Errorf(codes.NotFound, "universal tx %s not found", req.UtxId) + } + + var destChain string + outboundFound := false + for _, ob := range utx.OutboundTx { + if ob.Id == req.OutboundId { + destChain = ob.DestinationChain + outboundFound = true + break + } + } + if !outboundFound { + return nil, status.Errorf(codes.NotFound, "outbound %s not found in universal tx %s", req.OutboundId, req.UtxId) + } + + // Mirror the canonicalization applied at vote ingress (msg_vote_outbound.go). + obs := *req.ObservedTx + obs.TxHash = utils.LenientCanonicalizeTxHash(destChain, obs.TxHash) + obs.GasFeeUsed = strings.TrimSpace(obs.GasFeeUsed) + obs.ErrorMsg = strings.TrimSpace(obs.ErrorMsg) + + ballotID, err := types.GetOutboundBallotKey(req.UtxId, req.OutboundId, obs) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to derive outbound ballot key: %v", err) + } + + return &types.QueryOutboundBallotKeyResponse{ + BallotId: ballotID, + CanonicalObservedTx: &obs, + }, nil +} diff --git a/x/uexecutor/types/inbound.go b/x/uexecutor/types/inbound.go index b9b18af2a..c857d48ae 100644 --- a/x/uexecutor/types/inbound.go +++ b/x/uexecutor/types/inbound.go @@ -13,6 +13,28 @@ import ( const EvmZeroAddress = "0x0000000000000000000000000000000000000000" +// Canonicalize normalizes encoding-variant fields in place (per source-chain +// namespace) so the same event from any observer is byte-identical across +// ballot keys, UTX keys and registry lookups. Lenient (unparseable values are +// kept trimmed, never rejected) because the vote path must always record a +// UTX — execution-level validation rejects malformed inbounds later. +func (p *Inbound) Canonicalize() { + p.SourceChain = strings.TrimSpace(p.SourceChain) + p.TxHash = utils.LenientCanonicalizeTxHash(p.SourceChain, p.TxHash) + p.Sender = utils.LenientCanonicalizeAddress(p.SourceChain, p.Sender) + p.AssetAddr = utils.LenientCanonicalizeAddress(p.SourceChain, p.AssetAddr) + // Recipient lives on Push Chain (EVM) regardless of source chain. + p.Recipient = utils.LenientCanonicalizeEVMAddress(p.Recipient) + p.LogIndex = strings.TrimSpace(p.LogIndex) + p.Amount = strings.TrimSpace(p.Amount) + p.RawPayload = utils.CanonicalizeHexBlob(p.RawPayload) + p.VerificationData = utils.CanonicalizeHexBlob(p.VerificationData) + if p.RevertInstructions != nil { + // Refunds return to the source chain. + p.RevertInstructions.FundRecipient = utils.LenientCanonicalizeAddress(p.SourceChain, p.RevertInstructions.FundRecipient) + } +} + // NormalizeForTxType zeroes out fields that are irrelevant for the given TxType, // and decodes raw_payload into universal_payload for payload types. // This should be called by the core module after ballot finalization. diff --git a/x/uexecutor/types/keys.go b/x/uexecutor/types/keys.go index 036242ca7..23452ae20 100755 --- a/x/uexecutor/types/keys.go +++ b/x/uexecutor/types/keys.go @@ -4,8 +4,11 @@ import ( "crypto/sha256" "encoding/hex" fmt "fmt" + "strings" "cosmossdk.io/collections" + + "github.com/pushchain/push-chain-node/utils" ) var ( @@ -46,6 +49,13 @@ var ( // refund flow. See plan-pending-inbound-cleanup.md. ExpiredInboundsKey = collections.NewPrefix(8) ExpiredInboundsName = "expired_inbounds" + + // Domain separators for the canonical ballot-key digests. Hashed into the + // key preimage (never used as store prefixes); kept in this block so prefix + // numbers stay unique. They keep inbound vs outbound keys disjoint in the + // shared uvalidator Ballots map. + InboundBallotDomain = collections.NewPrefix(9) + OutboundBallotDomain = collections.NewPrefix(10) ) const ( @@ -56,18 +66,63 @@ const ( QuerierRoute = ModuleName ) +// GetInboundUniversalTxKey: UTX identity from canonical (source_chain, tx_hash, +// log_index). Canonicalizes locals; caller's inbound is not mutated. func GetInboundUniversalTxKey(inbound Inbound) string { - data := fmt.Sprintf("%s:%s:%s", inbound.SourceChain, inbound.TxHash, inbound.LogIndex) + chain := strings.TrimSpace(inbound.SourceChain) + txHash := utils.LenientCanonicalizeTxHash(chain, inbound.TxHash) + logIndex := strings.TrimSpace(inbound.LogIndex) + data := fmt.Sprintf("%s:%s:%s", chain, txHash, logIndex) hash := sha256.Sum256([]byte(data)) return hex.EncodeToString(hash[:]) // hash[:] converts [32]byte → []byte } +// hashFields = sha256( hex(sha256(domain)) : hex(sha256(f0)) : ... ). Per-field +// hashing makes it injective — a sub-hash can't contain ':', so no field value +// can shift a boundary and collide with a different tuple. +func hashFields(domain collections.Prefix, parts ...string) string { + hashed := make([]string, 0, len(parts)+1) + d := sha256.Sum256(domain.Bytes()) + hashed = append(hashed, hex.EncodeToString(d[:])) + for _, p := range parts { + sum := sha256.Sum256([]byte(p)) + hashed = append(hashed, hex.EncodeToString(sum[:])) + } + final := sha256.Sum256([]byte(strings.Join(hashed, ":"))) + return hex.EncodeToString(final[:]) +} + +// GetInboundBallotKey: versioned canonical digest over every execution- +// relevant field (so quorum implies agreement on the outcome), excluding +// universal_payload (recomputed on-chain from raw_payload). Self-canonicalizes, +// so any caller gets one ballot per logical event. func GetInboundBallotKey(inbound Inbound) (string, error) { - bz, err := inbound.Marshal() - if err != nil { - return "", err + chain := strings.TrimSpace(inbound.SourceChain) + + // nil RevertInstructions and an empty FundRecipient are semantically + // identical (revert falls back to sender) — digest them identically. + fundRecipient := "" + if inbound.RevertInstructions != nil { + fundRecipient = utils.LenientCanonicalizeAddress(chain, inbound.RevertInstructions.FundRecipient) } - return hex.EncodeToString(bz), nil + + return hashFields( + InboundBallotDomain, + chain, + utils.LenientCanonicalizeTxHash(chain, inbound.TxHash), + strings.TrimSpace(inbound.LogIndex), + utils.LenientCanonicalizeAddress(chain, inbound.Sender), + // Recipient lives on Push Chain (EVM) regardless of source chain. + utils.LenientCanonicalizeEVMAddress(inbound.Recipient), + strings.TrimSpace(inbound.Amount), + utils.LenientCanonicalizeAddress(chain, inbound.AssetAddr), + fmt.Sprintf("%d", inbound.TxType), + utils.CanonicalizeHexBlob(inbound.VerificationData), + fundRecipient, + fmt.Sprintf("%t", inbound.IsCEA), + utils.CanonicalizeHexBlob(inbound.RawPayload), + // universal_payload intentionally excluded (derived, ignored on-chain). + ), nil } func GetPcUniversalTxKey(pcCaip string, pc PCTx) string { @@ -76,21 +131,25 @@ func GetPcUniversalTxKey(pcCaip string, pc PCTx) string { return hex.EncodeToString(hash[:]) } +// GetOutboundBallotKey: versioned canonical digest over all observation fields +// (all consensus-critical — gas_fee_used drives the refund, error_msg must be +// agreed so no voter can inject unconsensused text). Caller canonicalizes +// tx_hash for the destination chain at vote ingress. func GetOutboundBallotKey( utxId string, outboundIndex string, observedTx OutboundObservation, ) (string, error) { - - bz, err := observedTx.Marshal() - if err != nil { - return "", err - } - - data := append([]byte(utxId+":"+outboundIndex+":"), bz...) - hash := sha256.Sum256(data) - - return hex.EncodeToString(hash[:]), nil + return hashFields( + OutboundBallotDomain, + utxId, + outboundIndex, + fmt.Sprintf("%t", observedTx.Success), + fmt.Sprintf("%d", observedTx.BlockHeight), + observedTx.TxHash, + observedTx.GasFeeUsed, + observedTx.ErrorMsg, + ), nil } // GetOutboundRevertId generates a deterministic outbound ID for an inbound-revert diff --git a/x/uexecutor/types/keys_canonical_test.go b/x/uexecutor/types/keys_canonical_test.go new file mode 100644 index 000000000..d48423404 --- /dev/null +++ b/x/uexecutor/types/keys_canonical_test.go @@ -0,0 +1,293 @@ +package types_test + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "strings" + "testing" + + "cosmossdk.io/collections" + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// recipeHashFields reproduces the production hashFields construction +// independently so the tests document (and pin) the exact algorithm: +// +// key = sha256( hex(sha256(domain.Bytes())) : hex(sha256(f0)) : ... ) +func recipeHashFields(domain collections.Prefix, parts ...string) string { + perField := make([]string, 0, len(parts)+1) + d := sha256.Sum256(domain.Bytes()) + perField = append(perField, hex.EncodeToString(d[:])) + for _, p := range parts { + s := sha256.Sum256([]byte(p)) + perField = append(perField, hex.EncodeToString(s[:])) + } + final := sha256.Sum256([]byte(strings.Join(perField, ":"))) + return hex.EncodeToString(final[:]) +} + +// Canonical voting digest suite: ballot identity must converge for encoding +// variants of the same event, diverge on any consensus-critical difference, +// and ignore the derived universal_payload. + +func canonInbound() types.Inbound { + return types.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", + Sender: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + Recipient: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", + Amount: "1000000", + AssetAddr: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + LogIndex: "1", + TxType: types.TxType_FUNDS, + RevertInstructions: &types.RevertInstructions{ + FundRecipient: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + }, + } +} + +// TestInboundBallotKey_GoldenValueAndRecipe shows exactly how an inbound +// ballot key is built and pins the resulting value. The fields below are +// already in canonical form, so canonicalization is a no-op and the recipe is +// transparent: hash each field, join the hex digests with ':', hash again. +func TestInboundBallotKey_GoldenValueAndRecipe(t *testing.T) { + in := types.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", + Sender: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + Recipient: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", + Amount: "1000000", + AssetAddr: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + LogIndex: "1", + TxType: types.TxType_FUNDS, + RevertInstructions: &types.RevertInstructions{ + FundRecipient: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + }, + } + + got, err := types.GetInboundBallotKey(in) + require.NoError(t, err) + t.Logf("inbound ballot key = %s", got) + + // 1. The exact pinned value (catches any accidental construction change). + require.Equal(t, + "1e7755fdc3d07f21b770f85a9de1cb62b740a8a4d7a38bae0a4a36fd809e2d30", + got, "inbound ballot key golden value changed — confirm the change is intentional") + + // 2. The same value, reproduced field-by-field via the documented recipe. + expected := recipeHashFields( + types.InboundBallotDomain, + in.SourceChain, + in.TxHash, + in.LogIndex, + in.Sender, + in.Recipient, + in.Amount, + in.AssetAddr, + fmt.Sprintf("%d", in.TxType), + in.VerificationData, // "" + in.RevertInstructions.FundRecipient, + fmt.Sprintf("%t", in.IsCEA), // false + in.RawPayload, // "" + ) + require.Equal(t, expected, got, "production key must equal the documented recipe") + require.Len(t, got, 64, "key is a hex-encoded sha256 digest") +} + +// TestOutboundBallotKey_GoldenValueAndRecipe is the outbound twin. +func TestOutboundBallotKey_GoldenValueAndRecipe(t *testing.T) { + obs := types.OutboundObservation{ + Success: true, + BlockHeight: 100, + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", + GasFeeUsed: "21000", + } + + got, err := types.GetOutboundBallotKey("utx-1", "ob-1", obs) + require.NoError(t, err) + t.Logf("outbound ballot key = %s", got) + + require.Equal(t, + "ac7ba6932ceec3e434947a96eabf1deb7a7d628d09691190244d5ed63ccb155a", + got, "outbound ballot key golden value changed — confirm the change is intentional") + + expected := recipeHashFields( + types.OutboundBallotDomain, + "utx-1", + "ob-1", + fmt.Sprintf("%t", obs.Success), + fmt.Sprintf("%d", obs.BlockHeight), + obs.TxHash, + obs.GasFeeUsed, + obs.ErrorMsg, // "" + ) + require.Equal(t, expected, got, "production key must equal the documented recipe") + require.Len(t, got, 64) +} + +func TestInboundBallotKey_EncodingVariantsConverge(t *testing.T) { + base := canonInbound() + base.Canonicalize() + baseKey, err := types.GetInboundBallotKey(base) + require.NoError(t, err) + + // Same logical event with every string field in a different encoding. + variant := canonInbound() + variant.TxHash = "0XB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD" + variant.Sender = "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed" + variant.Recipient = "0X1C7D4B196CB0C7B01D743FBC6116A902379C7238" + variant.AssetAddr = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + variant.RevertInstructions.FundRecipient = "0x5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED" + variant.Canonicalize() + + variantKey, err := types.GetInboundBallotKey(variant) + require.NoError(t, err) + require.Equal(t, baseKey, variantKey, + "encoding variants of the same event must produce one ballot key") + + // And the UTX key converges as well (sibling site). + require.Equal(t, types.GetInboundUniversalTxKey(base), types.GetInboundUniversalTxKey(variant)) +} + +func TestInboundBallotKey_UniversalPayloadExcluded(t *testing.T) { + a := canonInbound() + a.Canonicalize() + keyNil, err := types.GetInboundBallotKey(a) + require.NoError(t, err) + + b := canonInbound() + b.UniversalPayload = &types.UniversalPayload{To: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"} + b.Canonicalize() + keyPopulated, err := types.GetInboundBallotKey(b) + require.NoError(t, err) + + require.Equal(t, keyNil, keyPopulated, + "universal_payload is derived/ignored on-chain and must not affect ballot identity") +} + +func TestInboundBallotKey_NilAndEmptyRevertInstructionsConverge(t *testing.T) { + a := canonInbound() + a.RevertInstructions = nil + a.Canonicalize() + keyNil, _ := types.GetInboundBallotKey(a) + + b := canonInbound() + b.RevertInstructions = &types.RevertInstructions{FundRecipient: ""} + b.Canonicalize() + keyEmpty, _ := types.GetInboundBallotKey(b) + + require.Equal(t, keyNil, keyEmpty, + "nil revert_instructions and empty fund_recipient are semantically identical") +} + +func TestInboundBallotKey_ConsensusFieldsDiverge(t *testing.T) { + base := canonInbound() + base.Canonicalize() + baseKey, _ := types.GetInboundBallotKey(base) + + mutate := []func(*types.Inbound){ + func(i *types.Inbound) { i.Amount = "2000000" }, + func(i *types.Inbound) { i.Recipient = "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed" }, + func(i *types.Inbound) { i.AssetAddr = "0x387b9C8Db60E74999aAAC5A2b7825b400F12d68E" }, + func(i *types.Inbound) { i.LogIndex = "2" }, + func(i *types.Inbound) { i.TxType = types.TxType_GAS }, + func(i *types.Inbound) { i.IsCEA = true }, + func(i *types.Inbound) { i.RawPayload = "0xdeadbeef" }, + func(i *types.Inbound) { i.RevertInstructions.FundRecipient = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" }, + } + for n, m := range mutate { + v := canonInbound() + m(&v) + v.Canonicalize() + key, err := types.GetInboundBallotKey(v) + require.NoError(t, err) + require.NotEqual(t, baseKey, key, "mutation %d must change the ballot identity", n) + } +} + +func TestOutboundBallotKey_EncodingVariantsConverge(t *testing.T) { + // Hash canonicalization happens at vote ingress (per destination chain); + // digest over the canonical observation must converge. + obsA := types.OutboundObservation{Success: true, BlockHeight: 100, + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", GasFeeUsed: "21000"} + obsB := obsA + + keyA, err := types.GetOutboundBallotKey("utx-1", "ob-1", obsA) + require.NoError(t, err) + keyB, err := types.GetOutboundBallotKey("utx-1", "ob-1", obsB) + require.NoError(t, err) + require.Equal(t, keyA, keyB) +} + +func TestOutboundBallotKey_AllFieldsAreConsensusCritical(t *testing.T) { + base := types.OutboundObservation{Success: true, BlockHeight: 100, + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", GasFeeUsed: "21000"} + baseKey, _ := types.GetOutboundBallotKey("utx-1", "ob-1", base) + + mutations := []types.OutboundObservation{ + {Success: false, BlockHeight: 100, TxHash: base.TxHash, GasFeeUsed: "21000"}, + {Success: true, BlockHeight: 101, TxHash: base.TxHash, GasFeeUsed: "21000"}, + {Success: true, BlockHeight: 100, TxHash: "0x" + "11" + base.TxHash[4:], GasFeeUsed: "21000"}, + {Success: true, BlockHeight: 100, TxHash: base.TxHash, GasFeeUsed: "42000"}, + {Success: true, BlockHeight: 100, TxHash: base.TxHash, GasFeeUsed: "21000", ErrorMsg: "boom"}, + } + for n, obs := range mutations { + key, err := types.GetOutboundBallotKey("utx-1", "ob-1", obs) + require.NoError(t, err) + require.NotEqual(t, baseKey, key, "mutation %d must change the ballot identity", n) + } + + // Scoping fields too. + keyOtherUtx, _ := types.GetOutboundBallotKey("utx-2", "ob-1", base) + require.NotEqual(t, baseKey, keyOtherUtx) + keyOtherOb, _ := types.GetOutboundBallotKey("utx-1", "ob-2", base) + require.NotEqual(t, baseKey, keyOtherOb) +} + +func TestBallotKey_DomainSeparation(t *testing.T) { + // Inbound and outbound digests share the framing; the version-domain + // prefix must keep their key spaces disjoint. + in := canonInbound() + in.Canonicalize() + inKey, _ := types.GetInboundBallotKey(in) + outKey, _ := types.GetOutboundBallotKey("utx-1", "ob-1", types.OutboundObservation{Success: true, BlockHeight: 1, TxHash: in.TxHash, GasFeeUsed: "1"}) + require.NotEqual(t, inKey, outKey) + require.Len(t, inKey, 64, "sha256 hex digest") + require.Len(t, outKey, 64, "sha256 hex digest") +} + +func TestInboundCanonicalize_SolanaFieldsPreserved(t *testing.T) { + in := types.Inbound{ + SourceChain: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + TxHash: "0xAB12CD34" + "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccdd", // 0x-hex form (client converts sigs) + Sender: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // base58 — case-significant + Recipient: "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238", + AssetAddr: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + LogIndex: "0", + Amount: "5", + TxType: types.TxType_FUNDS, + } + in.Canonicalize() + + require.Equal(t, "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", in.Sender, + "base58 sender must not be case-mangled") + require.Equal(t, "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", in.AssetAddr, + "base58 asset must not be case-mangled") + require.Equal(t, "0x", in.TxHash[:2]) + require.Equal(t, in.TxHash, "0x"+lowercase(in.TxHash[2:]), "hex tx hash lowercased") + require.Equal(t, "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", in.Recipient, + "push-side recipient canonicalized to EIP-55") +} + +func lowercase(s string) string { + out := []rune(s) + for i, r := range out { + if r >= 'A' && r <= 'F' { + out[i] = r + 32 + } + } + return string(out) +} diff --git a/x/uexecutor/types/query.pb.go b/x/uexecutor/types/query.pb.go index 1bc8c73f1..23c90fd8b 100644 --- a/x/uexecutor/types/query.pb.go +++ b/x/uexecutor/types/query.pb.go @@ -1149,6 +1149,224 @@ func (m *QueryAllPendingOutboundsResponse) GetPagination() *query.PageResponse { return nil } +// InboundKeys: derive canonical UTX id + inbound ballot id from an inbound. +type QueryInboundKeysRequest struct { + Inbound *Inbound `protobuf:"bytes,1,opt,name=inbound,proto3" json:"inbound,omitempty"` +} + +func (m *QueryInboundKeysRequest) Reset() { *m = QueryInboundKeysRequest{} } +func (m *QueryInboundKeysRequest) String() string { return proto.CompactTextString(m) } +func (*QueryInboundKeysRequest) ProtoMessage() {} +func (*QueryInboundKeysRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{23} +} +func (m *QueryInboundKeysRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryInboundKeysRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryInboundKeysRequest.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 *QueryInboundKeysRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryInboundKeysRequest.Merge(m, src) +} +func (m *QueryInboundKeysRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryInboundKeysRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryInboundKeysRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryInboundKeysRequest proto.InternalMessageInfo + +func (m *QueryInboundKeysRequest) GetInbound() *Inbound { + if m != nil { + return m.Inbound + } + return nil +} + +type QueryInboundKeysResponse struct { + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` + BallotId string `protobuf:"bytes,2,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` + CanonicalInbound *Inbound `protobuf:"bytes,3,opt,name=canonical_inbound,json=canonicalInbound,proto3" json:"canonical_inbound,omitempty"` +} + +func (m *QueryInboundKeysResponse) Reset() { *m = QueryInboundKeysResponse{} } +func (m *QueryInboundKeysResponse) String() string { return proto.CompactTextString(m) } +func (*QueryInboundKeysResponse) ProtoMessage() {} +func (*QueryInboundKeysResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{24} +} +func (m *QueryInboundKeysResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryInboundKeysResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryInboundKeysResponse.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 *QueryInboundKeysResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryInboundKeysResponse.Merge(m, src) +} +func (m *QueryInboundKeysResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryInboundKeysResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryInboundKeysResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryInboundKeysResponse proto.InternalMessageInfo + +func (m *QueryInboundKeysResponse) GetUtxId() string { + if m != nil { + return m.UtxId + } + return "" +} + +func (m *QueryInboundKeysResponse) GetBallotId() string { + if m != nil { + return m.BallotId + } + return "" +} + +func (m *QueryInboundKeysResponse) GetCanonicalInbound() *Inbound { + if m != nil { + return m.CanonicalInbound + } + return nil +} + +// OutboundBallotKey: derive the canonical outbound ballot id for an observation. +type QueryOutboundBallotKeyRequest struct { + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` + OutboundId string `protobuf:"bytes,2,opt,name=outbound_id,json=outboundId,proto3" json:"outbound_id,omitempty"` + ObservedTx *OutboundObservation `protobuf:"bytes,3,opt,name=observed_tx,json=observedTx,proto3" json:"observed_tx,omitempty"` +} + +func (m *QueryOutboundBallotKeyRequest) Reset() { *m = QueryOutboundBallotKeyRequest{} } +func (m *QueryOutboundBallotKeyRequest) String() string { return proto.CompactTextString(m) } +func (*QueryOutboundBallotKeyRequest) ProtoMessage() {} +func (*QueryOutboundBallotKeyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{25} +} +func (m *QueryOutboundBallotKeyRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryOutboundBallotKeyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryOutboundBallotKeyRequest.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 *QueryOutboundBallotKeyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryOutboundBallotKeyRequest.Merge(m, src) +} +func (m *QueryOutboundBallotKeyRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryOutboundBallotKeyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryOutboundBallotKeyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryOutboundBallotKeyRequest proto.InternalMessageInfo + +func (m *QueryOutboundBallotKeyRequest) GetUtxId() string { + if m != nil { + return m.UtxId + } + return "" +} + +func (m *QueryOutboundBallotKeyRequest) GetOutboundId() string { + if m != nil { + return m.OutboundId + } + return "" +} + +func (m *QueryOutboundBallotKeyRequest) GetObservedTx() *OutboundObservation { + if m != nil { + return m.ObservedTx + } + return nil +} + +type QueryOutboundBallotKeyResponse struct { + BallotId string `protobuf:"bytes,1,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` + CanonicalObservedTx *OutboundObservation `protobuf:"bytes,2,opt,name=canonical_observed_tx,json=canonicalObservedTx,proto3" json:"canonical_observed_tx,omitempty"` +} + +func (m *QueryOutboundBallotKeyResponse) Reset() { *m = QueryOutboundBallotKeyResponse{} } +func (m *QueryOutboundBallotKeyResponse) String() string { return proto.CompactTextString(m) } +func (*QueryOutboundBallotKeyResponse) ProtoMessage() {} +func (*QueryOutboundBallotKeyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{26} +} +func (m *QueryOutboundBallotKeyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryOutboundBallotKeyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryOutboundBallotKeyResponse.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 *QueryOutboundBallotKeyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryOutboundBallotKeyResponse.Merge(m, src) +} +func (m *QueryOutboundBallotKeyResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryOutboundBallotKeyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryOutboundBallotKeyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryOutboundBallotKeyResponse proto.InternalMessageInfo + +func (m *QueryOutboundBallotKeyResponse) GetBallotId() string { + if m != nil { + return m.BallotId + } + return "" +} + +func (m *QueryOutboundBallotKeyResponse) GetCanonicalObservedTx() *OutboundObservation { + if m != nil { + return m.CanonicalObservedTx + } + return nil +} + func init() { proto.RegisterType((*QueryGasPriceRequest)(nil), "uexecutor.v1.QueryGasPriceRequest") proto.RegisterType((*QueryGasPriceResponse)(nil), "uexecutor.v1.QueryGasPriceResponse") @@ -1173,89 +1391,107 @@ func init() { proto.RegisterType((*QueryGetPendingOutboundResponse)(nil), "uexecutor.v1.QueryGetPendingOutboundResponse") proto.RegisterType((*QueryAllPendingOutboundsRequest)(nil), "uexecutor.v1.QueryAllPendingOutboundsRequest") proto.RegisterType((*QueryAllPendingOutboundsResponse)(nil), "uexecutor.v1.QueryAllPendingOutboundsResponse") + proto.RegisterType((*QueryInboundKeysRequest)(nil), "uexecutor.v1.QueryInboundKeysRequest") + proto.RegisterType((*QueryInboundKeysResponse)(nil), "uexecutor.v1.QueryInboundKeysResponse") + proto.RegisterType((*QueryOutboundBallotKeyRequest)(nil), "uexecutor.v1.QueryOutboundBallotKeyRequest") + proto.RegisterType((*QueryOutboundBallotKeyResponse)(nil), "uexecutor.v1.QueryOutboundBallotKeyResponse") } func init() { proto.RegisterFile("uexecutor/v1/query.proto", fileDescriptor_94816af5d57d33a7) } var fileDescriptor_94816af5d57d33a7 = []byte{ - // 1221 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcf, 0x6f, 0xe3, 0xc4, - 0x17, 0xef, 0xa4, 0xfb, 0xa3, 0x79, 0xfd, 0xb1, 0x5f, 0xcd, 0xe6, 0x5b, 0x52, 0xb7, 0x4d, 0x53, - 0x77, 0x69, 0xb3, 0x4b, 0x6b, 0xab, 0xdd, 0xa5, 0xe2, 0x80, 0x90, 0xda, 0x65, 0xa9, 0x8a, 0x16, - 0x6d, 0x88, 0x16, 0x0e, 0x5c, 0xa2, 0x49, 0x3c, 0x72, 0x2d, 0x5a, 0x3b, 0x6b, 0x3b, 0x51, 0xaa, - 0xaa, 0x42, 0x80, 0xb8, 0x70, 0x01, 0xc4, 0x09, 0x21, 0xc4, 0x0d, 0xb8, 0xf0, 0x7f, 0xec, 0x71, - 0x25, 0x2e, 0x9c, 0x10, 0xb4, 0xfc, 0x0b, 0xdc, 0x51, 0xc6, 0x33, 0x8e, 0xc7, 0x19, 0xa7, 0x11, - 0x0a, 0xdc, 0x9c, 0x79, 0xef, 0xcd, 0xfb, 0x7c, 0xde, 0xcc, 0xfb, 0xcc, 0x4c, 0xa0, 0xd8, 0xa6, - 0x5d, 0xda, 0x6c, 0x87, 0x9e, 0x6f, 0x76, 0xb6, 0xcd, 0x67, 0x6d, 0xea, 0x9f, 0x1a, 0x2d, 0xdf, - 0x0b, 0x3d, 0x3c, 0x13, 0x5b, 0x8c, 0xce, 0xb6, 0x56, 0xb0, 0x3d, 0xdb, 0x63, 0x06, 0xb3, 0xf7, - 0x15, 0xf9, 0x68, 0x4b, 0xb6, 0xe7, 0xd9, 0xc7, 0xd4, 0x24, 0x2d, 0xc7, 0x24, 0xae, 0xeb, 0x85, - 0x24, 0x74, 0x3c, 0x37, 0xe0, 0x56, 0x79, 0xee, 0xf0, 0xb4, 0x45, 0x85, 0x65, 0x49, 0xb2, 0xd8, - 0x24, 0xa8, 0xb7, 0x7c, 0xa7, 0x49, 0xb9, 0x75, 0x59, 0xb2, 0x36, 0x8f, 0x88, 0xe3, 0xd6, 0x4f, - 0x68, 0x48, 0xb8, 0x59, 0x93, 0xcc, 0x2d, 0xea, 0x5a, 0x8e, 0x6b, 0x73, 0xdb, 0xbd, 0xa6, 0x17, - 0x9c, 0x78, 0x81, 0xd9, 0x20, 0x01, 0x8d, 0xd8, 0x98, 0x9d, 0xed, 0x06, 0x0d, 0xc9, 0xb6, 0xd9, - 0x22, 0xb6, 0xe3, 0x32, 0x7c, 0x91, 0xaf, 0xbe, 0x0d, 0x85, 0x77, 0x7b, 0x1e, 0x07, 0x24, 0xa8, - 0xf6, 0xb2, 0xd7, 0xe8, 0xb3, 0x36, 0x0d, 0x42, 0xbc, 0x00, 0x53, 0x51, 0x4e, 0xc7, 0x2a, 0xa2, - 0x32, 0xaa, 0xe4, 0x6b, 0x37, 0xd9, 0xef, 0x43, 0x4b, 0x7f, 0x0c, 0xff, 0x4f, 0x85, 0x04, 0x2d, - 0xcf, 0x0d, 0x28, 0xbe, 0x0f, 0xf9, 0x98, 0x05, 0x0b, 0x9a, 0xde, 0x99, 0x37, 0x92, 0x05, 0x34, - 0xe2, 0x90, 0x29, 0x9b, 0x7f, 0xe9, 0x0d, 0x28, 0xb2, 0xd9, 0xf6, 0x8e, 0x8f, 0x85, 0x35, 0x10, - 0x20, 0xde, 0x02, 0xe8, 0x03, 0xe6, 0x33, 0xae, 0x1b, 0x11, 0x3b, 0xa3, 0xc7, 0xce, 0x88, 0xd6, - 0x8a, 0xb3, 0x33, 0xaa, 0xc4, 0x16, 0x04, 0x6a, 0x89, 0x48, 0xfd, 0x5b, 0x04, 0x0b, 0x8a, 0x24, - 0x1c, 0xf6, 0xab, 0x00, 0x31, 0xec, 0xa0, 0x88, 0xca, 0x93, 0x43, 0x70, 0xe7, 0x05, 0xee, 0x00, - 0x1f, 0x48, 0xe0, 0x72, 0x0c, 0xdc, 0xc6, 0x95, 0xe0, 0xa2, 0x9c, 0x12, 0xba, 0x1d, 0x5e, 0xcf, - 0x87, 0xbd, 0xfa, 0xbe, 0x43, 0x43, 0x32, 0xc2, 0x1a, 0x54, 0x61, 0x3e, 0x1d, 0xc3, 0xd9, 0xec, - 0x02, 0xf4, 0x37, 0x0b, 0xaf, 0xd9, 0x4b, 0x32, 0x9b, 0x7e, 0x50, 0xbe, 0x29, 0x3e, 0xf5, 0x66, - 0xbf, 0x44, 0xb1, 0x7d, 0xec, 0x0b, 0xf1, 0x3d, 0x02, 0x4d, 0x95, 0x85, 0x63, 0x7f, 0x0d, 0xa6, - 0xfb, 0xd8, 0xc5, 0x52, 0x64, 0x82, 0x87, 0x18, 0xfc, 0x18, 0x17, 0xa3, 0x00, 0x98, 0x01, 0xac, - 0x12, 0x9f, 0x9c, 0x08, 0xfe, 0xfa, 0x43, 0xb8, 0x2d, 0x8d, 0x72, 0xbc, 0x9b, 0x70, 0xa3, 0xc5, - 0x46, 0x78, 0x49, 0x0a, 0x32, 0x54, 0xee, 0xcd, 0x7d, 0xf4, 0x23, 0x28, 0x09, 0xee, 0xd5, 0xa8, - 0x5f, 0x0f, 0xdd, 0x86, 0xd7, 0x76, 0xad, 0xb1, 0x97, 0xf9, 0x67, 0x04, 0x2b, 0x99, 0xa9, 0x38, - 0xf6, 0x3d, 0xb8, 0x49, 0xdd, 0xd0, 0x77, 0xe2, 0x2d, 0xbf, 0x9a, 0x02, 0x2f, 0xc5, 0x3d, 0x72, - 0x43, 0xff, 0x74, 0xff, 0xda, 0xf3, 0xdf, 0x56, 0x26, 0x6a, 0x22, 0x6e, 0x7c, 0x45, 0x4f, 0x54, - 0xe6, 0x51, 0xb7, 0xe5, 0xf8, 0xd4, 0xfa, 0x2f, 0x2a, 0x33, 0x90, 0x6a, 0xc4, 0xca, 0xc8, 0x71, - 0xff, 0x6e, 0x65, 0x36, 0x79, 0xbf, 0x1c, 0xd0, 0xf0, 0x3d, 0xd7, 0xe9, 0x50, 0x3f, 0x20, 0xc7, - 0x4f, 0xbb, 0xa2, 0x2a, 0x73, 0x90, 0x8b, 0xa5, 0x21, 0xe7, 0x58, 0x3a, 0x81, 0x45, 0xa5, 0x37, - 0x27, 0xb6, 0x0f, 0x33, 0x6d, 0x31, 0x5c, 0x0f, 0xbb, 0xbc, 0x8c, 0x2b, 0x32, 0xbb, 0x44, 0xe0, - 0x63, 0x6a, 0x93, 0xe6, 0x69, 0x6d, 0xba, 0xdd, 0x1f, 0xd2, 0xad, 0x7e, 0x03, 0x2b, 0x00, 0x8d, - 0x6b, 0x99, 0x7e, 0x40, 0x9c, 0x49, 0x3a, 0x0d, 0x67, 0xf2, 0x06, 0xcc, 0x26, 0x99, 0x88, 0x85, - 0x5a, 0xc8, 0xa4, 0x52, 0x9b, 0x49, 0x90, 0x18, 0xe3, 0xfa, 0xfc, 0x85, 0xa0, 0xc0, 0x3b, 0xe5, - 0x49, 0x3b, 0xec, 0x6f, 0x08, 0xbc, 0x02, 0xd3, 0x1e, 0x1f, 0xe8, 0xcb, 0x37, 0x88, 0xa1, 0x43, - 0x0b, 0xaf, 0xc3, 0xad, 0x24, 0x85, 0x9e, 0x53, 0x8e, 0x39, 0xcd, 0x26, 0x90, 0x1e, 0x5a, 0x78, - 0x19, 0xa0, 0xe9, 0x53, 0x12, 0x52, 0xab, 0x4e, 0xc2, 0xe2, 0x64, 0x19, 0x55, 0x26, 0x6b, 0x79, - 0x3e, 0xb2, 0x17, 0xe2, 0xbb, 0xf0, 0xbf, 0xc0, 0xb1, 0x5d, 0xc7, 0xb5, 0xeb, 0x16, 0x25, 0xd6, - 0xb1, 0xe3, 0xd2, 0xe2, 0x35, 0xe6, 0x74, 0x8b, 0x8f, 0xbf, 0xc9, 0x87, 0xf1, 0xdb, 0x30, 0xd5, - 0x21, 0xbe, 0x43, 0xdc, 0x30, 0x28, 0x5e, 0x67, 0xf5, 0xaa, 0xc8, 0xf5, 0x12, 0x0c, 0x9e, 0x34, - 0x02, 0xea, 0x77, 0x18, 0xc1, 0xf7, 0xa3, 0x00, 0xbe, 0xbf, 0xe3, 0x78, 0x7d, 0x8f, 0x77, 0xec, - 0x01, 0x0d, 0x53, 0xf4, 0xc5, 0x56, 0xb8, 0xaa, 0x00, 0xfa, 0x57, 0xa2, 0x15, 0x55, 0x73, 0xc4, - 0x07, 0xc2, 0xf5, 0x5e, 0x4b, 0x9d, 0xf2, 0xad, 0xa4, 0x2b, 0x25, 0x4a, 0x2a, 0x7c, 0x2d, 0x0a, - 0xc0, 0x0f, 0x60, 0x4a, 0xe4, 0xe2, 0xeb, 0x5b, 0x54, 0x93, 0x7d, 0xda, 0xad, 0xc5, 0x9e, 0xba, - 0x33, 0xa0, 0x9b, 0xc2, 0x6d, 0xec, 0x4a, 0xf4, 0x07, 0x82, 0x72, 0x76, 0x2e, 0xce, 0xff, 0xf5, - 0xb4, 0x14, 0x8d, 0x52, 0x81, 0x58, 0x85, 0x76, 0x21, 0x2f, 0x98, 0x05, 0xc5, 0x1c, 0x8b, 0xcf, - 0x2e, 0x42, 0xdf, 0x35, 0xd5, 0x1d, 0x93, 0xff, 0xb8, 0x3b, 0x76, 0x7e, 0x9a, 0x81, 0xeb, 0x8c, - 0x23, 0xfe, 0x10, 0x6e, 0x44, 0xa7, 0x21, 0x2e, 0xcb, 0x08, 0x06, 0x0f, 0x5b, 0x6d, 0x75, 0x88, - 0x47, 0x94, 0x44, 0x5f, 0xfa, 0xe4, 0x97, 0x3f, 0xbf, 0xce, 0xcd, 0xe3, 0x82, 0x29, 0x5f, 0x83, - 0xa3, 0x14, 0xdf, 0x20, 0xc0, 0x83, 0x27, 0x1f, 0xde, 0x54, 0xcc, 0x9b, 0x79, 0x16, 0x6b, 0x5b, - 0x23, 0x7a, 0x73, 0x44, 0xeb, 0x0c, 0x51, 0x19, 0x97, 0x4c, 0xd5, 0xc5, 0xbc, 0xee, 0x08, 0x10, - 0x5f, 0x20, 0x98, 0x93, 0xe5, 0x19, 0x57, 0x14, 0x99, 0x94, 0x7a, 0xaf, 0xdd, 0x1d, 0xc1, 0x93, - 0xe3, 0xa9, 0x30, 0x3c, 0x3a, 0x2e, 0xcb, 0x78, 0x24, 0xd5, 0x34, 0xcf, 0x1c, 0xeb, 0x1c, 0x7f, - 0x8e, 0x60, 0x4e, 0x96, 0x59, 0x25, 0x22, 0xa5, 0xe0, 0x2b, 0x11, 0xa9, 0x35, 0x5b, 0x5f, 0x63, - 0x88, 0x96, 0xf1, 0xe2, 0x10, 0x44, 0xf8, 0x23, 0x98, 0x12, 0x77, 0x6d, 0xac, 0xab, 0xd8, 0xca, - 0xcf, 0x14, 0x6d, 0x6d, 0xa8, 0x0f, 0xcf, 0x7c, 0x8f, 0x65, 0xbe, 0x83, 0x75, 0x53, 0xfd, 0xe2, - 0x32, 0xcf, 0xc4, 0x35, 0xfb, 0x1c, 0x7f, 0x8c, 0x60, 0x26, 0xf9, 0x4a, 0xc0, 0xeb, 0x6a, 0x86, - 0xe9, 0xb7, 0x8a, 0xb6, 0x71, 0xa5, 0x1f, 0x47, 0x53, 0x66, 0x68, 0x34, 0x5c, 0xcc, 0x40, 0x13, - 0xe0, 0x4f, 0x11, 0xe4, 0xe3, 0x6b, 0x2e, 0x56, 0x51, 0x4c, 0x3f, 0x15, 0xb4, 0x3b, 0xc3, 0x9d, - 0x78, 0xea, 0x57, 0x58, 0xea, 0x97, 0xf1, 0x9a, 0x99, 0xf1, 0xb8, 0x4c, 0x56, 0xe2, 0x33, 0x04, - 0xb3, 0xd2, 0x35, 0x1d, 0x67, 0x50, 0x1c, 0x78, 0x2e, 0x68, 0x95, 0xab, 0x1d, 0x39, 0xa2, 0x55, - 0x86, 0x68, 0x11, 0x2f, 0x64, 0x21, 0x0a, 0xf0, 0x8f, 0x08, 0xf0, 0xe0, 0x11, 0xa1, 0xec, 0xe6, - 0xcc, 0xd3, 0x48, 0xd9, 0xcd, 0xd9, 0xe7, 0x8e, 0xfe, 0x80, 0xc1, 0x32, 0xf0, 0xa6, 0xba, 0x9b, - 0x85, 0x54, 0x9a, 0x67, 0x89, 0x23, 0xee, 0x1c, 0x7f, 0x87, 0xe0, 0xb6, 0x42, 0xcd, 0xf1, 0x70, - 0x29, 0x49, 0x9f, 0x30, 0x9a, 0x31, 0xaa, 0x3b, 0x07, 0xbb, 0xc1, 0xc0, 0xae, 0xe2, 0x95, 0xe1, - 0x60, 0x63, 0x5d, 0x4c, 0xdd, 0x7b, 0xb3, 0x74, 0x51, 0x7d, 0x13, 0xcf, 0xd2, 0xc5, 0x8c, 0xcb, - 0x74, 0x96, 0x2e, 0xd2, 0xc8, 0x3d, 0xd6, 0xc5, 0xfd, 0xea, 0xf3, 0x8b, 0x12, 0x7a, 0x71, 0x51, - 0x42, 0xbf, 0x5f, 0x94, 0xd0, 0x97, 0x97, 0xa5, 0x89, 0x17, 0x97, 0xa5, 0x89, 0x5f, 0x2f, 0x4b, - 0x13, 0x1f, 0xec, 0xda, 0x4e, 0x78, 0xd4, 0x6e, 0x18, 0x4d, 0xef, 0xc4, 0x6c, 0xb5, 0x83, 0x23, - 0xb6, 0x37, 0xd8, 0xd7, 0x16, 0xfb, 0xdc, 0x72, 0x3d, 0x8b, 0x9a, 0xdd, 0xc4, 0xfc, 0xec, 0x4f, - 0x96, 0xc6, 0x0d, 0xf6, 0x07, 0xc7, 0xfd, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x05, 0xd4, 0xf0, - 0x65, 0xdd, 0x11, 0x00, 0x00, + // 1448 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0x4f, 0x6f, 0x13, 0x47, + 0x14, 0xc0, 0x33, 0x0e, 0x09, 0xf1, 0x4b, 0x08, 0x30, 0x24, 0xe0, 0x6c, 0x88, 0xe3, 0x2c, 0x10, + 0x02, 0x04, 0xaf, 0x02, 0x14, 0x55, 0x55, 0x55, 0x29, 0xa1, 0x34, 0x0a, 0x50, 0x91, 0x5a, 0xd0, + 0x43, 0x2f, 0xd6, 0xda, 0x3b, 0xda, 0xac, 0x70, 0x76, 0x8d, 0x77, 0x1d, 0xd9, 0x42, 0xa8, 0x6a, + 0x51, 0x2f, 0xbd, 0xf4, 0xef, 0xa5, 0x6a, 0xab, 0xde, 0xda, 0x53, 0xbf, 0x07, 0x97, 0x4a, 0x48, + 0xbd, 0xf4, 0x54, 0xb5, 0xd0, 0xaf, 0xd0, 0x7b, 0xe5, 0xd9, 0x37, 0xbb, 0x3b, 0xeb, 0x59, 0xc7, + 0xaa, 0xdc, 0xde, 0xd6, 0x33, 0xef, 0xcd, 0xfb, 0xbd, 0x37, 0xf3, 0xde, 0xcc, 0x33, 0x14, 0xda, + 0xac, 0xc3, 0xea, 0xed, 0xc0, 0x6b, 0x19, 0x07, 0x1b, 0xc6, 0xe3, 0x36, 0x6b, 0x75, 0xcb, 0xcd, + 0x96, 0x17, 0x78, 0x74, 0x26, 0x9a, 0x29, 0x1f, 0x6c, 0x68, 0x73, 0xb6, 0x67, 0x7b, 0x7c, 0xc2, + 0xe8, 0x7d, 0x85, 0x32, 0xda, 0x59, 0xdb, 0xf3, 0xec, 0x06, 0x33, 0xcc, 0xa6, 0x63, 0x98, 0xae, + 0xeb, 0x05, 0x66, 0xe0, 0x78, 0xae, 0x8f, 0xb3, 0xf2, 0xda, 0x41, 0xb7, 0xc9, 0xc4, 0xcc, 0x59, + 0x69, 0xc6, 0x36, 0xfd, 0x6a, 0xb3, 0xe5, 0xd4, 0x19, 0xce, 0x2e, 0x49, 0xb3, 0xf5, 0x3d, 0xd3, + 0x71, 0xab, 0xfb, 0x2c, 0x30, 0x71, 0x5a, 0x93, 0xa6, 0x9b, 0xcc, 0xb5, 0x1c, 0xd7, 0xc6, 0xb9, + 0xcb, 0x75, 0xcf, 0xdf, 0xf7, 0x7c, 0xa3, 0x66, 0xfa, 0x2c, 0xf4, 0xc6, 0x38, 0xd8, 0xa8, 0xb1, + 0xc0, 0xdc, 0x30, 0x9a, 0xa6, 0xed, 0xb8, 0x9c, 0x2f, 0x94, 0xd5, 0x37, 0x60, 0xee, 0xbd, 0x9e, + 0xc4, 0xb6, 0xe9, 0xef, 0xf6, 0xac, 0x57, 0xd8, 0xe3, 0x36, 0xf3, 0x03, 0xba, 0x00, 0x53, 0xa1, + 0x4d, 0xc7, 0x2a, 0x90, 0x12, 0x59, 0xcb, 0x57, 0x8e, 0xf2, 0xdf, 0x3b, 0x96, 0x7e, 0x0f, 0xe6, + 0x53, 0x2a, 0x7e, 0xd3, 0x73, 0x7d, 0x46, 0xaf, 0x43, 0x3e, 0xf2, 0x82, 0x2b, 0x4d, 0x5f, 0x3b, + 0x5d, 0x4e, 0x06, 0xb0, 0x1c, 0xa9, 0x4c, 0xd9, 0xf8, 0xa5, 0xd7, 0xa0, 0xc0, 0x57, 0xdb, 0x6c, + 0x34, 0xc4, 0xac, 0x2f, 0x20, 0xde, 0x01, 0x88, 0x81, 0x71, 0xc5, 0xd5, 0x72, 0xe8, 0x5d, 0xb9, + 0xe7, 0x5d, 0x39, 0xdc, 0x2b, 0xf4, 0xae, 0xbc, 0x6b, 0xda, 0xc2, 0x81, 0x4a, 0x42, 0x53, 0xff, + 0x96, 0xc0, 0x82, 0xc2, 0x08, 0x62, 0xbf, 0x06, 0x10, 0x61, 0xfb, 0x05, 0x52, 0x1a, 0x1f, 0xc0, + 0x9d, 0x17, 0xdc, 0x3e, 0xdd, 0x96, 0xe0, 0x72, 0x1c, 0xee, 0xe2, 0xa1, 0x70, 0xa1, 0x4d, 0x89, + 0xee, 0x1a, 0xc6, 0xf3, 0x56, 0x2f, 0xbe, 0xef, 0xb2, 0xc0, 0x1c, 0x62, 0x0f, 0x76, 0xe1, 0x74, + 0x5a, 0x07, 0xbd, 0xb9, 0x09, 0x10, 0x1f, 0x16, 0x8c, 0xd9, 0x19, 0xd9, 0x9b, 0x58, 0x29, 0x5f, + 0x17, 0x9f, 0x7a, 0x3d, 0x0e, 0x51, 0x34, 0x3f, 0xf2, 0x8d, 0xf8, 0x81, 0x80, 0xa6, 0xb2, 0x82, + 0xec, 0xaf, 0xc3, 0x74, 0xcc, 0x2e, 0xb6, 0x22, 0x13, 0x1e, 0x22, 0xf8, 0x11, 0x6e, 0xc6, 0x1c, + 0x50, 0x0e, 0xb8, 0x6b, 0xb6, 0xcc, 0x7d, 0xe1, 0xbf, 0x7e, 0x0b, 0x4e, 0x49, 0xa3, 0xc8, 0xbb, + 0x0e, 0x93, 0x4d, 0x3e, 0x82, 0x21, 0x99, 0x93, 0x51, 0x51, 0x1a, 0x65, 0xf4, 0x3d, 0x28, 0x0a, + 0xdf, 0x77, 0xc3, 0x7c, 0xdd, 0x71, 0x6b, 0x5e, 0xdb, 0xb5, 0x46, 0x1e, 0xe6, 0x9f, 0x09, 0x2c, + 0x67, 0x9a, 0x42, 0xf6, 0x4d, 0x38, 0xca, 0xdc, 0xa0, 0xe5, 0x44, 0x47, 0x7e, 0x25, 0x05, 0x2f, + 0xe9, 0xdd, 0x76, 0x83, 0x56, 0x77, 0xeb, 0xc8, 0xf3, 0xdf, 0x97, 0xc7, 0x2a, 0x42, 0x6f, 0x74, + 0x41, 0x4f, 0x44, 0xe6, 0x76, 0xa7, 0xe9, 0xb4, 0x98, 0xf5, 0x7f, 0x44, 0xa6, 0xcf, 0xd4, 0x90, + 0x91, 0x91, 0xf5, 0xfe, 0xdb, 0xc8, 0xac, 0x63, 0xbe, 0x6c, 0xb3, 0xe0, 0xa1, 0xeb, 0x1c, 0xb0, + 0x96, 0x6f, 0x36, 0x1e, 0x74, 0x44, 0x54, 0x66, 0x21, 0x17, 0x95, 0x86, 0x9c, 0x63, 0xe9, 0x26, + 0x2c, 0x2a, 0xa5, 0xd1, 0xb1, 0x2d, 0x98, 0x69, 0x8b, 0xe1, 0x6a, 0xd0, 0xc1, 0x30, 0x2e, 0xcb, + 0xde, 0x25, 0x14, 0xef, 0x31, 0xdb, 0xac, 0x77, 0x2b, 0xd3, 0xed, 0x78, 0x48, 0xb7, 0xe2, 0x04, + 0x56, 0x00, 0x8d, 0x6a, 0x9b, 0x7e, 0x24, 0xe8, 0x49, 0xda, 0x0c, 0x7a, 0xf2, 0x16, 0x1c, 0x4b, + 0x7a, 0x22, 0x36, 0x6a, 0x21, 0xd3, 0x95, 0xca, 0x4c, 0xc2, 0x89, 0x11, 0xee, 0xcf, 0xdf, 0x04, + 0xe6, 0x30, 0x53, 0xee, 0xb7, 0x83, 0xf8, 0x40, 0xd0, 0x65, 0x98, 0xf6, 0x70, 0x20, 0x2e, 0xdf, + 0x20, 0x86, 0x76, 0x2c, 0xba, 0x0a, 0xc7, 0x93, 0x2e, 0xf4, 0x84, 0x72, 0x5c, 0xe8, 0x58, 0x82, + 0x74, 0xc7, 0xa2, 0x4b, 0x00, 0xf5, 0x16, 0x33, 0x03, 0x66, 0x55, 0xcd, 0xa0, 0x30, 0x5e, 0x22, + 0x6b, 0xe3, 0x95, 0x3c, 0x8e, 0x6c, 0x06, 0xf4, 0x12, 0x9c, 0xf0, 0x1d, 0xdb, 0x75, 0x5c, 0xbb, + 0x6a, 0x31, 0xd3, 0x6a, 0x38, 0x2e, 0x2b, 0x1c, 0xe1, 0x42, 0xc7, 0x71, 0xfc, 0x6d, 0x1c, 0xa6, + 0x77, 0x60, 0xea, 0xc0, 0x6c, 0x39, 0xa6, 0x1b, 0xf8, 0x85, 0x09, 0x1e, 0xaf, 0x35, 0x39, 0x5e, + 0xc2, 0x83, 0xfb, 0x35, 0x9f, 0xb5, 0x0e, 0xb8, 0x83, 0xef, 0x87, 0x0a, 0x78, 0xbe, 0x23, 0x7d, + 0x7d, 0x13, 0x33, 0x76, 0x9b, 0x05, 0x29, 0xf7, 0xc5, 0x51, 0x38, 0x2c, 0x00, 0xfa, 0x17, 0x22, + 0x15, 0x55, 0x6b, 0x44, 0x17, 0xc2, 0x44, 0x2f, 0xa5, 0xba, 0x78, 0x94, 0x74, 0x65, 0x89, 0x92, + 0x02, 0x5f, 0x09, 0x15, 0xe8, 0x0d, 0x98, 0x12, 0xb6, 0x70, 0x7f, 0x0b, 0x6a, 0x67, 0x1f, 0x74, + 0x2a, 0x91, 0xa4, 0xee, 0xf4, 0xd5, 0x4d, 0x21, 0x36, 0xf2, 0x4a, 0xf4, 0x27, 0x81, 0x52, 0xb6, + 0x2d, 0xf4, 0xff, 0xcd, 0x74, 0x29, 0x1a, 0x26, 0x02, 0x51, 0x15, 0xba, 0x09, 0x79, 0xe1, 0x99, + 0x5f, 0xc8, 0x71, 0xfd, 0xec, 0x20, 0xc4, 0xa2, 0xa9, 0xec, 0x18, 0xff, 0xf7, 0xd9, 0x71, 0x07, + 0xce, 0x70, 0x17, 0xb1, 0x54, 0xde, 0x65, 0xdd, 0x28, 0x8c, 0x06, 0x1c, 0x75, 0xc2, 0x51, 0x8c, + 0xe1, 0xbc, 0x4c, 0x86, 0x2a, 0x15, 0x21, 0xa5, 0x7f, 0x49, 0xf0, 0xa1, 0x28, 0x2d, 0x86, 0x71, + 0x9a, 0x87, 0xc9, 0x76, 0x98, 0x43, 0xe1, 0x39, 0x9b, 0x68, 0x07, 0xbd, 0xdc, 0x59, 0x84, 0x7c, + 0xcd, 0x6c, 0x34, 0xbc, 0x20, 0xce, 0xae, 0xa9, 0x70, 0x60, 0xc7, 0xa2, 0x5b, 0x70, 0xb2, 0x6e, + 0xba, 0x9e, 0xeb, 0xd4, 0xcd, 0x46, 0x55, 0xb0, 0x8c, 0x0f, 0x62, 0x39, 0x11, 0xc9, 0xe3, 0x48, + 0xef, 0x61, 0xb9, 0xc4, 0xa1, 0x44, 0x20, 0xb7, 0xf8, 0xea, 0x77, 0x59, 0x57, 0xf8, 0x99, 0x41, + 0x96, 0xca, 0x8e, 0x5c, 0x5f, 0x79, 0xd8, 0x82, 0x69, 0x8f, 0xa7, 0x21, 0xb3, 0x7a, 0xa5, 0x3a, + 0xe4, 0x5a, 0x39, 0x34, 0x5f, 0x2b, 0x20, 0xb4, 0x1e, 0x74, 0xf4, 0xaf, 0x09, 0x66, 0xa9, 0x82, + 0x0e, 0x03, 0x27, 0x45, 0x88, 0xa4, 0x22, 0xf4, 0x10, 0xe6, 0xe3, 0x08, 0x25, 0x69, 0x72, 0xc3, + 0xd2, 0x9c, 0x8a, 0xf4, 0xef, 0x47, 0x58, 0xd7, 0x7e, 0x99, 0x85, 0x09, 0x8e, 0x45, 0x1f, 0xc1, + 0x64, 0xf8, 0x46, 0xa2, 0x25, 0x79, 0xad, 0xfe, 0x27, 0x98, 0xb6, 0x32, 0x40, 0x22, 0x74, 0x46, + 0x3f, 0xfb, 0xf1, 0xaf, 0x7f, 0x7d, 0x95, 0x3b, 0x4d, 0xe7, 0x0c, 0xb9, 0x39, 0x0a, 0x4d, 0x7c, + 0x43, 0x80, 0xf6, 0xbf, 0x87, 0xe8, 0xba, 0x62, 0xdd, 0xcc, 0x17, 0x9a, 0x76, 0x75, 0x48, 0x69, + 0x24, 0x5a, 0xe5, 0x44, 0x25, 0x5a, 0x34, 0x54, 0xed, 0x9a, 0x38, 0x75, 0x3e, 0xfd, 0x8c, 0xc0, + 0xac, 0x7c, 0x69, 0xd3, 0x35, 0x85, 0x25, 0xe5, 0x2b, 0x40, 0xbb, 0x34, 0x84, 0x24, 0xf2, 0xac, + 0x71, 0x1e, 0x9d, 0x96, 0x64, 0x1e, 0xe9, 0x2e, 0x35, 0x9e, 0x38, 0xd6, 0x53, 0xfa, 0x29, 0x81, + 0x59, 0xf9, 0xf2, 0x55, 0x12, 0x29, 0x9f, 0x01, 0x4a, 0x22, 0xf5, 0x4d, 0xae, 0x9f, 0xe3, 0x44, + 0x4b, 0x74, 0x71, 0x00, 0x11, 0xfd, 0x10, 0xa6, 0x44, 0x07, 0x46, 0x75, 0x95, 0xb7, 0x72, 0xf3, + 0xaa, 0x9d, 0x1b, 0x28, 0x83, 0x96, 0x2f, 0x73, 0xcb, 0xe7, 0xa9, 0x6e, 0xa8, 0xfb, 0x70, 0xe3, + 0x89, 0x68, 0xbe, 0x9e, 0xd2, 0x8f, 0x08, 0xcc, 0x24, 0x7b, 0x47, 0xba, 0xaa, 0xf6, 0x30, 0xdd, + 0xc1, 0x6a, 0x17, 0x0f, 0x95, 0x43, 0x9a, 0x12, 0xa7, 0xd1, 0x68, 0x21, 0x83, 0xc6, 0xa7, 0xcf, + 0x08, 0xe4, 0xa3, 0xe6, 0x87, 0xaa, 0x5c, 0x4c, 0x37, 0x90, 0xda, 0xf9, 0xc1, 0x42, 0x68, 0xfa, + 0x0a, 0x37, 0x7d, 0x81, 0x9e, 0x33, 0x32, 0xfe, 0x72, 0x48, 0x46, 0xe2, 0x13, 0x02, 0xc7, 0xa4, + 0xe6, 0x8d, 0x66, 0xb8, 0xd8, 0xd7, 0x44, 0x6a, 0x6b, 0x87, 0x0b, 0x22, 0xd1, 0x0a, 0x27, 0x5a, + 0xa4, 0x0b, 0x59, 0x44, 0x3e, 0xfd, 0x89, 0x00, 0xed, 0x7f, 0x38, 0x28, 0xb3, 0x39, 0xf3, 0x8d, + 0xa2, 0xcc, 0xe6, 0xec, 0xd7, 0x88, 0x7e, 0x83, 0x63, 0x95, 0xe9, 0xba, 0x3a, 0x9b, 0x45, 0xf5, + 0x36, 0x9e, 0x24, 0x4a, 0xfb, 0x53, 0xfa, 0x3d, 0x81, 0x53, 0x8a, 0x3b, 0x9e, 0x0e, 0x2e, 0x25, + 0xe9, 0x77, 0x87, 0x56, 0x1e, 0x56, 0x1c, 0x61, 0x2f, 0x72, 0xd8, 0x15, 0xba, 0x3c, 0x18, 0x36, + 0xaa, 0x8b, 0xa9, 0x6e, 0x28, 0xab, 0x2e, 0xaa, 0xfb, 0xb3, 0xac, 0xba, 0x98, 0xd1, 0x62, 0x65, + 0xd5, 0x45, 0x16, 0x8a, 0xc7, 0x75, 0xf1, 0x19, 0x81, 0xe9, 0xc4, 0x7d, 0x4f, 0x2f, 0x28, 0xcc, + 0xf4, 0x3f, 0x2e, 0xb4, 0xd5, 0xc3, 0xc4, 0x10, 0xe3, 0x02, 0xc7, 0x58, 0x7e, 0x83, 0x5c, 0xd6, + 0x35, 0x99, 0x04, 0x09, 0xaa, 0x8f, 0x7a, 0x56, 0xbf, 0x23, 0x70, 0xb2, 0xef, 0x0a, 0xa5, 0x57, + 0x14, 0x46, 0xb2, 0x9e, 0x01, 0xda, 0xfa, 0x70, 0xc2, 0xc8, 0xb5, 0xce, 0xb9, 0x56, 0x7b, 0x5c, + 0x2b, 0x32, 0x57, 0x74, 0xb2, 0xf0, 0xd6, 0x7e, 0xc4, 0xba, 0x5b, 0xbb, 0xcf, 0x5f, 0x16, 0xc9, + 0x8b, 0x97, 0x45, 0xf2, 0xc7, 0xcb, 0x22, 0xf9, 0xfc, 0x55, 0x71, 0xec, 0xc5, 0xab, 0xe2, 0xd8, + 0x6f, 0xaf, 0x8a, 0x63, 0x1f, 0xdc, 0xb4, 0x9d, 0x60, 0xaf, 0x5d, 0x2b, 0xd7, 0xbd, 0x7d, 0xa3, + 0xd9, 0xf6, 0xf7, 0x78, 0x02, 0xf1, 0xaf, 0xab, 0xfc, 0xf3, 0xaa, 0xeb, 0x59, 0xcc, 0xe8, 0x24, + 0x4c, 0xf0, 0xff, 0x27, 0x6b, 0x93, 0xfc, 0xbf, 0xc1, 0xeb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, + 0xc5, 0x9c, 0xf1, 0x29, 0x18, 0x15, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1294,6 +1530,14 @@ type QueryClient interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(ctx context.Context, in *QueryAllExpiredInboundsRequest, opts ...grpc.CallOption) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) } type queryClient struct { @@ -1403,6 +1647,24 @@ func (c *queryClient) AllExpiredInbounds(ctx context.Context, in *QueryAllExpire return out, nil } +func (c *queryClient) InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) { + out := new(QueryInboundKeysResponse) + err := c.cc.Invoke(ctx, "/uexecutor.v1.Query/InboundKeys", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) { + out := new(QueryOutboundBallotKeyResponse) + err := c.cc.Invoke(ctx, "/uexecutor.v1.Query/OutboundBallotKey", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Params queries all parameters of the module. @@ -1429,6 +1691,14 @@ type QueryServer interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(context.Context, *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(context.Context, *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(context.Context, *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1468,6 +1738,12 @@ func (*UnimplementedQueryServer) AllPendingOutbounds(ctx context.Context, req *Q func (*UnimplementedQueryServer) AllExpiredInbounds(ctx context.Context, req *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllExpiredInbounds not implemented") } +func (*UnimplementedQueryServer) InboundKeys(ctx context.Context, req *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InboundKeys not implemented") +} +func (*UnimplementedQueryServer) OutboundBallotKey(ctx context.Context, req *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method OutboundBallotKey not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1671,6 +1947,42 @@ func _Query_AllExpiredInbounds_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Query_InboundKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryInboundKeysRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).InboundKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/uexecutor.v1.Query/InboundKeys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).InboundKeys(ctx, req.(*QueryInboundKeysRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_OutboundBallotKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryOutboundBallotKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).OutboundBallotKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/uexecutor.v1.Query/OutboundBallotKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).OutboundBallotKey(ctx, req.(*QueryOutboundBallotKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "uexecutor.v1.Query", HandlerType: (*QueryServer)(nil), @@ -1719,6 +2031,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "AllExpiredInbounds", Handler: _Query_AllExpiredInbounds_Handler, }, + { + MethodName: "InboundKeys", + Handler: _Query_InboundKeys_Handler, + }, + { + MethodName: "OutboundBallotKey", + Handler: _Query_OutboundBallotKey_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/query.proto", @@ -2633,69 +2953,244 @@ func (m *QueryAllPendingOutboundsResponse) MarshalToSizedBuffer(dAtA []byte) (in return len(dAtA) - i, nil } -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +func (m *QueryInboundKeysRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - dAtA[offset] = uint8(v) - return base + return dAtA[:n], nil } -func (m *QueryGasPriceRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n + +func (m *QueryInboundKeysRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryGasPriceResponse) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryInboundKeysRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if m.GasPrice != nil { - l = m.GasPrice.Size() - n += 1 + l + sovQuery(uint64(l)) + if m.Inbound != nil { + { + size, err := m.Inbound.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *QueryAllGasPricesRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) +func (m *QueryInboundKeysResponse) 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 n + return dAtA[:n], nil } -func (m *QueryAllGasPricesResponse) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryInboundKeysResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryInboundKeysResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if len(m.GasPrices) > 0 { - for _, e := range m.GasPrices { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } - if m.Pagination != nil { + if m.CanonicalInbound != nil { + { + size, err := m.CanonicalInbound.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.BallotId) > 0 { + i -= len(m.BallotId) + copy(dAtA[i:], m.BallotId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BallotId))) + i-- + dAtA[i] = 0x12 + } + if len(m.UtxId) > 0 { + i -= len(m.UtxId) + copy(dAtA[i:], m.UtxId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.UtxId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryOutboundBallotKeyRequest) 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 *QueryOutboundBallotKeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryOutboundBallotKeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ObservedTx != nil { + { + size, err := m.ObservedTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.OutboundId) > 0 { + i -= len(m.OutboundId) + copy(dAtA[i:], m.OutboundId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.OutboundId))) + i-- + dAtA[i] = 0x12 + } + if len(m.UtxId) > 0 { + i -= len(m.UtxId) + copy(dAtA[i:], m.UtxId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.UtxId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryOutboundBallotKeyResponse) 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 *QueryOutboundBallotKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryOutboundBallotKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CanonicalObservedTx != nil { + { + size, err := m.CanonicalObservedTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.BallotId) > 0 { + i -= len(m.BallotId) + copy(dAtA[i:], m.BallotId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BallotId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryGasPriceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGasPriceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GasPrice != nil { + l = m.GasPrice.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllGasPricesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllGasPricesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.GasPrices) > 0 { + for _, e := range m.GasPrices { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { l = m.Pagination.Size() n += 1 + l + sovQuery(uint64(l)) } @@ -3001,6 +3496,78 @@ func (m *QueryAllPendingOutboundsResponse) Size() (n int) { return n } +func (m *QueryInboundKeysRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Inbound != nil { + l = m.Inbound.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryInboundKeysResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.UtxId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.BallotId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.CanonicalInbound != nil { + l = m.CanonicalInbound.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryOutboundBallotKeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.UtxId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.OutboundId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.ObservedTx != nil { + l = m.ObservedTx.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryOutboundBallotKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BallotId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.CanonicalObservedTx != nil { + l = m.CanonicalObservedTx.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -5307,6 +5874,510 @@ func (m *QueryAllPendingOutboundsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryInboundKeysRequest) 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 ErrIntOverflowQuery + } + 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: QueryInboundKeysRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryInboundKeysRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Inbound", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Inbound == nil { + m.Inbound = &Inbound{} + } + if err := m.Inbound.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryInboundKeysResponse) 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 ErrIntOverflowQuery + } + 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: QueryInboundKeysResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryInboundKeysResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UtxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BallotId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CanonicalInbound", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CanonicalInbound == nil { + m.CanonicalInbound = &Inbound{} + } + if err := m.CanonicalInbound.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryOutboundBallotKeyRequest) 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 ErrIntOverflowQuery + } + 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: QueryOutboundBallotKeyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryOutboundBallotKeyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UtxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OutboundId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OutboundId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObservedTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ObservedTx == nil { + m.ObservedTx = &OutboundObservation{} + } + if err := m.ObservedTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryOutboundBallotKeyResponse) 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 ErrIntOverflowQuery + } + 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: QueryOutboundBallotKeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryOutboundBallotKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BallotId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CanonicalObservedTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CanonicalObservedTx == nil { + m.CanonicalObservedTx = &OutboundObservation{} + } + if err := m.CanonicalObservedTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/uexecutor/types/query.pb.gw.go b/x/uexecutor/types/query.pb.gw.go index 2a32c1962..8675cf9a2 100644 --- a/x/uexecutor/types/query.pb.gw.go +++ b/x/uexecutor/types/query.pb.gw.go @@ -483,6 +483,74 @@ func local_request_Query_AllExpiredInbounds_0(ctx context.Context, marshaler run } +func request_Query_InboundKeys_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryInboundKeysRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.InboundKeys(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_InboundKeys_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryInboundKeysRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.InboundKeys(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_OutboundBallotKey_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryOutboundBallotKeyRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.OutboundBallotKey(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_OutboundBallotKey_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryOutboundBallotKeyRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.OutboundBallotKey(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -742,6 +810,52 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("POST", pattern_Query_InboundKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_InboundKeys_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_InboundKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_OutboundBallotKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_OutboundBallotKey_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_OutboundBallotKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1003,6 +1117,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("POST", pattern_Query_InboundKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_InboundKeys_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_InboundKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_OutboundBallotKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_OutboundBallotKey_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_OutboundBallotKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1028,6 +1182,10 @@ var ( pattern_Query_AllPendingOutbounds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "pending_outbounds"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_AllExpiredInbounds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "expired_inbounds"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_InboundKeys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "inbound_keys"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_OutboundBallotKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "outbound_ballot_key"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -1052,4 +1210,8 @@ var ( forward_Query_AllPendingOutbounds_0 = runtime.ForwardResponseMessage forward_Query_AllExpiredInbounds_0 = runtime.ForwardResponseMessage + + forward_Query_InboundKeys_0 = runtime.ForwardResponseMessage + + forward_Query_OutboundBallotKey_0 = runtime.ForwardResponseMessage ) diff --git a/x/uregistry/keeper/canonical_token_key_test.go b/x/uregistry/keeper/canonical_token_key_test.go new file mode 100644 index 000000000..1e30dacec --- /dev/null +++ b/x/uregistry/keeper/canonical_token_key_test.go @@ -0,0 +1,101 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/x/uregistry/types" +) + +// Regression suite for case-canonical token storage keys: the same logical +// EVM address in any case/prefix variant must always resolve to one row, +// while case-significant solana base58 addresses are preserved verbatim. + +const ( + canonChainEVM = "eip155:11155111" + canonChainSol = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" + + // EIP-55 canonical form + variants of the same 20 bytes. + tokenEIP55 = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" + tokenLower = "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238" + tokenUpper = "0X1C7D4B196CB0C7B01D743FBC6116A902379C7238" + + prc20EIP55 = "0x387b9C8Db60E74999aAAC5A2b7825b400F12d68E" + prc20Lower = "0x387b9c8db60e74999aaac5a2b7825b400f12d68e" + + solMint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" +) + +func TestTokenStorageKey_CaseVariantsConverge(t *testing.T) { + want := types.GetTokenConfigsStorageKey(canonChainEVM, tokenEIP55) + for _, variant := range []string{tokenLower, tokenUpper, " " + tokenEIP55 + " "} { + require.Equal(t, want, types.GetTokenConfigsStorageKey(canonChainEVM, variant), + "variant %q must map to the canonical storage key", variant) + } + require.Contains(t, want, tokenEIP55, "canonical key embeds the EIP-55 form") +} + +func TestTokenStorageKey_SolanaBase58Preserved(t *testing.T) { + key := types.GetTokenConfigsStorageKey(canonChainSol, solMint) + require.Contains(t, key, solMint, "base58 mint must be preserved byte-for-byte (case-significant)") +} + +func TestGetTokenConfig_CrossCaseLookup(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + + // Registered with lowercase; readable via any variant. + cfg := makeTokenCfg(canonChainEVM, tokenLower, prc20EIP55) + require.NoError(t, k.TokenConfigs.Set(ctx, types.GetTokenConfigsStorageKey(cfg.Chain, cfg.Address), cfg)) + + for _, variant := range []string{tokenEIP55, tokenLower, tokenUpper} { + got, err := k.GetTokenConfig(ctx, canonChainEVM, variant) + require.NoError(t, err, "lookup with %q must hit the canonical row", variant) + require.Equal(t, tokenLower, got.Address) + } +} + +func TestAddTokenConfig_DuplicateCaseVariantRejected(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + + // AddTokenConfig requires the chain to be registered. + require.NoError(t, k.ChainConfigs.Set(ctx, canonChainEVM, types.ChainConfig{Chain: canonChainEVM})) + + first := makeTokenCfg(canonChainEVM, tokenEIP55, prc20EIP55) + require.NoError(t, k.AddTokenConfig(ctx, &first)) + + // Same address, different case → same canonical key → duplicate. + dup := makeTokenCfg(canonChainEVM, tokenLower, prc20EIP55) + err := k.AddTokenConfig(ctx, &dup) + require.Error(t, err) + require.Contains(t, err.Error(), "already exists", + "case-variant duplicate registration must collide on the canonical key") +} + +func TestRemoveTokenConfig_CrossCaseRemoval(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + require.NoError(t, k.ChainConfigs.Set(ctx, canonChainEVM, types.ChainConfig{Chain: canonChainEVM})) + + cfg := makeTokenCfg(canonChainEVM, tokenEIP55, prc20EIP55) + require.NoError(t, k.AddTokenConfig(ctx, &cfg)) + + // Remove using the all-lowercase variant — must target the same row. + require.NoError(t, k.RemoveTokenConfig(ctx, canonChainEVM, tokenLower)) + + _, err := k.GetTokenConfig(ctx, canonChainEVM, tokenEIP55) + require.Error(t, err, "row must be gone regardless of removal-key casing") +} + +func TestGetTokenConfigByPRC20_RealHexEIP55Index(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + + // Stored with lowercase PRC20 — index canonicalizes to EIP-55. + cfg := makeTokenCfg(canonChainEVM, tokenEIP55, prc20Lower) + require.NoError(t, k.TokenConfigs.Set(ctx, types.GetTokenConfigsStorageKey(cfg.Chain, cfg.Address), cfg)) + + for _, query := range []string{prc20EIP55, prc20Lower, "0X387B9C8DB60E74999AAAC5A2B7825B400F12D68E"} { + got, err := k.GetTokenConfigByPRC20(ctx, canonChainEVM, query) + require.NoError(t, err, "PRC20 lookup with %q must resolve via EIP-55 index", query) + require.Equal(t, tokenEIP55, got.Address) + } +} diff --git a/x/uregistry/keeper/keeper.go b/x/uregistry/keeper/keeper.go index b4388d13d..5ca94c248 100755 --- a/x/uregistry/keeper/keeper.go +++ b/x/uregistry/keeper/keeper.go @@ -17,11 +17,12 @@ import ( "cosmossdk.io/collections/indexes" storetypes "cosmossdk.io/core/store" "cosmossdk.io/log" + "github.com/pushchain/push-chain-node/utils" "github.com/pushchain/push-chain-node/x/uregistry/types" ) -// TokenConfigIndexes: PRC20Index maps lowercased PRC20 contract address → -// token storage key for O(1) GetTokenConfigByPRC20. Rows without +// TokenConfigIndexes: PRC20Index maps canonical (EIP-55) PRC20 contract +// address → token storage key for O(1) GetTokenConfigByPRC20. Rows without // NativeRepresentation index under the empty-string sentinel which is never // queried. Framework auto-maintains on every Set/Remove. type TokenConfigIndexes struct { @@ -32,6 +33,17 @@ func (t TokenConfigIndexes) IndexesList() []collections.Index[string, types.Toke return []collections.Index[string, types.TokenConfig]{t.PRC20Index} } +// canonicalPRC20 returns the EIP-55 form of a PRC20 address (PRC20s are EVM). +// Lenient (falls back to lowercase-trim) so index writes never fail; strict +// enforcement is in NativeRepresentation.ValidateBasic. +func canonicalPRC20(addr string) string { + canon, err := utils.CanonicalizeEVMAddress(addr) + if err != nil { + return strings.ToLower(strings.TrimSpace(addr)) + } + return canon +} + func newTokenConfigIndexes(sb *collections.SchemaBuilder) TokenConfigIndexes { return TokenConfigIndexes{ PRC20Index: indexes.NewMulti( @@ -41,7 +53,7 @@ func newTokenConfigIndexes(sb *collections.SchemaBuilder) TokenConfigIndexes { if v.NativeRepresentation == nil || v.NativeRepresentation.ContractAddress == "" { return "", nil // sentinel — non-PRC20 rows } - return strings.ToLower(v.NativeRepresentation.ContractAddress), nil + return canonicalPRC20(v.NativeRepresentation.ContractAddress), nil }, ), } @@ -233,10 +245,11 @@ func (k Keeper) GetTokenConfigByPRC20( prc20Addr string, ) (types.TokenConfig, error) { - prc20Addr = strings.ToLower(strings.TrimSpace(prc20Addr)) - if prc20Addr == "" { + if strings.TrimSpace(prc20Addr) == "" { return types.TokenConfig{}, fmt.Errorf("prc20 address is empty") } + // Same canonical form as the index function, so any case variant hits the row. + prc20Addr = canonicalPRC20(prc20Addr) // PRC20 addresses are globally unique by construction; MatchExact returns at most one. iter, err := k.TokenConfigs.Indexes.PRC20Index.MatchExact(ctx, prc20Addr) diff --git a/x/uregistry/types/keys.go b/x/uregistry/types/keys.go index ea13eec77..257ad8134 100755 --- a/x/uregistry/types/keys.go +++ b/x/uregistry/types/keys.go @@ -5,6 +5,8 @@ import ( "strings" "cosmossdk.io/collections" + + "github.com/pushchain/push-chain-node/utils" ) var ( @@ -26,7 +28,7 @@ var ( // TokenConfigsName is the name of the tokenConfigs collection. TokenConfigsName = "token_configs" - // PRC20Index secondary index on TokenConfigs: lowercased PRC20 → storage key. + // PRC20Index secondary index on TokenConfigs: canonical (EIP-55) PRC20 → storage key. PRC20IndexKey = collections.NewPrefix(3) PRC20IndexName = "prc20_index" ) @@ -39,7 +41,19 @@ const ( QuerierRoute = ModuleName ) -// GetTokenConfigsStorageKey returns the storage key for token config storage in the format "chain:address". +// GetTokenConfigsStorageKey builds the "chain:address" key with the address +// canonicalized per namespace, so case variants map to one row. Strict format +// enforcement is in TokenConfig.ValidateBasic. func GetTokenConfigsStorageKey(chain, address string) string { - return fmt.Sprintf("%s:%s", chain, strings.TrimSpace(address)) + return fmt.Sprintf("%s:%s", chain, CanonicalTokenAddress(chain, address)) +} + +// CanonicalTokenAddress is the lenient canonicalizer used for key paths: +// canonical form when the address parses, trimmed input otherwise. +func CanonicalTokenAddress(chain, address string) string { + canon, err := utils.CanonicalizeAddressByNamespace(chain, address) + if err != nil { + return strings.TrimSpace(address) + } + return canon } diff --git a/x/uregistry/types/msg_add_token_config_test.go b/x/uregistry/types/msg_add_token_config_test.go index dd8e64666..b4b5f1cd8 100644 --- a/x/uregistry/types/msg_add_token_config_test.go +++ b/x/uregistry/types/msg_add_token_config_test.go @@ -13,7 +13,7 @@ func TestMsgAddTokenConfig_ValidateBasic(t *testing.T) { validTokenConfig := &types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -28,7 +28,7 @@ func TestMsgAddTokenConfig_ValidateBasic(t *testing.T) { invalidTokenConfig := &types.TokenConfig{ Chain: "", // invalid - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, diff --git a/x/uregistry/types/msg_update_token_config_test.go b/x/uregistry/types/msg_update_token_config_test.go index 97c9cff94..5cbe78c17 100644 --- a/x/uregistry/types/msg_update_token_config_test.go +++ b/x/uregistry/types/msg_update_token_config_test.go @@ -13,7 +13,7 @@ func TestMsgUpdateTokenConfig_ValidateBasic(t *testing.T) { validTokenConfig := &types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -28,7 +28,7 @@ func TestMsgUpdateTokenConfig_ValidateBasic(t *testing.T) { invalidTokenConfig := &types.TokenConfig{ Chain: "", // invalid - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, diff --git a/x/uregistry/types/native_represenation_test.go b/x/uregistry/types/native_represenation_test.go index aa603fcde..1196a1df8 100644 --- a/x/uregistry/types/native_represenation_test.go +++ b/x/uregistry/types/native_represenation_test.go @@ -34,7 +34,7 @@ func TestNativeRepresentation_ValidateBasic(t *testing.T) { name: "valid - only contract_address set with 0x", nativeRep: types.NativeRepresentation{ Denom: "", - ContractAddress: "0xabc123def4567890", + ContractAddress: "0x387b9C8Db60E74999aAAC5A2b7825b400F12d68E", }, expectErr: false, }, @@ -42,7 +42,7 @@ func TestNativeRepresentation_ValidateBasic(t *testing.T) { name: "valid - both denom and contract_address set", nativeRep: types.NativeRepresentation{ Denom: "uatom", - ContractAddress: "0xdeadbeefcafebabe", + ContractAddress: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", }, expectErr: false, }, diff --git a/x/uregistry/types/native_representation.go b/x/uregistry/types/native_representation.go index 597de4d19..242f524e7 100644 --- a/x/uregistry/types/native_representation.go +++ b/x/uregistry/types/native_representation.go @@ -6,6 +6,8 @@ import ( "cosmossdk.io/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/pushchain/push-chain-node/utils" ) // Stringer method for NativeRepresentation @@ -30,5 +32,13 @@ func (p NativeRepresentation) ValidateBasic() error { return errors.Wrap(sdkerrors.ErrInvalidRequest, "contract_address must start with 0x") } + // PRC20s live on Push Chain (EVM): must be a parseable 20-byte hex address + // so the PRC20 reverse index always carries the canonical EIP-55 form. + if p.ContractAddress != "" { + if _, err := utils.CanonicalizeEVMAddress(p.ContractAddress); err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid contract_address: %s", err) + } + } + return nil } diff --git a/x/uregistry/types/token_config.go b/x/uregistry/types/token_config.go index db46ff1d5..7483a11f7 100644 --- a/x/uregistry/types/token_config.go +++ b/x/uregistry/types/token_config.go @@ -6,6 +6,8 @@ import ( "cosmossdk.io/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/pushchain/push-chain-node/utils" ) // Stringer method for TokenConfig @@ -27,6 +29,13 @@ func (p TokenConfig) ValidateBasic() error { return errors.Wrap(sdkerrors.ErrInvalidRequest, "token contract address cannot be empty") } + // Enforce a parseable address for the chain's namespace (e.g. 20-byte hex + // for eip155, base58 for solana) so every registration lands on the + // canonical storage key. + if _, err := utils.CanonicalizeAddressByNamespace(p.Chain, p.Address); err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid token address for chain %s: %s", p.Chain, err) + } + if strings.TrimSpace(p.Name) == "" { return errors.Wrap(sdkerrors.ErrInvalidRequest, "token name cannot be empty") } diff --git a/x/uregistry/types/token_config_test.go b/x/uregistry/types/token_config_test.go index b2b6d8d22..c1cc24629 100644 --- a/x/uregistry/types/token_config_test.go +++ b/x/uregistry/types/token_config_test.go @@ -23,7 +23,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "valid token config", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -38,7 +38,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "missing chain", config: types.TokenConfig{ Chain: "", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -68,7 +68,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "zero decimals", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 0, @@ -83,7 +83,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "invalid token type", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -98,7 +98,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "missing liquidity cap", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -113,7 +113,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "invalid native representation contract address", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, diff --git a/x/utss/keeper/msg_vote_fund_migration.go b/x/utss/keeper/msg_vote_fund_migration.go index 00292c2db..8bbd1a6d5 100644 --- a/x/utss/keeper/msg_vote_fund_migration.go +++ b/x/utss/keeper/msg_vote_fund_migration.go @@ -6,6 +6,7 @@ import ( "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pushchain/push-chain-node/utils" "github.com/pushchain/push-chain-node/x/utss/types" ) @@ -28,6 +29,13 @@ func (k Keeper) VoteFundMigration( return fmt.Errorf("fund migration %d is already finalized (status: %s)", migrationId, migration.Status.String()) } + // Canonicalize the observed txHash for the migration's chain so encoding + // variants (case, 0x prefix) from different validators land on one ballot. + txHash, err = utils.CanonicalizeTxHashByNamespace(migration.Chain, txHash) + if err != nil { + return fmt.Errorf("invalid tx hash for chain %s: %w", migration.Chain, err) + } + k.Logger().Info("fund migration vote received", "migration_id", migrationId, "validator", universalValidator.String(), diff --git a/x/utss/types/msg_vote_fund_migration.go b/x/utss/types/msg_vote_fund_migration.go new file mode 100644 index 000000000..d06739a28 --- /dev/null +++ b/x/utss/types/msg_vote_fund_migration.go @@ -0,0 +1,28 @@ +package types + +import ( + "strings" + + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ sdk.Msg = &MsgVoteFundMigration{} + +// ValidateBasic does a sanity check on the provided data. +func (msg *MsgVoteFundMigration) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Signer); err != nil { + return errors.Wrap(err, "invalid signer address") + } + if msg.MigrationId == 0 { + return errors.Wrap(sdkerrors.ErrInvalidRequest, "migration_id is required") + } + // A successful migration observation must carry the external tx hash. + // Canonicalization (per the migration's chain namespace) happens in the + // keeper, where the chain is known. + if msg.Success && strings.TrimSpace(msg.TxHash) == "" { + return errors.Wrap(sdkerrors.ErrInvalidRequest, "tx_hash is required when success is true") + } + return nil +}