diff --git a/api/uexecutor/v1/chain_meta.pulsar.go b/api/uexecutor/v1/chain_meta.pulsar.go new file mode 100644 index 00000000..598df694 --- /dev/null +++ b/api/uexecutor/v1/chain_meta.pulsar.go @@ -0,0 +1,1397 @@ +// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. +package uexecutorv1 + +import ( + _ "cosmossdk.io/api/amino" + fmt "fmt" + runtime "github.com/cosmos/cosmos-proto/runtime" + _ "github.com/cosmos/gogoproto/gogoproto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoiface "google.golang.org/protobuf/runtime/protoiface" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" + reflect "reflect" + sync "sync" +) + +var _ protoreflect.List = (*_ChainMeta_2_list)(nil) + +type _ChainMeta_2_list struct { + list *[]string +} + +func (x *_ChainMeta_2_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_ChainMeta_2_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfString((*x.list)[i]) +} + +func (x *_ChainMeta_2_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + (*x.list)[i] = concreteValue +} + +func (x *_ChainMeta_2_list) Append(value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + *x.list = append(*x.list, concreteValue) +} + +func (x *_ChainMeta_2_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message ChainMeta at list field Signers as it is not of Message kind")) +} + +func (x *_ChainMeta_2_list) Truncate(n int) { + *x.list = (*x.list)[:n] +} + +func (x *_ChainMeta_2_list) NewElement() protoreflect.Value { + v := "" + return protoreflect.ValueOfString(v) +} + +func (x *_ChainMeta_2_list) IsValid() bool { + return x.list != nil +} + +var _ protoreflect.List = (*_ChainMeta_3_list)(nil) + +type _ChainMeta_3_list struct { + list *[]uint64 +} + +func (x *_ChainMeta_3_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_ChainMeta_3_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfUint64((*x.list)[i]) +} + +func (x *_ChainMeta_3_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.Uint() + concreteValue := valueUnwrapped + (*x.list)[i] = concreteValue +} + +func (x *_ChainMeta_3_list) Append(value protoreflect.Value) { + valueUnwrapped := value.Uint() + concreteValue := valueUnwrapped + *x.list = append(*x.list, concreteValue) +} + +func (x *_ChainMeta_3_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message ChainMeta at list field Prices as it is not of Message kind")) +} + +func (x *_ChainMeta_3_list) Truncate(n int) { + *x.list = (*x.list)[:n] +} + +func (x *_ChainMeta_3_list) NewElement() protoreflect.Value { + v := uint64(0) + return protoreflect.ValueOfUint64(v) +} + +func (x *_ChainMeta_3_list) IsValid() bool { + return x.list != nil +} + +var _ protoreflect.List = (*_ChainMeta_4_list)(nil) + +type _ChainMeta_4_list struct { + list *[]uint64 +} + +func (x *_ChainMeta_4_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_ChainMeta_4_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfUint64((*x.list)[i]) +} + +func (x *_ChainMeta_4_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.Uint() + concreteValue := valueUnwrapped + (*x.list)[i] = concreteValue +} + +func (x *_ChainMeta_4_list) Append(value protoreflect.Value) { + valueUnwrapped := value.Uint() + concreteValue := valueUnwrapped + *x.list = append(*x.list, concreteValue) +} + +func (x *_ChainMeta_4_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message ChainMeta at list field ChainHeights as it is not of Message kind")) +} + +func (x *_ChainMeta_4_list) Truncate(n int) { + *x.list = (*x.list)[:n] +} + +func (x *_ChainMeta_4_list) NewElement() protoreflect.Value { + v := uint64(0) + return protoreflect.ValueOfUint64(v) +} + +func (x *_ChainMeta_4_list) IsValid() bool { + return x.list != nil +} + +var _ protoreflect.List = (*_ChainMeta_5_list)(nil) + +type _ChainMeta_5_list struct { + list *[]uint64 +} + +func (x *_ChainMeta_5_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_ChainMeta_5_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfUint64((*x.list)[i]) +} + +func (x *_ChainMeta_5_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.Uint() + concreteValue := valueUnwrapped + (*x.list)[i] = concreteValue +} + +func (x *_ChainMeta_5_list) Append(value protoreflect.Value) { + valueUnwrapped := value.Uint() + concreteValue := valueUnwrapped + *x.list = append(*x.list, concreteValue) +} + +func (x *_ChainMeta_5_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message ChainMeta at list field StoredAts as it is not of Message kind")) +} + +func (x *_ChainMeta_5_list) Truncate(n int) { + *x.list = (*x.list)[:n] +} + +func (x *_ChainMeta_5_list) NewElement() protoreflect.Value { + v := uint64(0) + return protoreflect.ValueOfUint64(v) +} + +func (x *_ChainMeta_5_list) IsValid() bool { + return x.list != nil +} + +var ( + md_ChainMeta protoreflect.MessageDescriptor + fd_ChainMeta_observed_chain_id protoreflect.FieldDescriptor + fd_ChainMeta_signers protoreflect.FieldDescriptor + fd_ChainMeta_prices protoreflect.FieldDescriptor + fd_ChainMeta_chain_heights protoreflect.FieldDescriptor + fd_ChainMeta_stored_ats protoreflect.FieldDescriptor + fd_ChainMeta_median_index protoreflect.FieldDescriptor + fd_ChainMeta_last_applied_chain_height protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_chain_meta_proto_init() + md_ChainMeta = File_uexecutor_v1_chain_meta_proto.Messages().ByName("ChainMeta") + fd_ChainMeta_observed_chain_id = md_ChainMeta.Fields().ByName("observed_chain_id") + fd_ChainMeta_signers = md_ChainMeta.Fields().ByName("signers") + fd_ChainMeta_prices = md_ChainMeta.Fields().ByName("prices") + fd_ChainMeta_chain_heights = md_ChainMeta.Fields().ByName("chain_heights") + fd_ChainMeta_stored_ats = md_ChainMeta.Fields().ByName("stored_ats") + fd_ChainMeta_median_index = md_ChainMeta.Fields().ByName("median_index") + fd_ChainMeta_last_applied_chain_height = md_ChainMeta.Fields().ByName("last_applied_chain_height") +} + +var _ protoreflect.Message = (*fastReflection_ChainMeta)(nil) + +type fastReflection_ChainMeta ChainMeta + +func (x *ChainMeta) ProtoReflect() protoreflect.Message { + return (*fastReflection_ChainMeta)(x) +} + +func (x *ChainMeta) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_chain_meta_proto_msgTypes[0] + 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_ChainMeta_messageType fastReflection_ChainMeta_messageType +var _ protoreflect.MessageType = fastReflection_ChainMeta_messageType{} + +type fastReflection_ChainMeta_messageType struct{} + +func (x fastReflection_ChainMeta_messageType) Zero() protoreflect.Message { + return (*fastReflection_ChainMeta)(nil) +} +func (x fastReflection_ChainMeta_messageType) New() protoreflect.Message { + return new(fastReflection_ChainMeta) +} +func (x fastReflection_ChainMeta_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_ChainMeta +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_ChainMeta) Descriptor() protoreflect.MessageDescriptor { + return md_ChainMeta +} + +// 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_ChainMeta) Type() protoreflect.MessageType { + return _fastReflection_ChainMeta_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_ChainMeta) New() protoreflect.Message { + return new(fastReflection_ChainMeta) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_ChainMeta) Interface() protoreflect.ProtoMessage { + return (*ChainMeta)(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_ChainMeta) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ObservedChainId != "" { + value := protoreflect.ValueOfString(x.ObservedChainId) + if !f(fd_ChainMeta_observed_chain_id, value) { + return + } + } + if len(x.Signers) != 0 { + value := protoreflect.ValueOfList(&_ChainMeta_2_list{list: &x.Signers}) + if !f(fd_ChainMeta_signers, value) { + return + } + } + if len(x.Prices) != 0 { + value := protoreflect.ValueOfList(&_ChainMeta_3_list{list: &x.Prices}) + if !f(fd_ChainMeta_prices, value) { + return + } + } + if len(x.ChainHeights) != 0 { + value := protoreflect.ValueOfList(&_ChainMeta_4_list{list: &x.ChainHeights}) + if !f(fd_ChainMeta_chain_heights, value) { + return + } + } + if len(x.StoredAts) != 0 { + value := protoreflect.ValueOfList(&_ChainMeta_5_list{list: &x.StoredAts}) + if !f(fd_ChainMeta_stored_ats, value) { + return + } + } + if x.MedianIndex != uint64(0) { + value := protoreflect.ValueOfUint64(x.MedianIndex) + if !f(fd_ChainMeta_median_index, value) { + return + } + } + if x.LastAppliedChainHeight != uint64(0) { + value := protoreflect.ValueOfUint64(x.LastAppliedChainHeight) + if !f(fd_ChainMeta_last_applied_chain_height, 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_ChainMeta) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.ChainMeta.observed_chain_id": + return x.ObservedChainId != "" + case "uexecutor.v1.ChainMeta.signers": + return len(x.Signers) != 0 + case "uexecutor.v1.ChainMeta.prices": + return len(x.Prices) != 0 + case "uexecutor.v1.ChainMeta.chain_heights": + return len(x.ChainHeights) != 0 + case "uexecutor.v1.ChainMeta.stored_ats": + return len(x.StoredAts) != 0 + case "uexecutor.v1.ChainMeta.median_index": + return x.MedianIndex != uint64(0) + case "uexecutor.v1.ChainMeta.last_applied_chain_height": + return x.LastAppliedChainHeight != uint64(0) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.ChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.ChainMeta 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_ChainMeta) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.ChainMeta.observed_chain_id": + x.ObservedChainId = "" + case "uexecutor.v1.ChainMeta.signers": + x.Signers = nil + case "uexecutor.v1.ChainMeta.prices": + x.Prices = nil + case "uexecutor.v1.ChainMeta.chain_heights": + x.ChainHeights = nil + case "uexecutor.v1.ChainMeta.stored_ats": + x.StoredAts = nil + case "uexecutor.v1.ChainMeta.median_index": + x.MedianIndex = uint64(0) + case "uexecutor.v1.ChainMeta.last_applied_chain_height": + x.LastAppliedChainHeight = uint64(0) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.ChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.ChainMeta 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_ChainMeta) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.ChainMeta.observed_chain_id": + value := x.ObservedChainId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.ChainMeta.signers": + if len(x.Signers) == 0 { + return protoreflect.ValueOfList(&_ChainMeta_2_list{}) + } + listValue := &_ChainMeta_2_list{list: &x.Signers} + return protoreflect.ValueOfList(listValue) + case "uexecutor.v1.ChainMeta.prices": + if len(x.Prices) == 0 { + return protoreflect.ValueOfList(&_ChainMeta_3_list{}) + } + listValue := &_ChainMeta_3_list{list: &x.Prices} + return protoreflect.ValueOfList(listValue) + case "uexecutor.v1.ChainMeta.chain_heights": + if len(x.ChainHeights) == 0 { + return protoreflect.ValueOfList(&_ChainMeta_4_list{}) + } + listValue := &_ChainMeta_4_list{list: &x.ChainHeights} + return protoreflect.ValueOfList(listValue) + case "uexecutor.v1.ChainMeta.stored_ats": + if len(x.StoredAts) == 0 { + return protoreflect.ValueOfList(&_ChainMeta_5_list{}) + } + listValue := &_ChainMeta_5_list{list: &x.StoredAts} + return protoreflect.ValueOfList(listValue) + case "uexecutor.v1.ChainMeta.median_index": + value := x.MedianIndex + return protoreflect.ValueOfUint64(value) + case "uexecutor.v1.ChainMeta.last_applied_chain_height": + value := x.LastAppliedChainHeight + return protoreflect.ValueOfUint64(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.ChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.ChainMeta 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_ChainMeta) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.ChainMeta.observed_chain_id": + x.ObservedChainId = value.Interface().(string) + case "uexecutor.v1.ChainMeta.signers": + lv := value.List() + clv := lv.(*_ChainMeta_2_list) + x.Signers = *clv.list + case "uexecutor.v1.ChainMeta.prices": + lv := value.List() + clv := lv.(*_ChainMeta_3_list) + x.Prices = *clv.list + case "uexecutor.v1.ChainMeta.chain_heights": + lv := value.List() + clv := lv.(*_ChainMeta_4_list) + x.ChainHeights = *clv.list + case "uexecutor.v1.ChainMeta.stored_ats": + lv := value.List() + clv := lv.(*_ChainMeta_5_list) + x.StoredAts = *clv.list + case "uexecutor.v1.ChainMeta.median_index": + x.MedianIndex = value.Uint() + case "uexecutor.v1.ChainMeta.last_applied_chain_height": + x.LastAppliedChainHeight = value.Uint() + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.ChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.ChainMeta 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_ChainMeta) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.ChainMeta.signers": + if x.Signers == nil { + x.Signers = []string{} + } + value := &_ChainMeta_2_list{list: &x.Signers} + return protoreflect.ValueOfList(value) + case "uexecutor.v1.ChainMeta.prices": + if x.Prices == nil { + x.Prices = []uint64{} + } + value := &_ChainMeta_3_list{list: &x.Prices} + return protoreflect.ValueOfList(value) + case "uexecutor.v1.ChainMeta.chain_heights": + if x.ChainHeights == nil { + x.ChainHeights = []uint64{} + } + value := &_ChainMeta_4_list{list: &x.ChainHeights} + return protoreflect.ValueOfList(value) + case "uexecutor.v1.ChainMeta.stored_ats": + if x.StoredAts == nil { + x.StoredAts = []uint64{} + } + value := &_ChainMeta_5_list{list: &x.StoredAts} + return protoreflect.ValueOfList(value) + case "uexecutor.v1.ChainMeta.observed_chain_id": + panic(fmt.Errorf("field observed_chain_id of message uexecutor.v1.ChainMeta is not mutable")) + case "uexecutor.v1.ChainMeta.median_index": + panic(fmt.Errorf("field median_index of message uexecutor.v1.ChainMeta is not mutable")) + case "uexecutor.v1.ChainMeta.last_applied_chain_height": + panic(fmt.Errorf("field last_applied_chain_height of message uexecutor.v1.ChainMeta is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.ChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.ChainMeta 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_ChainMeta) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.ChainMeta.observed_chain_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.ChainMeta.signers": + list := []string{} + return protoreflect.ValueOfList(&_ChainMeta_2_list{list: &list}) + case "uexecutor.v1.ChainMeta.prices": + list := []uint64{} + return protoreflect.ValueOfList(&_ChainMeta_3_list{list: &list}) + case "uexecutor.v1.ChainMeta.chain_heights": + list := []uint64{} + return protoreflect.ValueOfList(&_ChainMeta_4_list{list: &list}) + case "uexecutor.v1.ChainMeta.stored_ats": + list := []uint64{} + return protoreflect.ValueOfList(&_ChainMeta_5_list{list: &list}) + case "uexecutor.v1.ChainMeta.median_index": + return protoreflect.ValueOfUint64(uint64(0)) + case "uexecutor.v1.ChainMeta.last_applied_chain_height": + return protoreflect.ValueOfUint64(uint64(0)) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.ChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.ChainMeta 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_ChainMeta) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.ChainMeta", 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_ChainMeta) 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_ChainMeta) 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_ChainMeta) 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_ChainMeta) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*ChainMeta) + 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.ObservedChainId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if len(x.Signers) > 0 { + for _, s := range x.Signers { + l = len(s) + n += 1 + l + runtime.Sov(uint64(l)) + } + } + if len(x.Prices) > 0 { + l = 0 + for _, e := range x.Prices { + l += runtime.Sov(uint64(e)) + } + n += 1 + runtime.Sov(uint64(l)) + l + } + if len(x.ChainHeights) > 0 { + l = 0 + for _, e := range x.ChainHeights { + l += runtime.Sov(uint64(e)) + } + n += 1 + runtime.Sov(uint64(l)) + l + } + if len(x.StoredAts) > 0 { + l = 0 + for _, e := range x.StoredAts { + l += runtime.Sov(uint64(e)) + } + n += 1 + runtime.Sov(uint64(l)) + l + } + if x.MedianIndex != 0 { + n += 1 + runtime.Sov(uint64(x.MedianIndex)) + } + if x.LastAppliedChainHeight != 0 { + n += 1 + runtime.Sov(uint64(x.LastAppliedChainHeight)) + } + 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().(*ChainMeta) + 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.LastAppliedChainHeight != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.LastAppliedChainHeight)) + i-- + dAtA[i] = 0x38 + } + if x.MedianIndex != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.MedianIndex)) + i-- + dAtA[i] = 0x30 + } + if len(x.StoredAts) > 0 { + var pksize2 int + for _, num := range x.StoredAts { + pksize2 += runtime.Sov(uint64(num)) + } + i -= pksize2 + j1 := i + for _, num := range x.StoredAts { + for num >= 1<<7 { + dAtA[j1] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j1++ + } + dAtA[j1] = uint8(num) + j1++ + } + i = runtime.EncodeVarint(dAtA, i, uint64(pksize2)) + i-- + dAtA[i] = 0x2a + } + if len(x.ChainHeights) > 0 { + var pksize4 int + for _, num := range x.ChainHeights { + pksize4 += runtime.Sov(uint64(num)) + } + i -= pksize4 + j3 := i + for _, num := range x.ChainHeights { + for num >= 1<<7 { + dAtA[j3] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j3++ + } + dAtA[j3] = uint8(num) + j3++ + } + i = runtime.EncodeVarint(dAtA, i, uint64(pksize4)) + i-- + dAtA[i] = 0x22 + } + if len(x.Prices) > 0 { + var pksize6 int + for _, num := range x.Prices { + pksize6 += runtime.Sov(uint64(num)) + } + i -= pksize6 + j5 := i + for _, num := range x.Prices { + for num >= 1<<7 { + dAtA[j5] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j5++ + } + dAtA[j5] = uint8(num) + j5++ + } + i = runtime.EncodeVarint(dAtA, i, uint64(pksize6)) + i-- + dAtA[i] = 0x1a + } + if len(x.Signers) > 0 { + for iNdEx := len(x.Signers) - 1; iNdEx >= 0; iNdEx-- { + i -= len(x.Signers[iNdEx]) + copy(dAtA[i:], x.Signers[iNdEx]) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Signers[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(x.ObservedChainId) > 0 { + i -= len(x.ObservedChainId) + copy(dAtA[i:], x.ObservedChainId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ObservedChainId))) + 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().(*ChainMeta) + 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: ChainMeta: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ChainMeta: 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 ObservedChainId", 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.ObservedChainId = 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 Signers", 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.Signers = append(x.Signers, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: + if wireType == 0 { + var v 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++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + x.Prices = append(x.Prices, v) + } else if wireType == 2 { + var packedLen 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++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + packedLen + 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 + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(x.Prices) == 0 { + x.Prices = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v 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++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + x.Prices = append(x.Prices, v) + } + } else { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Prices", wireType) + } + case 4: + if wireType == 0 { + var v 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++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + x.ChainHeights = append(x.ChainHeights, v) + } else if wireType == 2 { + var packedLen 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++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + packedLen + 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 + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(x.ChainHeights) == 0 { + x.ChainHeights = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v 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++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + x.ChainHeights = append(x.ChainHeights, v) + } + } else { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ChainHeights", wireType) + } + case 5: + if wireType == 0 { + var v 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++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + x.StoredAts = append(x.StoredAts, v) + } else if wireType == 2 { + var packedLen 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++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + packedLen + 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 + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(x.StoredAts) == 0 { + x.StoredAts = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v 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++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + x.StoredAts = append(x.StoredAts, v) + } + } else { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field StoredAts", wireType) + } + case 6: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field MedianIndex", wireType) + } + x.MedianIndex = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.MedianIndex |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field LastAppliedChainHeight", wireType) + } + x.LastAppliedChainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.LastAppliedChainHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 +// protoc (unknown) +// source: uexecutor/v1/chain_meta.proto + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// ChainMeta stores aggregated chain metadata (gas price + block height) for a given chain +type ChainMeta struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ObservedChainId string `protobuf:"bytes,1,opt,name=observed_chain_id,json=observedChainId,proto3" json:"observed_chain_id,omitempty"` // chain ID of observed external chain (e.g. "eip155:1" for ethereum mainnet) + Signers []string `protobuf:"bytes,2,rep,name=signers,proto3" json:"signers,omitempty"` // Validators who submitted votes + Prices []uint64 `protobuf:"varint,3,rep,packed,name=prices,proto3" json:"prices,omitempty"` // Submitted gas prices + ChainHeights []uint64 `protobuf:"varint,4,rep,packed,name=chain_heights,json=chainHeights,proto3" json:"chain_heights,omitempty"` // Block heights corresponding to each price observation + StoredAts []uint64 `protobuf:"varint,5,rep,packed,name=stored_ats,json=storedAts,proto3" json:"stored_ats,omitempty"` // Block time (unix seconds) when each vote was last stored/updated + MedianIndex uint64 `protobuf:"varint,6,opt,name=median_index,json=medianIndex,proto3" json:"median_index,omitempty"` // Index of the median price in 'prices' + LastAppliedChainHeight uint64 `protobuf:"varint,7,opt,name=last_applied_chain_height,json=lastAppliedChainHeight,proto3" json:"last_applied_chain_height,omitempty"` // Chain height of last successful EVM setChainMeta call +} + +func (x *ChainMeta) Reset() { + *x = ChainMeta{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_chain_meta_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChainMeta) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChainMeta) ProtoMessage() {} + +// Deprecated: Use ChainMeta.ProtoReflect.Descriptor instead. +func (*ChainMeta) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_chain_meta_proto_rawDescGZIP(), []int{0} +} + +func (x *ChainMeta) GetObservedChainId() string { + if x != nil { + return x.ObservedChainId + } + return "" +} + +func (x *ChainMeta) GetSigners() []string { + if x != nil { + return x.Signers + } + return nil +} + +func (x *ChainMeta) GetPrices() []uint64 { + if x != nil { + return x.Prices + } + return nil +} + +func (x *ChainMeta) GetChainHeights() []uint64 { + if x != nil { + return x.ChainHeights + } + return nil +} + +func (x *ChainMeta) GetStoredAts() []uint64 { + if x != nil { + return x.StoredAts + } + return nil +} + +func (x *ChainMeta) GetMedianIndex() uint64 { + if x != nil { + return x.MedianIndex + } + return 0 +} + +func (x *ChainMeta) GetLastAppliedChainHeight() uint64 { + if x != nil { + return x.LastAppliedChainHeight + } + return 0 +} + +var File_uexecutor_v1_chain_meta_proto protoreflect.FileDescriptor + +var file_uexecutor_v1_chain_meta_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x0c, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x1a, 0x14, 0x67, + 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xae, 0x02, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, + 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x06, 0x70, 0x72, 0x69, 0x63, + 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x64, 0x41, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, + 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, + 0x64, 0x69, 0x61, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x39, 0x0a, 0x19, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x6c, 0x61, + 0x73, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x3a, 0x21, 0x98, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, + 0xb0, 0x2a, 0x14, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x42, 0xb6, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, + 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 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 ( + file_uexecutor_v1_chain_meta_proto_rawDescOnce sync.Once + file_uexecutor_v1_chain_meta_proto_rawDescData = file_uexecutor_v1_chain_meta_proto_rawDesc +) + +func file_uexecutor_v1_chain_meta_proto_rawDescGZIP() []byte { + file_uexecutor_v1_chain_meta_proto_rawDescOnce.Do(func() { + file_uexecutor_v1_chain_meta_proto_rawDescData = protoimpl.X.CompressGZIP(file_uexecutor_v1_chain_meta_proto_rawDescData) + }) + return file_uexecutor_v1_chain_meta_proto_rawDescData +} + +var file_uexecutor_v1_chain_meta_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_uexecutor_v1_chain_meta_proto_goTypes = []interface{}{ + (*ChainMeta)(nil), // 0: uexecutor.v1.ChainMeta +} +var file_uexecutor_v1_chain_meta_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_uexecutor_v1_chain_meta_proto_init() } +func file_uexecutor_v1_chain_meta_proto_init() { + if File_uexecutor_v1_chain_meta_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_uexecutor_v1_chain_meta_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChainMeta); 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{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_uexecutor_v1_chain_meta_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_uexecutor_v1_chain_meta_proto_goTypes, + DependencyIndexes: file_uexecutor_v1_chain_meta_proto_depIdxs, + MessageInfos: file_uexecutor_v1_chain_meta_proto_msgTypes, + }.Build() + File_uexecutor_v1_chain_meta_proto = out.File + file_uexecutor_v1_chain_meta_proto_rawDesc = nil + file_uexecutor_v1_chain_meta_proto_goTypes = nil + file_uexecutor_v1_chain_meta_proto_depIdxs = nil +} diff --git a/api/uexecutor/v1/query.pulsar.go b/api/uexecutor/v1/query.pulsar.go index 484399eb..55b69539 100644 --- a/api/uexecutor/v1/query.pulsar.go +++ b/api/uexecutor/v1/query.pulsar.go @@ -1877,6 +1877,1869 @@ func (x *fastReflection_QueryAllGasPricesResponse) ProtoMethods() *protoiface.Me } } +var ( + md_QueryChainMetaRequest protoreflect.MessageDescriptor + fd_QueryChainMetaRequest_chain_id protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryChainMetaRequest = File_uexecutor_v1_query_proto.Messages().ByName("QueryChainMetaRequest") + fd_QueryChainMetaRequest_chain_id = md_QueryChainMetaRequest.Fields().ByName("chain_id") +} + +var _ protoreflect.Message = (*fastReflection_QueryChainMetaRequest)(nil) + +type fastReflection_QueryChainMetaRequest QueryChainMetaRequest + +func (x *QueryChainMetaRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryChainMetaRequest)(x) +} + +func (x *QueryChainMetaRequest) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[4] + 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_QueryChainMetaRequest_messageType fastReflection_QueryChainMetaRequest_messageType +var _ protoreflect.MessageType = fastReflection_QueryChainMetaRequest_messageType{} + +type fastReflection_QueryChainMetaRequest_messageType struct{} + +func (x fastReflection_QueryChainMetaRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryChainMetaRequest)(nil) +} +func (x fastReflection_QueryChainMetaRequest_messageType) New() protoreflect.Message { + return new(fastReflection_QueryChainMetaRequest) +} +func (x fastReflection_QueryChainMetaRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryChainMetaRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryChainMetaRequest) Descriptor() protoreflect.MessageDescriptor { + return md_QueryChainMetaRequest +} + +// 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_QueryChainMetaRequest) Type() protoreflect.MessageType { + return _fastReflection_QueryChainMetaRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryChainMetaRequest) New() protoreflect.Message { + return new(fastReflection_QueryChainMetaRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryChainMetaRequest) Interface() protoreflect.ProtoMessage { + return (*QueryChainMetaRequest)(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_QueryChainMetaRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ChainId != "" { + value := protoreflect.ValueOfString(x.ChainId) + if !f(fd_QueryChainMetaRequest_chain_id, 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_QueryChainMetaRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaRequest.chain_id": + return x.ChainId != "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaRequest 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_QueryChainMetaRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaRequest.chain_id": + x.ChainId = "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaRequest 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_QueryChainMetaRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryChainMetaRequest.chain_id": + value := x.ChainId + return protoreflect.ValueOfString(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaRequest 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_QueryChainMetaRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaRequest.chain_id": + x.ChainId = value.Interface().(string) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaRequest 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_QueryChainMetaRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaRequest.chain_id": + panic(fmt.Errorf("field chain_id of message uexecutor.v1.QueryChainMetaRequest is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaRequest 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_QueryChainMetaRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaRequest.chain_id": + return protoreflect.ValueOfString("") + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaRequest 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_QueryChainMetaRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryChainMetaRequest", 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_QueryChainMetaRequest) 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_QueryChainMetaRequest) 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_QueryChainMetaRequest) 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_QueryChainMetaRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryChainMetaRequest) + 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.ChainId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryChainMetaRequest) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.ChainId) > 0 { + i -= len(x.ChainId) + copy(dAtA[i:], x.ChainId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ChainId))) + 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().(*QueryChainMetaRequest) + 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: QueryChainMetaRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryChainMetaRequest: 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 ChainId", 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.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_QueryChainMetaResponse protoreflect.MessageDescriptor + fd_QueryChainMetaResponse_chain_meta protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryChainMetaResponse = File_uexecutor_v1_query_proto.Messages().ByName("QueryChainMetaResponse") + fd_QueryChainMetaResponse_chain_meta = md_QueryChainMetaResponse.Fields().ByName("chain_meta") +} + +var _ protoreflect.Message = (*fastReflection_QueryChainMetaResponse)(nil) + +type fastReflection_QueryChainMetaResponse QueryChainMetaResponse + +func (x *QueryChainMetaResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryChainMetaResponse)(x) +} + +func (x *QueryChainMetaResponse) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[5] + 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_QueryChainMetaResponse_messageType fastReflection_QueryChainMetaResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryChainMetaResponse_messageType{} + +type fastReflection_QueryChainMetaResponse_messageType struct{} + +func (x fastReflection_QueryChainMetaResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryChainMetaResponse)(nil) +} +func (x fastReflection_QueryChainMetaResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryChainMetaResponse) +} +func (x fastReflection_QueryChainMetaResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryChainMetaResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryChainMetaResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryChainMetaResponse +} + +// 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_QueryChainMetaResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryChainMetaResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryChainMetaResponse) New() protoreflect.Message { + return new(fastReflection_QueryChainMetaResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryChainMetaResponse) Interface() protoreflect.ProtoMessage { + return (*QueryChainMetaResponse)(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_QueryChainMetaResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ChainMeta != nil { + value := protoreflect.ValueOfMessage(x.ChainMeta.ProtoReflect()) + if !f(fd_QueryChainMetaResponse_chain_meta, 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_QueryChainMetaResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaResponse.chain_meta": + return x.ChainMeta != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaResponse 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_QueryChainMetaResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaResponse.chain_meta": + x.ChainMeta = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaResponse 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_QueryChainMetaResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryChainMetaResponse.chain_meta": + value := x.ChainMeta + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaResponse 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_QueryChainMetaResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaResponse.chain_meta": + x.ChainMeta = value.Message().Interface().(*ChainMeta) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaResponse 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_QueryChainMetaResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaResponse.chain_meta": + if x.ChainMeta == nil { + x.ChainMeta = new(ChainMeta) + } + return protoreflect.ValueOfMessage(x.ChainMeta.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaResponse 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_QueryChainMetaResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryChainMetaResponse.chain_meta": + m := new(ChainMeta) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryChainMetaResponse 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_QueryChainMetaResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryChainMetaResponse", 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_QueryChainMetaResponse) 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_QueryChainMetaResponse) 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_QueryChainMetaResponse) 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_QueryChainMetaResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryChainMetaResponse) + 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.ChainMeta != nil { + l = options.Size(x.ChainMeta) + 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().(*QueryChainMetaResponse) + 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.ChainMeta != nil { + encoded, err := options.Marshal(x.ChainMeta) + 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().(*QueryChainMetaResponse) + 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: QueryChainMetaResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryChainMetaResponse: 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 ChainMeta", 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.ChainMeta == nil { + x.ChainMeta = &ChainMeta{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.ChainMeta); 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_QueryAllChainMetasRequest protoreflect.MessageDescriptor + fd_QueryAllChainMetasRequest_pagination protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryAllChainMetasRequest = File_uexecutor_v1_query_proto.Messages().ByName("QueryAllChainMetasRequest") + fd_QueryAllChainMetasRequest_pagination = md_QueryAllChainMetasRequest.Fields().ByName("pagination") +} + +var _ protoreflect.Message = (*fastReflection_QueryAllChainMetasRequest)(nil) + +type fastReflection_QueryAllChainMetasRequest QueryAllChainMetasRequest + +func (x *QueryAllChainMetasRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryAllChainMetasRequest)(x) +} + +func (x *QueryAllChainMetasRequest) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[6] + 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_QueryAllChainMetasRequest_messageType fastReflection_QueryAllChainMetasRequest_messageType +var _ protoreflect.MessageType = fastReflection_QueryAllChainMetasRequest_messageType{} + +type fastReflection_QueryAllChainMetasRequest_messageType struct{} + +func (x fastReflection_QueryAllChainMetasRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryAllChainMetasRequest)(nil) +} +func (x fastReflection_QueryAllChainMetasRequest_messageType) New() protoreflect.Message { + return new(fastReflection_QueryAllChainMetasRequest) +} +func (x fastReflection_QueryAllChainMetasRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryAllChainMetasRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryAllChainMetasRequest) Descriptor() protoreflect.MessageDescriptor { + return md_QueryAllChainMetasRequest +} + +// 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_QueryAllChainMetasRequest) Type() protoreflect.MessageType { + return _fastReflection_QueryAllChainMetasRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryAllChainMetasRequest) New() protoreflect.Message { + return new(fastReflection_QueryAllChainMetasRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryAllChainMetasRequest) Interface() protoreflect.ProtoMessage { + return (*QueryAllChainMetasRequest)(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_QueryAllChainMetasRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Pagination != nil { + value := protoreflect.ValueOfMessage(x.Pagination.ProtoReflect()) + if !f(fd_QueryAllChainMetasRequest_pagination, 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_QueryAllChainMetasRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasRequest.pagination": + return x.Pagination != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasRequest 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_QueryAllChainMetasRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasRequest.pagination": + x.Pagination = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasRequest 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_QueryAllChainMetasRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryAllChainMetasRequest.pagination": + value := x.Pagination + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasRequest 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_QueryAllChainMetasRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasRequest.pagination": + x.Pagination = value.Message().Interface().(*v1beta1.PageRequest) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasRequest 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_QueryAllChainMetasRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasRequest.pagination": + if x.Pagination == nil { + x.Pagination = new(v1beta1.PageRequest) + } + return protoreflect.ValueOfMessage(x.Pagination.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasRequest 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_QueryAllChainMetasRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasRequest.pagination": + m := new(v1beta1.PageRequest) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasRequest 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_QueryAllChainMetasRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryAllChainMetasRequest", 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_QueryAllChainMetasRequest) 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_QueryAllChainMetasRequest) 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_QueryAllChainMetasRequest) 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_QueryAllChainMetasRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryAllChainMetasRequest) + 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.Pagination != nil { + l = options.Size(x.Pagination) + 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().(*QueryAllChainMetasRequest) + 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.Pagination != nil { + encoded, err := options.Marshal(x.Pagination) + 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().(*QueryAllChainMetasRequest) + 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: QueryAllChainMetasRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryAllChainMetasRequest: 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 Pagination", 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.Pagination == nil { + x.Pagination = &v1beta1.PageRequest{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Pagination); 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 _ protoreflect.List = (*_QueryAllChainMetasResponse_1_list)(nil) + +type _QueryAllChainMetasResponse_1_list struct { + list *[]*ChainMeta +} + +func (x *_QueryAllChainMetasResponse_1_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_QueryAllChainMetasResponse_1_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfMessage((*x.list)[i].ProtoReflect()) +} + +func (x *_QueryAllChainMetasResponse_1_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*ChainMeta) + (*x.list)[i] = concreteValue +} + +func (x *_QueryAllChainMetasResponse_1_list) Append(value protoreflect.Value) { + valueUnwrapped := value.Message() + concreteValue := valueUnwrapped.Interface().(*ChainMeta) + *x.list = append(*x.list, concreteValue) +} + +func (x *_QueryAllChainMetasResponse_1_list) AppendMutable() protoreflect.Value { + v := new(ChainMeta) + *x.list = append(*x.list, v) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_QueryAllChainMetasResponse_1_list) Truncate(n int) { + for i := n; i < len(*x.list); i++ { + (*x.list)[i] = nil + } + *x.list = (*x.list)[:n] +} + +func (x *_QueryAllChainMetasResponse_1_list) NewElement() protoreflect.Value { + v := new(ChainMeta) + return protoreflect.ValueOfMessage(v.ProtoReflect()) +} + +func (x *_QueryAllChainMetasResponse_1_list) IsValid() bool { + return x.list != nil +} + +var ( + md_QueryAllChainMetasResponse protoreflect.MessageDescriptor + fd_QueryAllChainMetasResponse_chain_metas protoreflect.FieldDescriptor + fd_QueryAllChainMetasResponse_pagination protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryAllChainMetasResponse = File_uexecutor_v1_query_proto.Messages().ByName("QueryAllChainMetasResponse") + fd_QueryAllChainMetasResponse_chain_metas = md_QueryAllChainMetasResponse.Fields().ByName("chain_metas") + fd_QueryAllChainMetasResponse_pagination = md_QueryAllChainMetasResponse.Fields().ByName("pagination") +} + +var _ protoreflect.Message = (*fastReflection_QueryAllChainMetasResponse)(nil) + +type fastReflection_QueryAllChainMetasResponse QueryAllChainMetasResponse + +func (x *QueryAllChainMetasResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryAllChainMetasResponse)(x) +} + +func (x *QueryAllChainMetasResponse) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[7] + 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_QueryAllChainMetasResponse_messageType fastReflection_QueryAllChainMetasResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryAllChainMetasResponse_messageType{} + +type fastReflection_QueryAllChainMetasResponse_messageType struct{} + +func (x fastReflection_QueryAllChainMetasResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryAllChainMetasResponse)(nil) +} +func (x fastReflection_QueryAllChainMetasResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryAllChainMetasResponse) +} +func (x fastReflection_QueryAllChainMetasResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryAllChainMetasResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryAllChainMetasResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryAllChainMetasResponse +} + +// 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_QueryAllChainMetasResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryAllChainMetasResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryAllChainMetasResponse) New() protoreflect.Message { + return new(fastReflection_QueryAllChainMetasResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryAllChainMetasResponse) Interface() protoreflect.ProtoMessage { + return (*QueryAllChainMetasResponse)(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_QueryAllChainMetasResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if len(x.ChainMetas) != 0 { + value := protoreflect.ValueOfList(&_QueryAllChainMetasResponse_1_list{list: &x.ChainMetas}) + if !f(fd_QueryAllChainMetasResponse_chain_metas, value) { + return + } + } + if x.Pagination != nil { + value := protoreflect.ValueOfMessage(x.Pagination.ProtoReflect()) + if !f(fd_QueryAllChainMetasResponse_pagination, 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_QueryAllChainMetasResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasResponse.chain_metas": + return len(x.ChainMetas) != 0 + case "uexecutor.v1.QueryAllChainMetasResponse.pagination": + return x.Pagination != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasResponse 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_QueryAllChainMetasResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasResponse.chain_metas": + x.ChainMetas = nil + case "uexecutor.v1.QueryAllChainMetasResponse.pagination": + x.Pagination = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasResponse 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_QueryAllChainMetasResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryAllChainMetasResponse.chain_metas": + if len(x.ChainMetas) == 0 { + return protoreflect.ValueOfList(&_QueryAllChainMetasResponse_1_list{}) + } + listValue := &_QueryAllChainMetasResponse_1_list{list: &x.ChainMetas} + return protoreflect.ValueOfList(listValue) + case "uexecutor.v1.QueryAllChainMetasResponse.pagination": + value := x.Pagination + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasResponse 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_QueryAllChainMetasResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasResponse.chain_metas": + lv := value.List() + clv := lv.(*_QueryAllChainMetasResponse_1_list) + x.ChainMetas = *clv.list + case "uexecutor.v1.QueryAllChainMetasResponse.pagination": + x.Pagination = value.Message().Interface().(*v1beta1.PageResponse) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasResponse 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_QueryAllChainMetasResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasResponse.chain_metas": + if x.ChainMetas == nil { + x.ChainMetas = []*ChainMeta{} + } + value := &_QueryAllChainMetasResponse_1_list{list: &x.ChainMetas} + return protoreflect.ValueOfList(value) + case "uexecutor.v1.QueryAllChainMetasResponse.pagination": + if x.Pagination == nil { + x.Pagination = new(v1beta1.PageResponse) + } + return protoreflect.ValueOfMessage(x.Pagination.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasResponse 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_QueryAllChainMetasResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryAllChainMetasResponse.chain_metas": + list := []*ChainMeta{} + return protoreflect.ValueOfList(&_QueryAllChainMetasResponse_1_list{list: &list}) + case "uexecutor.v1.QueryAllChainMetasResponse.pagination": + m := new(v1beta1.PageResponse) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryAllChainMetasResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryAllChainMetasResponse 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_QueryAllChainMetasResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryAllChainMetasResponse", 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_QueryAllChainMetasResponse) 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_QueryAllChainMetasResponse) 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_QueryAllChainMetasResponse) 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_QueryAllChainMetasResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryAllChainMetasResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if len(x.ChainMetas) > 0 { + for _, e := range x.ChainMetas { + l = options.Size(e) + n += 1 + l + runtime.Sov(uint64(l)) + } + } + if x.Pagination != nil { + l = options.Size(x.Pagination) + 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().(*QueryAllChainMetasResponse) + 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.Pagination != nil { + encoded, err := options.Marshal(x.Pagination) + 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.ChainMetas) > 0 { + for iNdEx := len(x.ChainMetas) - 1; iNdEx >= 0; iNdEx-- { + encoded, err := options.Marshal(x.ChainMetas[iNdEx]) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0xa + } + } + 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().(*QueryAllChainMetasResponse) + 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: QueryAllChainMetasResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryAllChainMetasResponse: 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 ChainMetas", 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 + } + x.ChainMetas = append(x.ChainMetas, &ChainMeta{}) + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.ChainMetas[len(x.ChainMetas)-1]); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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.Pagination == nil { + x.Pagination = &v1beta1.PageResponse{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Pagination); 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_QueryParamsRequest protoreflect.MessageDescriptor ) @@ -1895,7 +3758,7 @@ func (x *QueryParamsRequest) ProtoReflect() protoreflect.Message { } func (x *QueryParamsRequest) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[4] + mi := &file_uexecutor_v1_query_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2253,7 +4116,7 @@ func (x *QueryParamsResponse) ProtoReflect() protoreflect.Message { } func (x *QueryParamsResponse) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[5] + mi := &file_uexecutor_v1_query_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2688,7 +4551,7 @@ func (x *QueryAllPendingInboundsRequest) ProtoReflect() protoreflect.Message { } func (x *QueryAllPendingInboundsRequest) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[6] + mi := &file_uexecutor_v1_query_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3171,7 +5034,7 @@ func (x *QueryAllPendingInboundsResponse) ProtoReflect() protoreflect.Message { } func (x *QueryAllPendingInboundsResponse) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[7] + mi := &file_uexecutor_v1_query_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3682,7 +5545,7 @@ func (x *QueryGetUniversalTxRequest) ProtoReflect() protoreflect.Message { } func (x *QueryGetUniversalTxRequest) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[8] + mi := &file_uexecutor_v1_query_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4102,7 +5965,7 @@ func (x *QueryGetUniversalTxResponse) ProtoReflect() protoreflect.Message { } func (x *QueryGetUniversalTxResponse) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[9] + mi := &file_uexecutor_v1_query_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4537,7 +6400,7 @@ func (x *QueryAllUniversalTxRequest) ProtoReflect() protoreflect.Message { } func (x *QueryAllUniversalTxRequest) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[10] + mi := &file_uexecutor_v1_query_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5025,7 +6888,7 @@ func (x *QueryAllUniversalTxResponse) ProtoReflect() protoreflect.Message { } func (x *QueryAllUniversalTxResponse) slowProtoReflect() protoreflect.Message { - mi := &file_uexecutor_v1_query_proto_msgTypes[11] + mi := &file_uexecutor_v1_query_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5688,6 +7551,156 @@ func (x *QueryAllGasPricesResponse) GetPagination() *v1beta1.PageResponse { return nil } +// Single chain meta +type QueryChainMetaRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (x *QueryChainMetaRequest) Reset() { + *x = QueryChainMetaRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryChainMetaRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryChainMetaRequest) ProtoMessage() {} + +// Deprecated: Use QueryChainMetaRequest.ProtoReflect.Descriptor instead. +func (*QueryChainMetaRequest) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{4} +} + +func (x *QueryChainMetaRequest) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +type QueryChainMetaResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChainMeta *ChainMeta `protobuf:"bytes,1,opt,name=chain_meta,json=chainMeta,proto3" json:"chain_meta,omitempty"` +} + +func (x *QueryChainMetaResponse) Reset() { + *x = QueryChainMetaResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryChainMetaResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryChainMetaResponse) ProtoMessage() {} + +// Deprecated: Use QueryChainMetaResponse.ProtoReflect.Descriptor instead. +func (*QueryChainMetaResponse) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{5} +} + +func (x *QueryChainMetaResponse) GetChainMeta() *ChainMeta { + if x != nil { + return x.ChainMeta + } + return nil +} + +// All chain metas +type QueryAllChainMetasRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Pagination *v1beta1.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (x *QueryAllChainMetasRequest) Reset() { + *x = QueryAllChainMetasRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryAllChainMetasRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryAllChainMetasRequest) ProtoMessage() {} + +// Deprecated: Use QueryAllChainMetasRequest.ProtoReflect.Descriptor instead. +func (*QueryAllChainMetasRequest) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{6} +} + +func (x *QueryAllChainMetasRequest) GetPagination() *v1beta1.PageRequest { + if x != nil { + return x.Pagination + } + return nil +} + +type QueryAllChainMetasResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChainMetas []*ChainMeta `protobuf:"bytes,1,rep,name=chain_metas,json=chainMetas,proto3" json:"chain_metas,omitempty"` + Pagination *v1beta1.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (x *QueryAllChainMetasResponse) Reset() { + *x = QueryAllChainMetasResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryAllChainMetasResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryAllChainMetasResponse) ProtoMessage() {} + +// Deprecated: Use QueryAllChainMetasResponse.ProtoReflect.Descriptor instead. +func (*QueryAllChainMetasResponse) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{7} +} + +func (x *QueryAllChainMetasResponse) GetChainMetas() []*ChainMeta { + if x != nil { + return x.ChainMetas + } + return nil +} + +func (x *QueryAllChainMetasResponse) GetPagination() *v1beta1.PageResponse { + if x != nil { + return x.Pagination + } + return nil +} + // Existing types type QueryParamsRequest struct { state protoimpl.MessageState @@ -5698,7 +7711,7 @@ type QueryParamsRequest struct { func (x *QueryParamsRequest) Reset() { *x = QueryParamsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[4] + mi := &file_uexecutor_v1_query_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5712,7 +7725,7 @@ func (*QueryParamsRequest) ProtoMessage() {} // Deprecated: Use QueryParamsRequest.ProtoReflect.Descriptor instead. func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{4} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{8} } // QueryParamsResponse is the response type for the Query/Params RPC method. @@ -5728,7 +7741,7 @@ type QueryParamsResponse struct { func (x *QueryParamsResponse) Reset() { *x = QueryParamsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[5] + mi := &file_uexecutor_v1_query_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5742,7 +7755,7 @@ func (*QueryParamsResponse) ProtoMessage() {} // Deprecated: Use QueryParamsResponse.ProtoReflect.Descriptor instead. func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{5} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{9} } func (x *QueryParamsResponse) GetParams() *Params { @@ -5764,7 +7777,7 @@ type QueryAllPendingInboundsRequest struct { func (x *QueryAllPendingInboundsRequest) Reset() { *x = QueryAllPendingInboundsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[6] + mi := &file_uexecutor_v1_query_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5778,7 +7791,7 @@ func (*QueryAllPendingInboundsRequest) ProtoMessage() {} // Deprecated: Use QueryAllPendingInboundsRequest.ProtoReflect.Descriptor instead. func (*QueryAllPendingInboundsRequest) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{6} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{10} } func (x *QueryAllPendingInboundsRequest) GetPagination() *v1beta1.PageRequest { @@ -5800,7 +7813,7 @@ type QueryAllPendingInboundsResponse struct { func (x *QueryAllPendingInboundsResponse) Reset() { *x = QueryAllPendingInboundsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[7] + mi := &file_uexecutor_v1_query_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5814,7 +7827,7 @@ func (*QueryAllPendingInboundsResponse) ProtoMessage() {} // Deprecated: Use QueryAllPendingInboundsResponse.ProtoReflect.Descriptor instead. func (*QueryAllPendingInboundsResponse) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{7} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{11} } func (x *QueryAllPendingInboundsResponse) GetInboundIds() []string { @@ -5843,7 +7856,7 @@ type QueryGetUniversalTxRequest struct { func (x *QueryGetUniversalTxRequest) Reset() { *x = QueryGetUniversalTxRequest{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[8] + mi := &file_uexecutor_v1_query_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5857,7 +7870,7 @@ func (*QueryGetUniversalTxRequest) ProtoMessage() {} // Deprecated: Use QueryGetUniversalTxRequest.ProtoReflect.Descriptor instead. func (*QueryGetUniversalTxRequest) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{8} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{12} } func (x *QueryGetUniversalTxRequest) GetId() string { @@ -5878,7 +7891,7 @@ type QueryGetUniversalTxResponse struct { func (x *QueryGetUniversalTxResponse) Reset() { *x = QueryGetUniversalTxResponse{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[9] + mi := &file_uexecutor_v1_query_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5892,7 +7905,7 @@ func (*QueryGetUniversalTxResponse) ProtoMessage() {} // Deprecated: Use QueryGetUniversalTxResponse.ProtoReflect.Descriptor instead. func (*QueryGetUniversalTxResponse) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{9} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{13} } func (x *QueryGetUniversalTxResponse) GetUniversalTx() *UniversalTxLegacy { @@ -5913,7 +7926,7 @@ type QueryAllUniversalTxRequest struct { func (x *QueryAllUniversalTxRequest) Reset() { *x = QueryAllUniversalTxRequest{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[10] + mi := &file_uexecutor_v1_query_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5927,7 +7940,7 @@ func (*QueryAllUniversalTxRequest) ProtoMessage() {} // Deprecated: Use QueryAllUniversalTxRequest.ProtoReflect.Descriptor instead. func (*QueryAllUniversalTxRequest) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{10} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{14} } func (x *QueryAllUniversalTxRequest) GetPagination() *v1beta1.PageRequest { @@ -5949,7 +7962,7 @@ type QueryAllUniversalTxResponse struct { func (x *QueryAllUniversalTxResponse) Reset() { *x = QueryAllUniversalTxResponse{} if protoimpl.UnsafeEnabled { - mi := &file_uexecutor_v1_query_proto_msgTypes[11] + mi := &file_uexecutor_v1_query_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5963,7 +7976,7 @@ func (*QueryAllUniversalTxResponse) ProtoMessage() {} // Deprecated: Use QueryAllUniversalTxResponse.ProtoReflect.Descriptor instead. func (*QueryAllUniversalTxResponse) Descriptor() ([]byte, []int) { - return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{11} + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{15} } func (x *QueryAllUniversalTxResponse) GetUniversalTxs() []*UniversalTx { @@ -5990,145 +8003,188 @@ var file_uexecutor_v1_query_proto_rawDesc = []byte{ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, - 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x31, 0x0a, 0x14, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x4c, 0x0a, - 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, - 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, - 0x65, 0x52, 0x08, 0x67, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x22, 0x62, 0x0a, 0x18, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 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, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x9b, 0x01, 0x0a, 0x19, 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, 0x12, 0x35, 0x0a, - 0x0a, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x09, 0x67, 0x61, 0x73, 0x50, 0x72, - 0x69, 0x63, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 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, 0x22, 0x14, 0x0a, - 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x43, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x75, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x68, 0x0a, 0x1e, 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, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, - 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, - 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x8b, 0x01, 0x0a, 0x1f, 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, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 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, - 0x22, 0x2c, 0x0a, 0x1a, 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, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x61, - 0x0a, 0x1b, 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, 0x12, 0x42, 0x0a, - 0x0c, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x4c, 0x65, - 0x67, 0x61, 0x63, 0x79, 0x52, 0x0b, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, - 0x78, 0x22, 0x64, 0x0a, 0x1a, 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, 0x12, + 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, + 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x31, 0x0a, 0x14, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x15, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x52, 0x08, 0x67, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x22, 0x62, 0x0a, 0x18, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 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, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9b, + 0x01, 0x0a, 0x19, 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, 0x12, 0x35, 0x0a, 0x0a, + 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x09, 0x67, 0x61, 0x73, 0x50, 0x72, 0x69, + 0x63, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 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, 0x22, 0x32, 0x0a, 0x15, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x22, 0x50, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, + 0x74, 0x61, 0x22, 0x63, 0x0a, 0x19, 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, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa6, 0x01, 0x0a, 0x1b, 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, 0x12, 0x3e, 0x0a, 0x0d, 0x75, 0x6e, 0x69, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, - 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x0c, 0x75, 0x6e, 0x69, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 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, 0xb4, 0x06, 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, 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, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9f, 0x01, 0x0a, 0x1a, 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, 0x12, 0x38, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x75, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, + 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 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, 0x22, 0x14, 0x0a, 0x12, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x43, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x22, 0x68, 0x0a, 0x1e, 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, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 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, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8b, + 0x01, 0x0a, 0x1f, 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, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 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, 0x22, 0x2c, 0x0a, 0x1a, 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, + 0x6c, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x61, 0x0a, 0x1b, 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, 0x12, 0x42, 0x0a, 0x0c, 0x75, 0x6e, 0x69, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x52, 0x0b, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x22, 0x64, 0x0a, + 0x1a, 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, 0x12, 0x46, 0x0a, 0x0a, 0x70, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0xa6, 0x01, 0x0a, 0x1b, 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, 0x12, 0x3e, 0x0a, 0x0d, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, + 0x5f, 0x74, 0x78, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x0c, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, + 0x54, 0x78, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 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, 0xc2, 0x08, 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, 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, - 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, 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, + 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, 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, 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, + 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, 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, 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, + 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, 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 ( @@ -6143,56 +8199,69 @@ 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, 12) +var file_uexecutor_v1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_uexecutor_v1_query_proto_goTypes = []interface{}{ (*QueryGasPriceRequest)(nil), // 0: uexecutor.v1.QueryGasPriceRequest (*QueryGasPriceResponse)(nil), // 1: uexecutor.v1.QueryGasPriceResponse (*QueryAllGasPricesRequest)(nil), // 2: uexecutor.v1.QueryAllGasPricesRequest (*QueryAllGasPricesResponse)(nil), // 3: uexecutor.v1.QueryAllGasPricesResponse - (*QueryParamsRequest)(nil), // 4: uexecutor.v1.QueryParamsRequest - (*QueryParamsResponse)(nil), // 5: uexecutor.v1.QueryParamsResponse - (*QueryAllPendingInboundsRequest)(nil), // 6: uexecutor.v1.QueryAllPendingInboundsRequest - (*QueryAllPendingInboundsResponse)(nil), // 7: uexecutor.v1.QueryAllPendingInboundsResponse - (*QueryGetUniversalTxRequest)(nil), // 8: uexecutor.v1.QueryGetUniversalTxRequest - (*QueryGetUniversalTxResponse)(nil), // 9: uexecutor.v1.QueryGetUniversalTxResponse - (*QueryAllUniversalTxRequest)(nil), // 10: uexecutor.v1.QueryAllUniversalTxRequest - (*QueryAllUniversalTxResponse)(nil), // 11: uexecutor.v1.QueryAllUniversalTxResponse - (*GasPrice)(nil), // 12: uexecutor.v1.GasPrice - (*v1beta1.PageRequest)(nil), // 13: cosmos.base.query.v1beta1.PageRequest - (*v1beta1.PageResponse)(nil), // 14: cosmos.base.query.v1beta1.PageResponse - (*Params)(nil), // 15: uexecutor.v1.Params - (*UniversalTxLegacy)(nil), // 16: uexecutor.v1.UniversalTxLegacy - (*UniversalTx)(nil), // 17: uexecutor.v1.UniversalTx + (*QueryChainMetaRequest)(nil), // 4: uexecutor.v1.QueryChainMetaRequest + (*QueryChainMetaResponse)(nil), // 5: uexecutor.v1.QueryChainMetaResponse + (*QueryAllChainMetasRequest)(nil), // 6: uexecutor.v1.QueryAllChainMetasRequest + (*QueryAllChainMetasResponse)(nil), // 7: uexecutor.v1.QueryAllChainMetasResponse + (*QueryParamsRequest)(nil), // 8: uexecutor.v1.QueryParamsRequest + (*QueryParamsResponse)(nil), // 9: uexecutor.v1.QueryParamsResponse + (*QueryAllPendingInboundsRequest)(nil), // 10: uexecutor.v1.QueryAllPendingInboundsRequest + (*QueryAllPendingInboundsResponse)(nil), // 11: uexecutor.v1.QueryAllPendingInboundsResponse + (*QueryGetUniversalTxRequest)(nil), // 12: uexecutor.v1.QueryGetUniversalTxRequest + (*QueryGetUniversalTxResponse)(nil), // 13: uexecutor.v1.QueryGetUniversalTxResponse + (*QueryAllUniversalTxRequest)(nil), // 14: uexecutor.v1.QueryAllUniversalTxRequest + (*QueryAllUniversalTxResponse)(nil), // 15: uexecutor.v1.QueryAllUniversalTxResponse + (*GasPrice)(nil), // 16: uexecutor.v1.GasPrice + (*v1beta1.PageRequest)(nil), // 17: cosmos.base.query.v1beta1.PageRequest + (*v1beta1.PageResponse)(nil), // 18: cosmos.base.query.v1beta1.PageResponse + (*ChainMeta)(nil), // 19: uexecutor.v1.ChainMeta + (*Params)(nil), // 20: uexecutor.v1.Params + (*UniversalTxLegacy)(nil), // 21: uexecutor.v1.UniversalTxLegacy + (*UniversalTx)(nil), // 22: uexecutor.v1.UniversalTx } var file_uexecutor_v1_query_proto_depIdxs = []int32{ - 12, // 0: uexecutor.v1.QueryGasPriceResponse.gas_price:type_name -> uexecutor.v1.GasPrice - 13, // 1: uexecutor.v1.QueryAllGasPricesRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 12, // 2: uexecutor.v1.QueryAllGasPricesResponse.gas_prices:type_name -> uexecutor.v1.GasPrice - 14, // 3: uexecutor.v1.QueryAllGasPricesResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 15, // 4: uexecutor.v1.QueryParamsResponse.params:type_name -> uexecutor.v1.Params - 13, // 5: uexecutor.v1.QueryAllPendingInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 14, // 6: uexecutor.v1.QueryAllPendingInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 16, // 7: uexecutor.v1.QueryGetUniversalTxResponse.universal_tx:type_name -> uexecutor.v1.UniversalTxLegacy - 13, // 8: uexecutor.v1.QueryAllUniversalTxRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 17, // 9: uexecutor.v1.QueryAllUniversalTxResponse.universal_txs:type_name -> uexecutor.v1.UniversalTx - 14, // 10: uexecutor.v1.QueryAllUniversalTxResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 4, // 11: uexecutor.v1.Query.Params:input_type -> uexecutor.v1.QueryParamsRequest - 6, // 12: uexecutor.v1.Query.AllPendingInbounds:input_type -> uexecutor.v1.QueryAllPendingInboundsRequest - 8, // 13: uexecutor.v1.Query.GetUniversalTx:input_type -> uexecutor.v1.QueryGetUniversalTxRequest - 10, // 14: uexecutor.v1.Query.AllUniversalTx:input_type -> uexecutor.v1.QueryAllUniversalTxRequest - 0, // 15: uexecutor.v1.Query.GasPrice:input_type -> uexecutor.v1.QueryGasPriceRequest - 2, // 16: uexecutor.v1.Query.AllGasPrices:input_type -> uexecutor.v1.QueryAllGasPricesRequest - 5, // 17: uexecutor.v1.Query.Params:output_type -> uexecutor.v1.QueryParamsResponse - 7, // 18: uexecutor.v1.Query.AllPendingInbounds:output_type -> uexecutor.v1.QueryAllPendingInboundsResponse - 9, // 19: uexecutor.v1.Query.GetUniversalTx:output_type -> uexecutor.v1.QueryGetUniversalTxResponse - 11, // 20: uexecutor.v1.Query.AllUniversalTx:output_type -> uexecutor.v1.QueryAllUniversalTxResponse - 1, // 21: uexecutor.v1.Query.GasPrice:output_type -> uexecutor.v1.QueryGasPriceResponse - 3, // 22: uexecutor.v1.Query.AllGasPrices:output_type -> uexecutor.v1.QueryAllGasPricesResponse - 17, // [17:23] is the sub-list for method output_type - 11, // [11:17] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 16, // 0: uexecutor.v1.QueryGasPriceResponse.gas_price:type_name -> uexecutor.v1.GasPrice + 17, // 1: uexecutor.v1.QueryAllGasPricesRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 16, // 2: uexecutor.v1.QueryAllGasPricesResponse.gas_prices:type_name -> uexecutor.v1.GasPrice + 18, // 3: uexecutor.v1.QueryAllGasPricesResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 19, // 4: uexecutor.v1.QueryChainMetaResponse.chain_meta:type_name -> uexecutor.v1.ChainMeta + 17, // 5: uexecutor.v1.QueryAllChainMetasRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 19, // 6: uexecutor.v1.QueryAllChainMetasResponse.chain_metas:type_name -> uexecutor.v1.ChainMeta + 18, // 7: uexecutor.v1.QueryAllChainMetasResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 20, // 8: uexecutor.v1.QueryParamsResponse.params:type_name -> uexecutor.v1.Params + 17, // 9: uexecutor.v1.QueryAllPendingInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 18, // 10: uexecutor.v1.QueryAllPendingInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 21, // 11: uexecutor.v1.QueryGetUniversalTxResponse.universal_tx:type_name -> uexecutor.v1.UniversalTxLegacy + 17, // 12: uexecutor.v1.QueryAllUniversalTxRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 22, // 13: uexecutor.v1.QueryAllUniversalTxResponse.universal_txs:type_name -> uexecutor.v1.UniversalTx + 18, // 14: uexecutor.v1.QueryAllUniversalTxResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 8, // 15: uexecutor.v1.Query.Params:input_type -> uexecutor.v1.QueryParamsRequest + 10, // 16: uexecutor.v1.Query.AllPendingInbounds:input_type -> uexecutor.v1.QueryAllPendingInboundsRequest + 12, // 17: uexecutor.v1.Query.GetUniversalTx:input_type -> uexecutor.v1.QueryGetUniversalTxRequest + 14, // 18: uexecutor.v1.Query.AllUniversalTx:input_type -> uexecutor.v1.QueryAllUniversalTxRequest + 0, // 19: uexecutor.v1.Query.GasPrice:input_type -> uexecutor.v1.QueryGasPriceRequest + 2, // 20: uexecutor.v1.Query.AllGasPrices:input_type -> uexecutor.v1.QueryAllGasPricesRequest + 4, // 21: uexecutor.v1.Query.ChainMeta:input_type -> uexecutor.v1.QueryChainMetaRequest + 6, // 22: uexecutor.v1.Query.AllChainMetas:input_type -> uexecutor.v1.QueryAllChainMetasRequest + 9, // 23: uexecutor.v1.Query.Params:output_type -> uexecutor.v1.QueryParamsResponse + 11, // 24: uexecutor.v1.Query.AllPendingInbounds:output_type -> uexecutor.v1.QueryAllPendingInboundsResponse + 13, // 25: uexecutor.v1.Query.GetUniversalTx:output_type -> uexecutor.v1.QueryGetUniversalTxResponse + 15, // 26: uexecutor.v1.Query.AllUniversalTx:output_type -> uexecutor.v1.QueryAllUniversalTxResponse + 1, // 27: uexecutor.v1.Query.GasPrice:output_type -> uexecutor.v1.QueryGasPriceResponse + 3, // 28: uexecutor.v1.Query.AllGasPrices:output_type -> uexecutor.v1.QueryAllGasPricesResponse + 5, // 29: uexecutor.v1.Query.ChainMeta:output_type -> uexecutor.v1.QueryChainMetaResponse + 7, // 30: uexecutor.v1.Query.AllChainMetas:output_type -> uexecutor.v1.QueryAllChainMetasResponse + 23, // [23:31] is the sub-list for method output_type + 15, // [15:23] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_uexecutor_v1_query_proto_init() } @@ -6202,6 +8271,7 @@ func file_uexecutor_v1_query_proto_init() { } file_uexecutor_v1_types_proto_init() file_uexecutor_v1_gas_price_proto_init() + file_uexecutor_v1_chain_meta_proto_init() if !protoimpl.UnsafeEnabled { file_uexecutor_v1_query_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryGasPriceRequest); i { @@ -6252,7 +8322,7 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryParamsRequest); i { + switch v := v.(*QueryChainMetaRequest); i { case 0: return &v.state case 1: @@ -6264,7 +8334,7 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryParamsResponse); i { + switch v := v.(*QueryChainMetaResponse); i { case 0: return &v.state case 1: @@ -6276,7 +8346,7 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryAllPendingInboundsRequest); i { + switch v := v.(*QueryAllChainMetasRequest); i { case 0: return &v.state case 1: @@ -6288,7 +8358,7 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryAllPendingInboundsResponse); i { + switch v := v.(*QueryAllChainMetasResponse); i { case 0: return &v.state case 1: @@ -6300,7 +8370,7 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryGetUniversalTxRequest); i { + switch v := v.(*QueryParamsRequest); i { case 0: return &v.state case 1: @@ -6312,7 +8382,7 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryGetUniversalTxResponse); i { + switch v := v.(*QueryParamsResponse); i { case 0: return &v.state case 1: @@ -6324,7 +8394,7 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryAllUniversalTxRequest); i { + switch v := v.(*QueryAllPendingInboundsRequest); i { case 0: return &v.state case 1: @@ -6336,6 +8406,54 @@ func file_uexecutor_v1_query_proto_init() { } } file_uexecutor_v1_query_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryAllPendingInboundsResponse); 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[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryGetUniversalTxRequest); 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[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryGetUniversalTxResponse); 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[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryAllUniversalTxRequest); 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[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryAllUniversalTxResponse); i { case 0: return &v.state @@ -6354,7 +8472,7 @@ func file_uexecutor_v1_query_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_uexecutor_v1_query_proto_rawDesc, NumEnums: 0, - NumMessages: 12, + NumMessages: 16, NumExtensions: 0, NumServices: 1, }, diff --git a/api/uexecutor/v1/query_grpc.pb.go b/api/uexecutor/v1/query_grpc.pb.go index 0a921c47..8299a71b 100644 --- a/api/uexecutor/v1/query_grpc.pb.go +++ b/api/uexecutor/v1/query_grpc.pb.go @@ -25,6 +25,8 @@ const ( Query_AllUniversalTx_FullMethodName = "/uexecutor.v1.Query/AllUniversalTx" Query_GasPrice_FullMethodName = "/uexecutor.v1.Query/GasPrice" Query_AllGasPrices_FullMethodName = "/uexecutor.v1.Query/AllGasPrices" + Query_ChainMeta_FullMethodName = "/uexecutor.v1.Query/ChainMeta" + Query_AllChainMetas_FullMethodName = "/uexecutor.v1.Query/AllChainMetas" ) // QueryClient is the client API for Query service. @@ -43,6 +45,10 @@ type QueryClient interface { GasPrice(ctx context.Context, in *QueryGasPriceRequest, opts ...grpc.CallOption) (*QueryGasPriceResponse, error) // 🔹 Queries all gas prices across chains AllGasPrices(ctx context.Context, in *QueryAllGasPricesRequest, opts ...grpc.CallOption) (*QueryAllGasPricesResponse, error) + // 🔹 Queries chain meta for a specific chain + ChainMeta(ctx context.Context, in *QueryChainMetaRequest, opts ...grpc.CallOption) (*QueryChainMetaResponse, error) + // 🔹 Queries all chain metas across chains + AllChainMetas(ctx context.Context, in *QueryAllChainMetasRequest, opts ...grpc.CallOption) (*QueryAllChainMetasResponse, error) } type queryClient struct { @@ -107,6 +113,24 @@ func (c *queryClient) AllGasPrices(ctx context.Context, in *QueryAllGasPricesReq return out, nil } +func (c *queryClient) ChainMeta(ctx context.Context, in *QueryChainMetaRequest, opts ...grpc.CallOption) (*QueryChainMetaResponse, error) { + out := new(QueryChainMetaResponse) + err := c.cc.Invoke(ctx, Query_ChainMeta_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AllChainMetas(ctx context.Context, in *QueryAllChainMetasRequest, opts ...grpc.CallOption) (*QueryAllChainMetasResponse, error) { + out := new(QueryAllChainMetasResponse) + err := c.cc.Invoke(ctx, Query_AllChainMetas_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 @@ -123,6 +147,10 @@ type QueryServer interface { GasPrice(context.Context, *QueryGasPriceRequest) (*QueryGasPriceResponse, error) // 🔹 Queries all gas prices across chains AllGasPrices(context.Context, *QueryAllGasPricesRequest) (*QueryAllGasPricesResponse, error) + // 🔹 Queries chain meta for a specific chain + ChainMeta(context.Context, *QueryChainMetaRequest) (*QueryChainMetaResponse, error) + // 🔹 Queries all chain metas across chains + AllChainMetas(context.Context, *QueryAllChainMetasRequest) (*QueryAllChainMetasResponse, error) mustEmbedUnimplementedQueryServer() } @@ -148,6 +176,12 @@ func (UnimplementedQueryServer) GasPrice(context.Context, *QueryGasPriceRequest) func (UnimplementedQueryServer) AllGasPrices(context.Context, *QueryAllGasPricesRequest) (*QueryAllGasPricesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllGasPrices not implemented") } +func (UnimplementedQueryServer) ChainMeta(context.Context, *QueryChainMetaRequest) (*QueryChainMetaResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ChainMeta not implemented") +} +func (UnimplementedQueryServer) AllChainMetas(context.Context, *QueryAllChainMetasRequest) (*QueryAllChainMetasResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AllChainMetas not implemented") +} func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} // UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. @@ -269,6 +303,42 @@ func _Query_AllGasPrices_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Query_ChainMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryChainMetaRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ChainMeta(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Query_ChainMeta_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ChainMeta(ctx, req.(*QueryChainMetaRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AllChainMetas_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAllChainMetasRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AllChainMetas(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Query_AllChainMetas_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AllChainMetas(ctx, req.(*QueryAllChainMetasRequest)) + } + 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) @@ -300,6 +370,14 @@ var Query_ServiceDesc = grpc.ServiceDesc{ MethodName: "AllGasPrices", Handler: _Query_AllGasPrices_Handler, }, + { + MethodName: "ChainMeta", + Handler: _Query_ChainMeta_Handler, + }, + { + MethodName: "AllChainMetas", + Handler: _Query_AllChainMetas_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/query.proto", diff --git a/api/uexecutor/v1/tx.pulsar.go b/api/uexecutor/v1/tx.pulsar.go index 619f27bd..94d580ea 100644 --- a/api/uexecutor/v1/tx.pulsar.go +++ b/api/uexecutor/v1/tx.pulsar.go @@ -5641,6 +5641,942 @@ func (x *fastReflection_MsgVoteGasPriceResponse) ProtoMethods() *protoiface.Meth } } +var ( + md_MsgVoteChainMeta protoreflect.MessageDescriptor + fd_MsgVoteChainMeta_signer protoreflect.FieldDescriptor + fd_MsgVoteChainMeta_observed_chain_id protoreflect.FieldDescriptor + fd_MsgVoteChainMeta_price protoreflect.FieldDescriptor + fd_MsgVoteChainMeta_chain_height protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_tx_proto_init() + md_MsgVoteChainMeta = File_uexecutor_v1_tx_proto.Messages().ByName("MsgVoteChainMeta") + fd_MsgVoteChainMeta_signer = md_MsgVoteChainMeta.Fields().ByName("signer") + fd_MsgVoteChainMeta_observed_chain_id = md_MsgVoteChainMeta.Fields().ByName("observed_chain_id") + fd_MsgVoteChainMeta_price = md_MsgVoteChainMeta.Fields().ByName("price") + fd_MsgVoteChainMeta_chain_height = md_MsgVoteChainMeta.Fields().ByName("chain_height") +} + +var _ protoreflect.Message = (*fastReflection_MsgVoteChainMeta)(nil) + +type fastReflection_MsgVoteChainMeta MsgVoteChainMeta + +func (x *MsgVoteChainMeta) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgVoteChainMeta)(x) +} + +func (x *MsgVoteChainMeta) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_tx_proto_msgTypes[12] + 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_MsgVoteChainMeta_messageType fastReflection_MsgVoteChainMeta_messageType +var _ protoreflect.MessageType = fastReflection_MsgVoteChainMeta_messageType{} + +type fastReflection_MsgVoteChainMeta_messageType struct{} + +func (x fastReflection_MsgVoteChainMeta_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgVoteChainMeta)(nil) +} +func (x fastReflection_MsgVoteChainMeta_messageType) New() protoreflect.Message { + return new(fastReflection_MsgVoteChainMeta) +} +func (x fastReflection_MsgVoteChainMeta_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgVoteChainMeta +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgVoteChainMeta) Descriptor() protoreflect.MessageDescriptor { + return md_MsgVoteChainMeta +} + +// 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_MsgVoteChainMeta) Type() protoreflect.MessageType { + return _fastReflection_MsgVoteChainMeta_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgVoteChainMeta) New() protoreflect.Message { + return new(fastReflection_MsgVoteChainMeta) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgVoteChainMeta) Interface() protoreflect.ProtoMessage { + return (*MsgVoteChainMeta)(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_MsgVoteChainMeta) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Signer != "" { + value := protoreflect.ValueOfString(x.Signer) + if !f(fd_MsgVoteChainMeta_signer, value) { + return + } + } + if x.ObservedChainId != "" { + value := protoreflect.ValueOfString(x.ObservedChainId) + if !f(fd_MsgVoteChainMeta_observed_chain_id, value) { + return + } + } + if x.Price != uint64(0) { + value := protoreflect.ValueOfUint64(x.Price) + if !f(fd_MsgVoteChainMeta_price, value) { + return + } + } + if x.ChainHeight != uint64(0) { + value := protoreflect.ValueOfUint64(x.ChainHeight) + if !f(fd_MsgVoteChainMeta_chain_height, 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_MsgVoteChainMeta) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.MsgVoteChainMeta.signer": + return x.Signer != "" + case "uexecutor.v1.MsgVoteChainMeta.observed_chain_id": + return x.ObservedChainId != "" + case "uexecutor.v1.MsgVoteChainMeta.price": + return x.Price != uint64(0) + case "uexecutor.v1.MsgVoteChainMeta.chain_height": + return x.ChainHeight != uint64(0) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMeta 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_MsgVoteChainMeta) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.MsgVoteChainMeta.signer": + x.Signer = "" + case "uexecutor.v1.MsgVoteChainMeta.observed_chain_id": + x.ObservedChainId = "" + case "uexecutor.v1.MsgVoteChainMeta.price": + x.Price = uint64(0) + case "uexecutor.v1.MsgVoteChainMeta.chain_height": + x.ChainHeight = uint64(0) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMeta 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_MsgVoteChainMeta) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.MsgVoteChainMeta.signer": + value := x.Signer + return protoreflect.ValueOfString(value) + case "uexecutor.v1.MsgVoteChainMeta.observed_chain_id": + value := x.ObservedChainId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.MsgVoteChainMeta.price": + value := x.Price + return protoreflect.ValueOfUint64(value) + case "uexecutor.v1.MsgVoteChainMeta.chain_height": + value := x.ChainHeight + return protoreflect.ValueOfUint64(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMeta 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_MsgVoteChainMeta) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.MsgVoteChainMeta.signer": + x.Signer = value.Interface().(string) + case "uexecutor.v1.MsgVoteChainMeta.observed_chain_id": + x.ObservedChainId = value.Interface().(string) + case "uexecutor.v1.MsgVoteChainMeta.price": + x.Price = value.Uint() + case "uexecutor.v1.MsgVoteChainMeta.chain_height": + x.ChainHeight = value.Uint() + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMeta 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_MsgVoteChainMeta) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.MsgVoteChainMeta.signer": + panic(fmt.Errorf("field signer of message uexecutor.v1.MsgVoteChainMeta is not mutable")) + case "uexecutor.v1.MsgVoteChainMeta.observed_chain_id": + panic(fmt.Errorf("field observed_chain_id of message uexecutor.v1.MsgVoteChainMeta is not mutable")) + case "uexecutor.v1.MsgVoteChainMeta.price": + panic(fmt.Errorf("field price of message uexecutor.v1.MsgVoteChainMeta is not mutable")) + case "uexecutor.v1.MsgVoteChainMeta.chain_height": + panic(fmt.Errorf("field chain_height of message uexecutor.v1.MsgVoteChainMeta is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMeta 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_MsgVoteChainMeta) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.MsgVoteChainMeta.signer": + return protoreflect.ValueOfString("") + case "uexecutor.v1.MsgVoteChainMeta.observed_chain_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.MsgVoteChainMeta.price": + return protoreflect.ValueOfUint64(uint64(0)) + case "uexecutor.v1.MsgVoteChainMeta.chain_height": + return protoreflect.ValueOfUint64(uint64(0)) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMeta 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_MsgVoteChainMeta) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.MsgVoteChainMeta", 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_MsgVoteChainMeta) 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_MsgVoteChainMeta) 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_MsgVoteChainMeta) 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_MsgVoteChainMeta) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgVoteChainMeta) + 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.Signer) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ObservedChainId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.Price != 0 { + n += 1 + runtime.Sov(uint64(x.Price)) + } + if x.ChainHeight != 0 { + n += 1 + runtime.Sov(uint64(x.ChainHeight)) + } + 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().(*MsgVoteChainMeta) + 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.ChainHeight != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.ChainHeight)) + i-- + dAtA[i] = 0x20 + } + if x.Price != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.Price)) + i-- + dAtA[i] = 0x18 + } + if len(x.ObservedChainId) > 0 { + i -= len(x.ObservedChainId) + copy(dAtA[i:], x.ObservedChainId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ObservedChainId))) + i-- + dAtA[i] = 0x12 + } + if len(x.Signer) > 0 { + i -= len(x.Signer) + copy(dAtA[i:], x.Signer) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Signer))) + 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().(*MsgVoteChainMeta) + 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: MsgVoteChainMeta: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgVoteChainMeta: 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 Signer", 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.Signer = 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 ObservedChainId", 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.ObservedChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) + } + x.Price = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.Price |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ChainHeight", wireType) + } + x.ChainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.ChainHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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_MsgVoteChainMetaResponse protoreflect.MessageDescriptor +) + +func init() { + file_uexecutor_v1_tx_proto_init() + md_MsgVoteChainMetaResponse = File_uexecutor_v1_tx_proto.Messages().ByName("MsgVoteChainMetaResponse") +} + +var _ protoreflect.Message = (*fastReflection_MsgVoteChainMetaResponse)(nil) + +type fastReflection_MsgVoteChainMetaResponse MsgVoteChainMetaResponse + +func (x *MsgVoteChainMetaResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgVoteChainMetaResponse)(x) +} + +func (x *MsgVoteChainMetaResponse) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_tx_proto_msgTypes[13] + 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_MsgVoteChainMetaResponse_messageType fastReflection_MsgVoteChainMetaResponse_messageType +var _ protoreflect.MessageType = fastReflection_MsgVoteChainMetaResponse_messageType{} + +type fastReflection_MsgVoteChainMetaResponse_messageType struct{} + +func (x fastReflection_MsgVoteChainMetaResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgVoteChainMetaResponse)(nil) +} +func (x fastReflection_MsgVoteChainMetaResponse_messageType) New() protoreflect.Message { + return new(fastReflection_MsgVoteChainMetaResponse) +} +func (x fastReflection_MsgVoteChainMetaResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgVoteChainMetaResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgVoteChainMetaResponse) Descriptor() protoreflect.MessageDescriptor { + return md_MsgVoteChainMetaResponse +} + +// 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_MsgVoteChainMetaResponse) Type() protoreflect.MessageType { + return _fastReflection_MsgVoteChainMetaResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgVoteChainMetaResponse) New() protoreflect.Message { + return new(fastReflection_MsgVoteChainMetaResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgVoteChainMetaResponse) Interface() protoreflect.ProtoMessage { + return (*MsgVoteChainMetaResponse)(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_MsgVoteChainMetaResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +} + +// 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_MsgVoteChainMetaResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMetaResponse 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_MsgVoteChainMetaResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMetaResponse 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_MsgVoteChainMetaResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMetaResponse 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_MsgVoteChainMetaResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMetaResponse 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_MsgVoteChainMetaResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMetaResponse 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_MsgVoteChainMetaResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMetaResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.MsgVoteChainMetaResponse 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_MsgVoteChainMetaResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.MsgVoteChainMetaResponse", 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_MsgVoteChainMetaResponse) 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_MsgVoteChainMetaResponse) 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_MsgVoteChainMetaResponse) 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_MsgVoteChainMetaResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgVoteChainMetaResponse) + 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.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().(*MsgVoteChainMetaResponse) + 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 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().(*MsgVoteChainMetaResponse) + 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: MsgVoteChainMetaResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgVoteChainMetaResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 @@ -6163,6 +7099,93 @@ func (*MsgVoteGasPriceResponse) Descriptor() ([]byte, []int) { return file_uexecutor_v1_tx_proto_rawDescGZIP(), []int{11} } +// MsgVoteChainMeta is broadcasted by Universal Validators to submit observed chain metadata (gas price + block height) +type MsgVoteChainMeta struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` // Universal Validator address submitting the vote + ObservedChainId string `protobuf:"bytes,2,opt,name=observed_chain_id,json=observedChainId,proto3" json:"observed_chain_id,omitempty"` // CAIP-2 chain ID of observed external chain (e.g. "eip155:1") + Price uint64 `protobuf:"varint,3,opt,name=price,proto3" json:"price,omitempty"` // Observed gas price in wei + ChainHeight uint64 `protobuf:"varint,4,opt,name=chain_height,json=chainHeight,proto3" json:"chain_height,omitempty"` // Block height from which observation was made +} + +func (x *MsgVoteChainMeta) Reset() { + *x = MsgVoteChainMeta{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_tx_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgVoteChainMeta) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgVoteChainMeta) ProtoMessage() {} + +// Deprecated: Use MsgVoteChainMeta.ProtoReflect.Descriptor instead. +func (*MsgVoteChainMeta) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_tx_proto_rawDescGZIP(), []int{12} +} + +func (x *MsgVoteChainMeta) GetSigner() string { + if x != nil { + return x.Signer + } + return "" +} + +func (x *MsgVoteChainMeta) GetObservedChainId() string { + if x != nil { + return x.ObservedChainId + } + return "" +} + +func (x *MsgVoteChainMeta) GetPrice() uint64 { + if x != nil { + return x.Price + } + return 0 +} + +func (x *MsgVoteChainMeta) GetChainHeight() uint64 { + if x != nil { + return x.ChainHeight + } + return 0 +} + +// MsgVoteChainMetaResponse defines the response for MsgVoteChainMeta +type MsgVoteChainMetaResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *MsgVoteChainMetaResponse) Reset() { + *x = MsgVoteChainMetaResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_tx_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgVoteChainMetaResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgVoteChainMetaResponse) ProtoMessage() {} + +// Deprecated: Use MsgVoteChainMetaResponse.ProtoReflect.Descriptor instead. +func (*MsgVoteChainMetaResponse) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_tx_proto_rawDescGZIP(), []int{13} +} + var File_uexecutor_v1_tx_proto protoreflect.FileDescriptor var file_uexecutor_v1_tx_proto_rawDesc = []byte{ @@ -6172,152 +7195,174 @@ var file_uexecutor_v1_tx_proto_rawDesc = []byte{ 0x6e, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x73, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x73, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, - 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xab, 0x01, 0x0a, - 0x0f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x04, - 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x2c, 0x82, 0xe7, - 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x8a, 0xe7, 0xb0, 0x2a, - 0x19, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x4d, 0x73, 0x67, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, - 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc0, 0x02, 0x0a, 0x11, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, - 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x52, 0x0a, - 0x14, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x75, 0x65, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xab, 0x01, 0x0a, 0x0f, + 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, + 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x04, 0xc8, + 0xde, 0x1f, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x2c, 0x82, 0xe7, 0xb0, + 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x8a, 0xe7, 0xb0, 0x2a, 0x19, + 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc0, 0x02, 0x0a, 0x11, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, + 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x14, + 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x12, 0x75, 0x6e, + 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, + 0x12, 0x4b, 0x0a, 0x11, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x12, 0x75, - 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, - 0x64, 0x12, 0x4b, 0x0a, 0x11, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x75, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x75, 0x6e, - 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x2b, - 0x0a, 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x65, 0x72, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x3a, 0x2b, 0x82, 0xe7, 0xb0, - 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x8a, 0xe7, 0xb0, 0x2a, 0x1b, 0x75, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x4d, 0x73, 0x67, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa9, 0x02, 0x0a, 0x0d, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, - 0x72, 0x61, 0x74, 0x65, 0x55, 0x45, 0x41, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x14, 0x75, 0x6e, 0x69, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x12, 0x75, 0x6e, 0x69, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x4b, 0x0a, - 0x11, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x27, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x72, 0x8a, 0xe7, 0xb0, 0x2a, 0x17, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2f, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, 0x45, - 0x41, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, - 0x45, 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x0e, 0x4d, - 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x30, 0x0a, - 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, - 0x2f, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 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, - 0x3a, 0x21, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x8a, 0xe7, 0xb0, - 0x2a, 0x11, 0x75, 0x65, 0x2f, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xde, 0x01, - 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x72, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x75, 0x74, 0x78, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x75, 0x74, 0x78, 0x49, 0x64, 0x12, - 0x42, 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x04, - 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, 0x3a, 0x29, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, - 0x8a, 0xe7, 0xb0, 0x2a, 0x19, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x4d, - 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x19, - 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd3, 0x01, 0x0a, 0x0f, 0x4d, 0x73, - 0x67, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a, - 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, - 0x2a, 0x0a, 0x11, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x62, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x70, - 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, - 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x29, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x72, 0x8a, 0xe7, 0xb0, 0x2a, 0x19, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, - 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x22, - 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8d, 0x04, 0x0a, 0x03, 0x4d, - 0x73, 0x67, 0x12, 0x54, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x12, 0x1d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x1a, 0x25, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0e, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1f, 0x2e, 0x75, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x1a, 0x27, 0x2e, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x45, 0x78, + 0x72, 0x73, 0x61, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x75, 0x6e, 0x69, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x2b, 0x0a, + 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x3a, 0x2b, 0x82, 0xe7, 0xb0, 0x2a, + 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x8a, 0xe7, 0xb0, 0x2a, 0x1b, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, - 0x45, 0x41, 0x12, 0x1b, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, 0x45, 0x41, 0x1a, - 0x23, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, 0x45, 0x41, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x12, 0x1c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x1a, 0x24, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0c, 0x56, 0x6f, 0x74, 0x65, 0x4f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x1a, 0x25, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, - 0x0c, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1d, 0x2e, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa9, 0x02, 0x0a, 0x0d, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, + 0x61, 0x74, 0x65, 0x55, 0x45, 0x41, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x12, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x11, + 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x27, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, + 0x67, 0x6e, 0x65, 0x72, 0x8a, 0xe7, 0xb0, 0x2a, 0x17, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2f, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, 0x45, 0x41, + 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, 0x45, + 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x0e, 0x4d, 0x73, + 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x30, 0x0a, 0x06, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, + 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x2f, + 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 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, 0x3a, + 0x21, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x8a, 0xe7, 0xb0, 0x2a, + 0x11, 0x75, 0x65, 0x2f, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xde, 0x01, 0x0a, + 0x0f, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x75, 0x74, 0x78, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x75, 0x74, 0x78, 0x49, 0x64, 0x12, 0x42, + 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x04, 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, 0x3a, 0x29, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x8a, + 0xe7, 0xb0, 0x2a, 0x19, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x4d, 0x73, + 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x19, 0x0a, + 0x17, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd3, 0x01, 0x0a, 0x0f, 0x4d, 0x73, 0x67, + 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x06, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, + 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x2a, + 0x0a, 0x11, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, + 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x3a, 0x29, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, + 0x8a, 0xe7, 0xb0, 0x2a, 0x19, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x4d, + 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x22, 0x19, + 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd5, 0x01, 0x0a, 0x10, 0x4d, 0x73, + 0x67, 0x56, 0x6f, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x30, + 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, + 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, + 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x62, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x48, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x2a, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x8a, 0xe7, 0xb0, 0x2a, 0x1a, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2f, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, + 0x61, 0x22, 0x1a, 0x0a, 0x18, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe6, 0x04, + 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x54, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x25, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0e, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1f, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, - 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x1a, 0x25, 0x2e, 0x75, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, - 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0xaf, 0x01, 0x0a, 0x10, 0x63, - 0x6f, 0x6d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x42, - 0x07, 0x54, 0x78, 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, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x1a, 0x27, + 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, + 0x67, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x4d, 0x69, 0x67, 0x72, 0x61, + 0x74, 0x65, 0x55, 0x45, 0x41, 0x12, 0x1b, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, + 0x45, 0x41, 0x1a, 0x23, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x55, 0x45, 0x41, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x56, 0x6f, 0x74, 0x65, 0x49, + 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x1a, 0x24, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0c, 0x56, 0x6f, + 0x74, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1d, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, + 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x1a, 0x25, 0x2e, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, + 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x54, 0x0a, 0x0c, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x12, 0x1d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x1a, + 0x25, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0d, 0x56, 0x6f, 0x74, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x26, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x56, 0x6f, 0x74, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, + 0x05, 0x80, 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0xaf, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x75, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x07, 0x54, 0x78, 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 ( @@ -6332,7 +7377,7 @@ func file_uexecutor_v1_tx_proto_rawDescGZIP() []byte { return file_uexecutor_v1_tx_proto_rawDescData } -var file_uexecutor_v1_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_uexecutor_v1_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 14) var file_uexecutor_v1_tx_proto_goTypes = []interface{}{ (*MsgUpdateParams)(nil), // 0: uexecutor.v1.MsgUpdateParams (*MsgUpdateParamsResponse)(nil), // 1: uexecutor.v1.MsgUpdateParamsResponse @@ -6346,35 +7391,39 @@ var file_uexecutor_v1_tx_proto_goTypes = []interface{}{ (*MsgVoteOutboundResponse)(nil), // 9: uexecutor.v1.MsgVoteOutboundResponse (*MsgVoteGasPrice)(nil), // 10: uexecutor.v1.MsgVoteGasPrice (*MsgVoteGasPriceResponse)(nil), // 11: uexecutor.v1.MsgVoteGasPriceResponse - (*Params)(nil), // 12: uexecutor.v1.Params - (*UniversalAccountId)(nil), // 13: uexecutor.v1.UniversalAccountId - (*UniversalPayload)(nil), // 14: uexecutor.v1.UniversalPayload - (*MigrationPayload)(nil), // 15: uexecutor.v1.MigrationPayload - (*Inbound)(nil), // 16: uexecutor.v1.Inbound - (*OutboundObservation)(nil), // 17: uexecutor.v1.OutboundObservation + (*MsgVoteChainMeta)(nil), // 12: uexecutor.v1.MsgVoteChainMeta + (*MsgVoteChainMetaResponse)(nil), // 13: uexecutor.v1.MsgVoteChainMetaResponse + (*Params)(nil), // 14: uexecutor.v1.Params + (*UniversalAccountId)(nil), // 15: uexecutor.v1.UniversalAccountId + (*UniversalPayload)(nil), // 16: uexecutor.v1.UniversalPayload + (*MigrationPayload)(nil), // 17: uexecutor.v1.MigrationPayload + (*Inbound)(nil), // 18: uexecutor.v1.Inbound + (*OutboundObservation)(nil), // 19: uexecutor.v1.OutboundObservation } var file_uexecutor_v1_tx_proto_depIdxs = []int32{ - 12, // 0: uexecutor.v1.MsgUpdateParams.params:type_name -> uexecutor.v1.Params - 13, // 1: uexecutor.v1.MsgExecutePayload.universal_account_id:type_name -> uexecutor.v1.UniversalAccountId - 14, // 2: uexecutor.v1.MsgExecutePayload.universal_payload:type_name -> uexecutor.v1.UniversalPayload - 13, // 3: uexecutor.v1.MsgMigrateUEA.universal_account_id:type_name -> uexecutor.v1.UniversalAccountId - 15, // 4: uexecutor.v1.MsgMigrateUEA.migration_payload:type_name -> uexecutor.v1.MigrationPayload - 16, // 5: uexecutor.v1.MsgVoteInbound.inbound:type_name -> uexecutor.v1.Inbound - 17, // 6: uexecutor.v1.MsgVoteOutbound.observed_tx:type_name -> uexecutor.v1.OutboundObservation + 14, // 0: uexecutor.v1.MsgUpdateParams.params:type_name -> uexecutor.v1.Params + 15, // 1: uexecutor.v1.MsgExecutePayload.universal_account_id:type_name -> uexecutor.v1.UniversalAccountId + 16, // 2: uexecutor.v1.MsgExecutePayload.universal_payload:type_name -> uexecutor.v1.UniversalPayload + 15, // 3: uexecutor.v1.MsgMigrateUEA.universal_account_id:type_name -> uexecutor.v1.UniversalAccountId + 17, // 4: uexecutor.v1.MsgMigrateUEA.migration_payload:type_name -> uexecutor.v1.MigrationPayload + 18, // 5: uexecutor.v1.MsgVoteInbound.inbound:type_name -> uexecutor.v1.Inbound + 19, // 6: uexecutor.v1.MsgVoteOutbound.observed_tx:type_name -> uexecutor.v1.OutboundObservation 0, // 7: uexecutor.v1.Msg.UpdateParams:input_type -> uexecutor.v1.MsgUpdateParams 2, // 8: uexecutor.v1.Msg.ExecutePayload:input_type -> uexecutor.v1.MsgExecutePayload 4, // 9: uexecutor.v1.Msg.MigrateUEA:input_type -> uexecutor.v1.MsgMigrateUEA 6, // 10: uexecutor.v1.Msg.VoteInbound:input_type -> uexecutor.v1.MsgVoteInbound 8, // 11: uexecutor.v1.Msg.VoteOutbound:input_type -> uexecutor.v1.MsgVoteOutbound 10, // 12: uexecutor.v1.Msg.VoteGasPrice:input_type -> uexecutor.v1.MsgVoteGasPrice - 1, // 13: uexecutor.v1.Msg.UpdateParams:output_type -> uexecutor.v1.MsgUpdateParamsResponse - 3, // 14: uexecutor.v1.Msg.ExecutePayload:output_type -> uexecutor.v1.MsgExecutePayloadResponse - 5, // 15: uexecutor.v1.Msg.MigrateUEA:output_type -> uexecutor.v1.MsgMigrateUEAResponse - 7, // 16: uexecutor.v1.Msg.VoteInbound:output_type -> uexecutor.v1.MsgVoteInboundResponse - 9, // 17: uexecutor.v1.Msg.VoteOutbound:output_type -> uexecutor.v1.MsgVoteOutboundResponse - 11, // 18: uexecutor.v1.Msg.VoteGasPrice:output_type -> uexecutor.v1.MsgVoteGasPriceResponse - 13, // [13:19] is the sub-list for method output_type - 7, // [7:13] is the sub-list for method input_type + 12, // 13: uexecutor.v1.Msg.VoteChainMeta:input_type -> uexecutor.v1.MsgVoteChainMeta + 1, // 14: uexecutor.v1.Msg.UpdateParams:output_type -> uexecutor.v1.MsgUpdateParamsResponse + 3, // 15: uexecutor.v1.Msg.ExecutePayload:output_type -> uexecutor.v1.MsgExecutePayloadResponse + 5, // 16: uexecutor.v1.Msg.MigrateUEA:output_type -> uexecutor.v1.MsgMigrateUEAResponse + 7, // 17: uexecutor.v1.Msg.VoteInbound:output_type -> uexecutor.v1.MsgVoteInboundResponse + 9, // 18: uexecutor.v1.Msg.VoteOutbound:output_type -> uexecutor.v1.MsgVoteOutboundResponse + 11, // 19: uexecutor.v1.Msg.VoteGasPrice:output_type -> uexecutor.v1.MsgVoteGasPriceResponse + 13, // 20: uexecutor.v1.Msg.VoteChainMeta:output_type -> uexecutor.v1.MsgVoteChainMetaResponse + 14, // [14:21] is the sub-list for method output_type + 7, // [7:14] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name 7, // [7:7] is the sub-list for extension extendee 0, // [0:7] is the sub-list for field type_name @@ -6386,6 +7435,7 @@ func file_uexecutor_v1_tx_proto_init() { return } file_uexecutor_v1_types_proto_init() + file_uexecutor_v1_chain_meta_proto_init() if !protoimpl.UnsafeEnabled { file_uexecutor_v1_tx_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MsgUpdateParams); i { @@ -6531,6 +7581,30 @@ func file_uexecutor_v1_tx_proto_init() { return nil } } + file_uexecutor_v1_tx_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgVoteChainMeta); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_uexecutor_v1_tx_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgVoteChainMetaResponse); 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{ @@ -6538,7 +7612,7 @@ func file_uexecutor_v1_tx_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_uexecutor_v1_tx_proto_rawDesc, NumEnums: 0, - NumMessages: 12, + NumMessages: 14, NumExtensions: 0, NumServices: 1, }, diff --git a/api/uexecutor/v1/tx_grpc.pb.go b/api/uexecutor/v1/tx_grpc.pb.go index 7da7d9f3..f2e562d4 100644 --- a/api/uexecutor/v1/tx_grpc.pb.go +++ b/api/uexecutor/v1/tx_grpc.pb.go @@ -25,6 +25,7 @@ const ( Msg_VoteInbound_FullMethodName = "/uexecutor.v1.Msg/VoteInbound" Msg_VoteOutbound_FullMethodName = "/uexecutor.v1.Msg/VoteOutbound" Msg_VoteGasPrice_FullMethodName = "/uexecutor.v1.Msg/VoteGasPrice" + Msg_VoteChainMeta_FullMethodName = "/uexecutor.v1.Msg/VoteChainMeta" ) // MsgClient is the client API for Msg service. @@ -45,6 +46,8 @@ type MsgClient interface { VoteOutbound(ctx context.Context, in *MsgVoteOutbound, opts ...grpc.CallOption) (*MsgVoteOutboundResponse, error) // VoteGasPrice defines a message for universal validators to vote on the gas price VoteGasPrice(ctx context.Context, in *MsgVoteGasPrice, opts ...grpc.CallOption) (*MsgVoteGasPriceResponse, error) + // VoteChainMeta defines a message for universal validators to vote on chain metadata (gas price + block height) + VoteChainMeta(ctx context.Context, in *MsgVoteChainMeta, opts ...grpc.CallOption) (*MsgVoteChainMetaResponse, error) } type msgClient struct { @@ -109,6 +112,15 @@ func (c *msgClient) VoteGasPrice(ctx context.Context, in *MsgVoteGasPrice, opts return out, nil } +func (c *msgClient) VoteChainMeta(ctx context.Context, in *MsgVoteChainMeta, opts ...grpc.CallOption) (*MsgVoteChainMetaResponse, error) { + out := new(MsgVoteChainMetaResponse) + err := c.cc.Invoke(ctx, Msg_VoteChainMeta_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer // for forward compatibility @@ -127,6 +139,8 @@ type MsgServer interface { VoteOutbound(context.Context, *MsgVoteOutbound) (*MsgVoteOutboundResponse, error) // VoteGasPrice defines a message for universal validators to vote on the gas price VoteGasPrice(context.Context, *MsgVoteGasPrice) (*MsgVoteGasPriceResponse, error) + // VoteChainMeta defines a message for universal validators to vote on chain metadata (gas price + block height) + VoteChainMeta(context.Context, *MsgVoteChainMeta) (*MsgVoteChainMetaResponse, error) mustEmbedUnimplementedMsgServer() } @@ -152,6 +166,9 @@ func (UnimplementedMsgServer) VoteOutbound(context.Context, *MsgVoteOutbound) (* func (UnimplementedMsgServer) VoteGasPrice(context.Context, *MsgVoteGasPrice) (*MsgVoteGasPriceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method VoteGasPrice not implemented") } +func (UnimplementedMsgServer) VoteChainMeta(context.Context, *MsgVoteChainMeta) (*MsgVoteChainMetaResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteChainMeta not implemented") +} func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} // UnsafeMsgServer may be embedded to opt out of forward compatibility for this service. @@ -273,6 +290,24 @@ func _Msg_VoteGasPrice_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Msg_VoteChainMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVoteChainMeta) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).VoteChainMeta(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Msg_VoteChainMeta_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).VoteChainMeta(ctx, req.(*MsgVoteChainMeta)) + } + return interceptor(ctx, in, info, handler) +} + // Msg_ServiceDesc is the grpc.ServiceDesc for Msg service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -304,6 +339,10 @@ var Msg_ServiceDesc = grpc.ServiceDesc{ MethodName: "VoteGasPrice", Handler: _Msg_VoteGasPrice_Handler, }, + { + MethodName: "VoteChainMeta", + Handler: _Msg_VoteChainMeta_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/tx.proto", diff --git a/api/uexecutor/v1/types.pulsar.go b/api/uexecutor/v1/types.pulsar.go index 6f3d4cbd..1090a951 100644 --- a/api/uexecutor/v1/types.pulsar.go +++ b/api/uexecutor/v1/types.pulsar.go @@ -4698,6 +4698,7 @@ var ( fd_OutboundObservation_block_height protoreflect.FieldDescriptor fd_OutboundObservation_tx_hash protoreflect.FieldDescriptor fd_OutboundObservation_error_msg protoreflect.FieldDescriptor + fd_OutboundObservation_gas_fee_used protoreflect.FieldDescriptor ) func init() { @@ -4707,6 +4708,7 @@ func init() { fd_OutboundObservation_block_height = md_OutboundObservation.Fields().ByName("block_height") fd_OutboundObservation_tx_hash = md_OutboundObservation.Fields().ByName("tx_hash") fd_OutboundObservation_error_msg = md_OutboundObservation.Fields().ByName("error_msg") + fd_OutboundObservation_gas_fee_used = md_OutboundObservation.Fields().ByName("gas_fee_used") } var _ protoreflect.Message = (*fastReflection_OutboundObservation)(nil) @@ -4798,6 +4800,12 @@ func (x *fastReflection_OutboundObservation) Range(f func(protoreflect.FieldDesc return } } + if x.GasFeeUsed != "" { + value := protoreflect.ValueOfString(x.GasFeeUsed) + if !f(fd_OutboundObservation_gas_fee_used, value) { + return + } + } } // Has reports whether a field is populated. @@ -4821,6 +4829,8 @@ func (x *fastReflection_OutboundObservation) Has(fd protoreflect.FieldDescriptor return x.TxHash != "" case "uexecutor.v1.OutboundObservation.error_msg": return x.ErrorMsg != "" + case "uexecutor.v1.OutboundObservation.gas_fee_used": + return x.GasFeeUsed != "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundObservation")) @@ -4845,6 +4855,8 @@ func (x *fastReflection_OutboundObservation) Clear(fd protoreflect.FieldDescript x.TxHash = "" case "uexecutor.v1.OutboundObservation.error_msg": x.ErrorMsg = "" + case "uexecutor.v1.OutboundObservation.gas_fee_used": + x.GasFeeUsed = "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundObservation")) @@ -4873,6 +4885,9 @@ func (x *fastReflection_OutboundObservation) Get(descriptor protoreflect.FieldDe case "uexecutor.v1.OutboundObservation.error_msg": value := x.ErrorMsg return protoreflect.ValueOfString(value) + case "uexecutor.v1.OutboundObservation.gas_fee_used": + value := x.GasFeeUsed + return protoreflect.ValueOfString(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundObservation")) @@ -4901,6 +4916,8 @@ func (x *fastReflection_OutboundObservation) Set(fd protoreflect.FieldDescriptor x.TxHash = value.Interface().(string) case "uexecutor.v1.OutboundObservation.error_msg": x.ErrorMsg = value.Interface().(string) + case "uexecutor.v1.OutboundObservation.gas_fee_used": + x.GasFeeUsed = value.Interface().(string) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundObservation")) @@ -4929,6 +4946,8 @@ func (x *fastReflection_OutboundObservation) Mutable(fd protoreflect.FieldDescri panic(fmt.Errorf("field tx_hash of message uexecutor.v1.OutboundObservation is not mutable")) case "uexecutor.v1.OutboundObservation.error_msg": panic(fmt.Errorf("field error_msg of message uexecutor.v1.OutboundObservation is not mutable")) + case "uexecutor.v1.OutboundObservation.gas_fee_used": + panic(fmt.Errorf("field gas_fee_used of message uexecutor.v1.OutboundObservation is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundObservation")) @@ -4950,6 +4969,8 @@ func (x *fastReflection_OutboundObservation) NewField(fd protoreflect.FieldDescr return protoreflect.ValueOfString("") case "uexecutor.v1.OutboundObservation.error_msg": return protoreflect.ValueOfString("") + case "uexecutor.v1.OutboundObservation.gas_fee_used": + return protoreflect.ValueOfString("") default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundObservation")) @@ -5033,6 +5054,10 @@ func (x *fastReflection_OutboundObservation) ProtoMethods() *protoiface.Methods if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } + l = len(x.GasFeeUsed) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -5062,6 +5087,13 @@ func (x *fastReflection_OutboundObservation) ProtoMethods() *protoiface.Methods i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if len(x.GasFeeUsed) > 0 { + i -= len(x.GasFeeUsed) + copy(dAtA[i:], x.GasFeeUsed) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.GasFeeUsed))) + i-- + dAtA[i] = 0x2a + } if len(x.ErrorMsg) > 0 { i -= len(x.ErrorMsg) copy(dAtA[i:], x.ErrorMsg) @@ -5243,6 +5275,38 @@ func (x *fastReflection_OutboundObservation) ProtoMethods() *protoiface.Methods } x.ErrorMsg = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 5: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field GasFeeUsed", 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.GasFeeUsed = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -5779,6 +5843,11 @@ var ( fd_OutboundTx_outbound_status protoreflect.FieldDescriptor fd_OutboundTx_revert_instructions protoreflect.FieldDescriptor fd_OutboundTx_pc_revert_execution protoreflect.FieldDescriptor + fd_OutboundTx_gas_price protoreflect.FieldDescriptor + fd_OutboundTx_gas_fee protoreflect.FieldDescriptor + fd_OutboundTx_pc_refund_execution protoreflect.FieldDescriptor + fd_OutboundTx_refund_swap_error protoreflect.FieldDescriptor + fd_OutboundTx_gas_token protoreflect.FieldDescriptor ) func init() { @@ -5799,6 +5868,11 @@ func init() { fd_OutboundTx_outbound_status = md_OutboundTx.Fields().ByName("outbound_status") fd_OutboundTx_revert_instructions = md_OutboundTx.Fields().ByName("revert_instructions") fd_OutboundTx_pc_revert_execution = md_OutboundTx.Fields().ByName("pc_revert_execution") + fd_OutboundTx_gas_price = md_OutboundTx.Fields().ByName("gas_price") + fd_OutboundTx_gas_fee = md_OutboundTx.Fields().ByName("gas_fee") + fd_OutboundTx_pc_refund_execution = md_OutboundTx.Fields().ByName("pc_refund_execution") + fd_OutboundTx_refund_swap_error = md_OutboundTx.Fields().ByName("refund_swap_error") + fd_OutboundTx_gas_token = md_OutboundTx.Fields().ByName("gas_token") } var _ protoreflect.Message = (*fastReflection_OutboundTx)(nil) @@ -5956,6 +6030,36 @@ func (x *fastReflection_OutboundTx) Range(f func(protoreflect.FieldDescriptor, p return } } + if x.GasPrice != "" { + value := protoreflect.ValueOfString(x.GasPrice) + if !f(fd_OutboundTx_gas_price, value) { + return + } + } + if x.GasFee != "" { + value := protoreflect.ValueOfString(x.GasFee) + if !f(fd_OutboundTx_gas_fee, value) { + return + } + } + if x.PcRefundExecution != nil { + value := protoreflect.ValueOfMessage(x.PcRefundExecution.ProtoReflect()) + if !f(fd_OutboundTx_pc_refund_execution, value) { + return + } + } + if x.RefundSwapError != "" { + value := protoreflect.ValueOfString(x.RefundSwapError) + if !f(fd_OutboundTx_refund_swap_error, value) { + return + } + } + if x.GasToken != "" { + value := protoreflect.ValueOfString(x.GasToken) + if !f(fd_OutboundTx_gas_token, value) { + return + } + } } // Has reports whether a field is populated. @@ -6001,6 +6105,16 @@ func (x *fastReflection_OutboundTx) Has(fd protoreflect.FieldDescriptor) bool { return x.RevertInstructions != nil case "uexecutor.v1.OutboundTx.pc_revert_execution": return x.PcRevertExecution != nil + case "uexecutor.v1.OutboundTx.gas_price": + return x.GasPrice != "" + case "uexecutor.v1.OutboundTx.gas_fee": + return x.GasFee != "" + case "uexecutor.v1.OutboundTx.pc_refund_execution": + return x.PcRefundExecution != nil + case "uexecutor.v1.OutboundTx.refund_swap_error": + return x.RefundSwapError != "" + case "uexecutor.v1.OutboundTx.gas_token": + return x.GasToken != "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6047,6 +6161,16 @@ func (x *fastReflection_OutboundTx) Clear(fd protoreflect.FieldDescriptor) { x.RevertInstructions = nil case "uexecutor.v1.OutboundTx.pc_revert_execution": x.PcRevertExecution = nil + case "uexecutor.v1.OutboundTx.gas_price": + x.GasPrice = "" + case "uexecutor.v1.OutboundTx.gas_fee": + x.GasFee = "" + case "uexecutor.v1.OutboundTx.pc_refund_execution": + x.PcRefundExecution = nil + case "uexecutor.v1.OutboundTx.refund_swap_error": + x.RefundSwapError = "" + case "uexecutor.v1.OutboundTx.gas_token": + x.GasToken = "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6108,6 +6232,21 @@ func (x *fastReflection_OutboundTx) Get(descriptor protoreflect.FieldDescriptor) case "uexecutor.v1.OutboundTx.pc_revert_execution": value := x.PcRevertExecution return protoreflect.ValueOfMessage(value.ProtoReflect()) + case "uexecutor.v1.OutboundTx.gas_price": + value := x.GasPrice + return protoreflect.ValueOfString(value) + case "uexecutor.v1.OutboundTx.gas_fee": + value := x.GasFee + return protoreflect.ValueOfString(value) + case "uexecutor.v1.OutboundTx.pc_refund_execution": + value := x.PcRefundExecution + return protoreflect.ValueOfMessage(value.ProtoReflect()) + case "uexecutor.v1.OutboundTx.refund_swap_error": + value := x.RefundSwapError + return protoreflect.ValueOfString(value) + case "uexecutor.v1.OutboundTx.gas_token": + value := x.GasToken + return protoreflect.ValueOfString(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6158,6 +6297,16 @@ func (x *fastReflection_OutboundTx) Set(fd protoreflect.FieldDescriptor, value p x.RevertInstructions = value.Message().Interface().(*RevertInstructions) case "uexecutor.v1.OutboundTx.pc_revert_execution": x.PcRevertExecution = value.Message().Interface().(*PCTx) + case "uexecutor.v1.OutboundTx.gas_price": + x.GasPrice = value.Interface().(string) + case "uexecutor.v1.OutboundTx.gas_fee": + x.GasFee = value.Interface().(string) + case "uexecutor.v1.OutboundTx.pc_refund_execution": + x.PcRefundExecution = value.Message().Interface().(*PCTx) + case "uexecutor.v1.OutboundTx.refund_swap_error": + x.RefundSwapError = value.Interface().(string) + case "uexecutor.v1.OutboundTx.gas_token": + x.GasToken = value.Interface().(string) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6198,6 +6347,11 @@ func (x *fastReflection_OutboundTx) Mutable(fd protoreflect.FieldDescriptor) pro x.PcRevertExecution = new(PCTx) } return protoreflect.ValueOfMessage(x.PcRevertExecution.ProtoReflect()) + case "uexecutor.v1.OutboundTx.pc_refund_execution": + if x.PcRefundExecution == nil { + x.PcRefundExecution = new(PCTx) + } + return protoreflect.ValueOfMessage(x.PcRefundExecution.ProtoReflect()) case "uexecutor.v1.OutboundTx.destination_chain": panic(fmt.Errorf("field destination_chain of message uexecutor.v1.OutboundTx is not mutable")) case "uexecutor.v1.OutboundTx.recipient": @@ -6220,6 +6374,14 @@ func (x *fastReflection_OutboundTx) Mutable(fd protoreflect.FieldDescriptor) pro panic(fmt.Errorf("field id of message uexecutor.v1.OutboundTx is not mutable")) case "uexecutor.v1.OutboundTx.outbound_status": panic(fmt.Errorf("field outbound_status of message uexecutor.v1.OutboundTx is not mutable")) + case "uexecutor.v1.OutboundTx.gas_price": + panic(fmt.Errorf("field gas_price of message uexecutor.v1.OutboundTx is not mutable")) + case "uexecutor.v1.OutboundTx.gas_fee": + panic(fmt.Errorf("field gas_fee of message uexecutor.v1.OutboundTx is not mutable")) + case "uexecutor.v1.OutboundTx.refund_swap_error": + panic(fmt.Errorf("field refund_swap_error of message uexecutor.v1.OutboundTx is not mutable")) + case "uexecutor.v1.OutboundTx.gas_token": + panic(fmt.Errorf("field gas_token of message uexecutor.v1.OutboundTx is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6267,6 +6429,17 @@ func (x *fastReflection_OutboundTx) NewField(fd protoreflect.FieldDescriptor) pr case "uexecutor.v1.OutboundTx.pc_revert_execution": m := new(PCTx) return protoreflect.ValueOfMessage(m.ProtoReflect()) + case "uexecutor.v1.OutboundTx.gas_price": + return protoreflect.ValueOfString("") + case "uexecutor.v1.OutboundTx.gas_fee": + return protoreflect.ValueOfString("") + case "uexecutor.v1.OutboundTx.pc_refund_execution": + m := new(PCTx) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + case "uexecutor.v1.OutboundTx.refund_swap_error": + return protoreflect.ValueOfString("") + case "uexecutor.v1.OutboundTx.gas_token": + return protoreflect.ValueOfString("") default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6394,6 +6567,26 @@ func (x *fastReflection_OutboundTx) ProtoMethods() *protoiface.Methods { l = options.Size(x.PcRevertExecution) n += 1 + l + runtime.Sov(uint64(l)) } + l = len(x.GasPrice) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } + l = len(x.GasFee) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } + if x.PcRefundExecution != nil { + l = options.Size(x.PcRefundExecution) + n += 2 + l + runtime.Sov(uint64(l)) + } + l = len(x.RefundSwapError) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } + l = len(x.GasToken) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -6423,6 +6616,58 @@ func (x *fastReflection_OutboundTx) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if len(x.GasToken) > 0 { + i -= len(x.GasToken) + copy(dAtA[i:], x.GasToken) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.GasToken))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa2 + } + if len(x.RefundSwapError) > 0 { + i -= len(x.RefundSwapError) + copy(dAtA[i:], x.RefundSwapError) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.RefundSwapError))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x9a + } + if x.PcRefundExecution != nil { + encoded, err := options.Marshal(x.PcRefundExecution) + 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] = 0x1 + i-- + dAtA[i] = 0x92 + } + if len(x.GasFee) > 0 { + i -= len(x.GasFee) + copy(dAtA[i:], x.GasFee) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.GasFee))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + if len(x.GasPrice) > 0 { + i -= len(x.GasPrice) + copy(dAtA[i:], x.GasPrice) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.GasPrice))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } if x.PcRevertExecution != nil { encoded, err := options.Marshal(x.PcRevertExecution) if err != nil { @@ -7071,6 +7316,170 @@ func (x *fastReflection_OutboundTx) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex + case 16: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field GasPrice", 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.GasPrice = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 17: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field GasFee", 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.GasFee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 18: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field PcRefundExecution", 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.PcRefundExecution == nil { + x.PcRefundExecution = &PCTx{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.PcRefundExecution); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + case 19: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field RefundSwapError", 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.RefundSwapError = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 20: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field GasToken", 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.GasToken = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -7209,12 +7618,11 @@ func (x *_UniversalTx_4_list) IsValid() bool { } var ( - md_UniversalTx protoreflect.MessageDescriptor - fd_UniversalTx_id protoreflect.FieldDescriptor - fd_UniversalTx_inbound_tx protoreflect.FieldDescriptor - fd_UniversalTx_pc_tx protoreflect.FieldDescriptor - fd_UniversalTx_outbound_tx protoreflect.FieldDescriptor - fd_UniversalTx_universal_status protoreflect.FieldDescriptor + md_UniversalTx protoreflect.MessageDescriptor + fd_UniversalTx_id protoreflect.FieldDescriptor + fd_UniversalTx_inbound_tx protoreflect.FieldDescriptor + fd_UniversalTx_pc_tx protoreflect.FieldDescriptor + fd_UniversalTx_outbound_tx protoreflect.FieldDescriptor ) func init() { @@ -7224,7 +7632,6 @@ func init() { fd_UniversalTx_inbound_tx = md_UniversalTx.Fields().ByName("inbound_tx") fd_UniversalTx_pc_tx = md_UniversalTx.Fields().ByName("pc_tx") fd_UniversalTx_outbound_tx = md_UniversalTx.Fields().ByName("outbound_tx") - fd_UniversalTx_universal_status = md_UniversalTx.Fields().ByName("universal_status") } var _ protoreflect.Message = (*fastReflection_UniversalTx)(nil) @@ -7316,12 +7723,6 @@ func (x *fastReflection_UniversalTx) Range(f func(protoreflect.FieldDescriptor, return } } - if x.UniversalStatus != 0 { - value := protoreflect.ValueOfEnum((protoreflect.EnumNumber)(x.UniversalStatus)) - if !f(fd_UniversalTx_universal_status, value) { - return - } - } } // Has reports whether a field is populated. @@ -7345,8 +7746,6 @@ func (x *fastReflection_UniversalTx) Has(fd protoreflect.FieldDescriptor) bool { return len(x.PcTx) != 0 case "uexecutor.v1.UniversalTx.outbound_tx": return len(x.OutboundTx) != 0 - case "uexecutor.v1.UniversalTx.universal_status": - return x.UniversalStatus != 0 default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.UniversalTx")) @@ -7371,8 +7770,6 @@ func (x *fastReflection_UniversalTx) Clear(fd protoreflect.FieldDescriptor) { x.PcTx = nil case "uexecutor.v1.UniversalTx.outbound_tx": x.OutboundTx = nil - case "uexecutor.v1.UniversalTx.universal_status": - x.UniversalStatus = 0 default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.UniversalTx")) @@ -7407,9 +7804,6 @@ func (x *fastReflection_UniversalTx) Get(descriptor protoreflect.FieldDescriptor } listValue := &_UniversalTx_4_list{list: &x.OutboundTx} return protoreflect.ValueOfList(listValue) - case "uexecutor.v1.UniversalTx.universal_status": - value := x.UniversalStatus - return protoreflect.ValueOfEnum((protoreflect.EnumNumber)(value)) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.UniversalTx")) @@ -7442,8 +7836,6 @@ func (x *fastReflection_UniversalTx) Set(fd protoreflect.FieldDescriptor, value lv := value.List() clv := lv.(*_UniversalTx_4_list) x.OutboundTx = *clv.list - case "uexecutor.v1.UniversalTx.universal_status": - x.UniversalStatus = (UniversalTxStatus)(value.Enum()) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.UniversalTx")) @@ -7483,8 +7875,6 @@ func (x *fastReflection_UniversalTx) Mutable(fd protoreflect.FieldDescriptor) pr return protoreflect.ValueOfList(value) case "uexecutor.v1.UniversalTx.id": panic(fmt.Errorf("field id of message uexecutor.v1.UniversalTx is not mutable")) - case "uexecutor.v1.UniversalTx.universal_status": - panic(fmt.Errorf("field universal_status of message uexecutor.v1.UniversalTx is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.UniversalTx")) @@ -7509,8 +7899,6 @@ func (x *fastReflection_UniversalTx) NewField(fd protoreflect.FieldDescriptor) p case "uexecutor.v1.UniversalTx.outbound_tx": list := []*OutboundTx{} return protoreflect.ValueOfList(&_UniversalTx_4_list{list: &list}) - case "uexecutor.v1.UniversalTx.universal_status": - return protoreflect.ValueOfEnum(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.UniversalTx")) @@ -7600,9 +7988,6 @@ func (x *fastReflection_UniversalTx) ProtoMethods() *protoiface.Methods { n += 1 + l + runtime.Sov(uint64(l)) } } - if x.UniversalStatus != 0 { - n += 1 + runtime.Sov(uint64(x.UniversalStatus)) - } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -7632,11 +8017,6 @@ func (x *fastReflection_UniversalTx) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if x.UniversalStatus != 0 { - i = runtime.EncodeVarint(dAtA, i, uint64(x.UniversalStatus)) - i-- - dAtA[i] = 0x28 - } if len(x.OutboundTx) > 0 { for iNdEx := len(x.OutboundTx) - 1; iNdEx >= 0; iNdEx-- { encoded, err := options.Marshal(x.OutboundTx[iNdEx]) @@ -7875,25 +8255,6 @@ func (x *fastReflection_UniversalTx) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex - case 5: - if wireType != 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field UniversalStatus", wireType) - } - x.UniversalStatus = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - x.UniversalStatus |= UniversalTxStatus(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -10492,6 +10853,7 @@ const ( TxType_FUNDS_AND_PAYLOAD TxType = 4 TxType_PAYLOAD TxType = 5 TxType_INBOUND_REVERT TxType = 6 + TxType_RESCUE_FUNDS TxType = 7 ) // Enum value maps for TxType. @@ -10504,6 +10866,7 @@ var ( 4: "FUNDS_AND_PAYLOAD", 5: "PAYLOAD", 6: "INBOUND_REVERT", + 7: "RESCUE_FUNDS", } TxType_value = map[string]int32{ "UNSPECIFIED_TX": 0, @@ -10513,6 +10876,7 @@ var ( "FUNDS_AND_PAYLOAD": 4, "PAYLOAD": 5, "INBOUND_REVERT": 6, + "RESCUE_FUNDS": 7, } ) @@ -11081,6 +11445,7 @@ type OutboundObservation struct { BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` // block height on external chain TxHash string `protobuf:"bytes,3,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` // external chain tx hash ErrorMsg string `protobuf:"bytes,4,opt,name=error_msg,json=errorMsg,proto3" json:"error_msg,omitempty"` + GasFeeUsed string `protobuf:"bytes,5,opt,name=gas_fee_used,json=gasFeeUsed,proto3" json:"gas_fee_used,omitempty"` // actual gas fee consumed on destination chain; used to compute excess refund } func (x *OutboundObservation) Reset() { @@ -11131,6 +11496,13 @@ func (x *OutboundObservation) GetErrorMsg() string { return "" } +func (x *OutboundObservation) GetGasFeeUsed() string { + if x != nil { + return x.GasFeeUsed + } + return "" +} + type OriginatingPcTx struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -11194,6 +11566,11 @@ type OutboundTx struct { OutboundStatus Status `protobuf:"varint,13,opt,name=outbound_status,json=outboundStatus,proto3,enum=uexecutor.v1.Status" json:"outbound_status,omitempty"` // status of outbound tx RevertInstructions *RevertInstructions `protobuf:"bytes,14,opt,name=revert_instructions,json=revertInstructions,proto3" json:"revert_instructions,omitempty"` PcRevertExecution *PCTx `protobuf:"bytes,15,opt,name=pc_revert_execution,json=pcRevertExecution,proto3" json:"pc_revert_execution,omitempty"` + GasPrice string `protobuf:"bytes,16,opt,name=gas_price,json=gasPrice,proto3" json:"gas_price,omitempty"` // gas price on destination chain at time of outbound + GasFee string `protobuf:"bytes,17,opt,name=gas_fee,json=gasFee,proto3" json:"gas_fee,omitempty"` // gas fee paid to relayer on destination chain + PcRefundExecution *PCTx `protobuf:"bytes,18,opt,name=pc_refund_execution,json=pcRefundExecution,proto3" json:"pc_refund_execution,omitempty"` // PC tx that executed the gas refund (non-nil if refund ran) + RefundSwapError string `protobuf:"bytes,19,opt,name=refund_swap_error,json=refundSwapError,proto3" json:"refund_swap_error,omitempty"` // non-empty if swap-refund failed and we fell back to no-swap + GasToken string `protobuf:"bytes,20,opt,name=gas_token,json=gasToken,proto3" json:"gas_token,omitempty"` // gas token PRC20 address used to pay relayer fee } func (x *OutboundTx) Reset() { @@ -11321,16 +11698,50 @@ func (x *OutboundTx) GetPcRevertExecution() *PCTx { return nil } +func (x *OutboundTx) GetGasPrice() string { + if x != nil { + return x.GasPrice + } + return "" +} + +func (x *OutboundTx) GetGasFee() string { + if x != nil { + return x.GasFee + } + return "" +} + +func (x *OutboundTx) GetPcRefundExecution() *PCTx { + if x != nil { + return x.PcRefundExecution + } + return nil +} + +func (x *OutboundTx) GetRefundSwapError() string { + if x != nil { + return x.RefundSwapError + } + return "" +} + +func (x *OutboundTx) GetGasToken() string { + if x != nil { + return x.GasToken + } + return "" +} + type UniversalTx struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - InboundTx *Inbound `protobuf:"bytes,2,opt,name=inbound_tx,json=inboundTx,proto3" json:"inbound_tx,omitempty"` // Full inbound tx data - PcTx []*PCTx `protobuf:"bytes,3,rep,name=pc_tx,json=pcTx,proto3" json:"pc_tx,omitempty"` // Execution details on Push Chain - OutboundTx []*OutboundTx `protobuf:"bytes,4,rep,name=outbound_tx,json=outboundTx,proto3" json:"outbound_tx,omitempty"` // Outbound tx triggered by this tx - UniversalStatus UniversalTxStatus `protobuf:"varint,5,opt,name=universal_status,json=universalStatus,proto3,enum=uexecutor.v1.UniversalTxStatus" json:"universal_status,omitempty"` // Current status + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + InboundTx *Inbound `protobuf:"bytes,2,opt,name=inbound_tx,json=inboundTx,proto3" json:"inbound_tx,omitempty"` // Full inbound tx data + PcTx []*PCTx `protobuf:"bytes,3,rep,name=pc_tx,json=pcTx,proto3" json:"pc_tx,omitempty"` // Execution details on Push Chain + OutboundTx []*OutboundTx `protobuf:"bytes,4,rep,name=outbound_tx,json=outboundTx,proto3" json:"outbound_tx,omitempty"` // Outbound tx triggered by this tx } func (x *UniversalTx) Reset() { @@ -11381,13 +11792,6 @@ func (x *UniversalTx) GetOutboundTx() []*OutboundTx { return nil } -func (x *UniversalTx) GetUniversalStatus() UniversalTxStatus { - if x != nil { - return x.UniversalStatus - } - return UniversalTxStatus_UNIVERSAL_TX_STATUS_UNSPECIFIED -} - type InboundLegacy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -11724,7 +12128,7 @@ var file_uexecutor_v1_types_proto_rawDesc = []byte{ 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x3a, 0x1c, 0x98, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x0f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x63, 0x5f, 0x74, 0x78, 0x22, - 0xb1, 0x01, 0x0a, 0x13, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4f, 0x62, 0x73, 0x65, + 0xd3, 0x01, 0x0a, 0x13, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, @@ -11732,194 +12136,204 @@ var file_uexecutor_v1_types_proto_rawDesc = []byte{ 0x69, 0x67, 0x68, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x3a, 0x27, 0xe8, 0xa0, 0x1f, 0x01, - 0x8a, 0xe7, 0xb0, 0x2a, 0x1e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x6f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x0f, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6e, 0x67, 0x50, 0x63, 0x54, 0x78, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, - 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x24, 0xe8, 0xa0, - 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x1b, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x63, 0x5f, - 0x74, 0x78, 0x22, 0xaf, 0x05, 0x0a, 0x0a, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x78, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x1c, - 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x20, 0x0a, 0x0c, 0x67, 0x61, + 0x73, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x67, 0x61, 0x73, 0x46, 0x65, 0x65, 0x55, 0x73, 0x65, 0x64, 0x3a, 0x27, 0xe8, 0xa0, + 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x1e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x0f, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6e, 0x67, 0x50, 0x63, 0x54, 0x78, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, + 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x24, + 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x1b, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, + 0x63, 0x5f, 0x74, 0x78, 0x22, 0xf2, 0x06, 0x0a, 0x0a, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x54, 0x78, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x11, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x63, 0x32, 0x30, 0x5f, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x70, 0x72, 0x63, 0x32, 0x30, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, + 0x2d, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x14, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, + 0x0a, 0x05, 0x70, 0x63, 0x5f, 0x74, 0x78, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x69, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x63, 0x54, 0x78, 0x52, 0x04, 0x70, 0x63, + 0x54, 0x78, 0x12, 0x42, 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x74, + 0x78, 0x18, 0x0b, 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, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3d, 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x14, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x51, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x5f, + 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x13, 0x70, 0x63, 0x5f, 0x72, + 0x65, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x43, 0x54, 0x78, 0x52, 0x11, 0x70, 0x63, 0x52, 0x65, 0x76, + 0x65, 0x72, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, + 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x67, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x61, 0x73, + 0x5f, 0x66, 0x65, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x61, 0x73, 0x46, + 0x65, 0x65, 0x12, 0x42, 0x0a, 0x13, 0x70, 0x63, 0x5f, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x5f, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x43, 0x54, 0x78, 0x52, 0x11, 0x70, 0x63, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, + 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x61, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x3a, + 0x08, 0x98, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x01, 0x22, 0xdc, 0x01, 0x0a, 0x0b, 0x55, 0x6e, + 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x0a, 0x69, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 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, 0x09, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, + 0x27, 0x0a, 0x05, 0x70, 0x63, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x43, + 0x54, 0x78, 0x52, 0x04, 0x70, 0x63, 0x54, 0x78, 0x12, 0x39, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x54, 0x78, 0x3a, 0x23, 0x98, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, + 0x2a, 0x16, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x75, 0x6e, 0x69, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x22, 0xab, 0x03, 0x0a, 0x0d, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x17, 0x0a, + 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, + 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x11, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x63, 0x32, 0x30, 0x5f, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x70, 0x72, 0x63, 0x32, 0x30, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2d, 0x0a, - 0x07, 0x74, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x78, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x05, - 0x70, 0x63, 0x5f, 0x74, 0x78, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x63, 0x54, 0x78, 0x52, 0x04, 0x70, 0x63, 0x54, 0x78, - 0x12, 0x42, 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x74, 0x78, 0x18, - 0x0b, 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, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x3d, 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, - 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x51, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x6e, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x12, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x13, 0x70, 0x63, 0x5f, 0x72, 0x65, 0x76, - 0x65, 0x72, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x43, 0x54, 0x78, 0x52, 0x11, 0x70, 0x63, 0x52, 0x65, 0x76, 0x65, 0x72, - 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x08, 0x98, 0xa0, 0x1f, 0x00, - 0xe8, 0xa0, 0x1f, 0x01, 0x22, 0xa8, 0x02, 0x0a, 0x0b, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x6c, 0x54, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, - 0x74, 0x78, 0x18, 0x02, 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, - 0x09, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x63, - 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x43, 0x54, 0x78, 0x52, 0x04, 0x70, - 0x63, 0x54, 0x78, 0x12, 0x39, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, - 0x74, 0x78, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x54, 0x78, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x4a, - 0x0a, 0x10, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x6c, 0x54, 0x78, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0f, 0x75, 0x6e, 0x69, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3a, 0x23, 0x98, 0xa0, 0x1f, 0x00, - 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x16, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x22, - 0xab, 0x03, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, - 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, - 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, - 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3a, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x78, 0x54, 0x79, 0x70, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x52, 0x06, 0x74, 0x78, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x11, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, - 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, - 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, - 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x12, 0x2b, 0x0a, 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x65, 0x72, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x3a, 0x1e, 0x98, - 0xa0, 0x1f, 0x01, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x11, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0xd1, 0x01, - 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x4c, 0x65, 0x67, 0x61, - 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, - 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x3a, 0x22, 0x98, - 0xa0, 0x1f, 0x01, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x15, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, - 0x78, 0x22, 0xaa, 0x02, 0x0a, 0x11, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, - 0x78, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x3a, 0x0a, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x52, 0x09, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x54, 0x78, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x63, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x43, 0x54, 0x78, 0x52, 0x04, 0x70, 0x63, 0x54, 0x78, 0x12, 0x3f, 0x0a, 0x0b, - 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x4c, 0x65, 0x67, 0x61, 0x63, - 0x79, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x4a, 0x0a, - 0x10, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x41, + 0x64, 0x64, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x3a, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x54, 0x79, 0x70, 0x65, 0x4c, 0x65, + 0x67, 0x61, 0x63, 0x79, 0x52, 0x06, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x11, + 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, - 0x54, 0x78, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3a, 0x23, 0x98, 0xa0, 0x1f, 0x01, 0xe8, - 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x16, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, - 0x72, 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x2a, 0x47, - 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x65, 0x72, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x75, 0x6e, - 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x01, 0x2a, 0x83, 0x02, 0x0a, 0x11, 0x55, 0x6e, 0x69, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, - 0x1f, 0x55, 0x4e, 0x49, 0x56, 0x45, 0x52, 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x58, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x55, - 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x45, 0x4e, 0x44, 0x49, - 0x4e, 0x47, 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, - 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x43, 0x5f, 0x45, 0x58, 0x45, - 0x43, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12, - 0x16, 0x0a, 0x12, 0x50, 0x43, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x46, - 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x43, 0x5f, 0x50, 0x45, - 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x52, 0x45, 0x56, 0x45, 0x52, 0x54, 0x10, 0x05, 0x12, 0x14, - 0x0a, 0x10, 0x4f, 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, - 0x4e, 0x47, 0x10, 0x06, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, - 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, - 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x08, 0x12, - 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x09, 0x2a, 0x42, 0x0a, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, - 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x4f, 0x42, 0x53, 0x45, 0x52, 0x56, 0x45, - 0x44, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x56, 0x45, 0x52, 0x54, 0x45, 0x44, 0x10, - 0x03, 0x2a, 0x7d, 0x0a, 0x06, 0x54, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x54, 0x58, 0x10, 0x00, 0x12, - 0x07, 0x0a, 0x03, 0x47, 0x41, 0x53, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x41, 0x53, 0x5f, - 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x02, 0x12, 0x09, 0x0a, - 0x05, 0x46, 0x55, 0x4e, 0x44, 0x53, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x55, 0x4e, 0x44, - 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x04, 0x12, - 0x0b, 0x0a, 0x07, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, - 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x56, 0x45, 0x52, 0x54, 0x10, 0x06, - 0x2a, 0xb4, 0x01, 0x0a, 0x13, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x54, 0x79, - 0x70, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x42, 0x4f, - 0x55, 0x4e, 0x44, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x54, 0x58, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x49, - 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x47, 0x41, - 0x53, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x4c, - 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x46, 0x55, 0x4e, 0x44, 0x53, 0x10, 0x02, 0x12, 0x24, 0x0a, - 0x20, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, - 0x46, 0x55, 0x4e, 0x44, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, - 0x44, 0x10, 0x03, 0x12, 0x22, 0x0a, 0x1e, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x4c, - 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x47, 0x41, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x41, - 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x04, 0x42, 0xb2, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, - 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x79, - 0x70, 0x65, 0x73, 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, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x3a, 0x1e, 0x98, 0xa0, 0x1f, 0x01, 0xe8, 0xa0, 0x1f, 0x01, + 0x8a, 0xe7, 0xb0, 0x2a, 0x11, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x69, + 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0xd1, 0x01, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x54, 0x78, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, + 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x3a, 0x22, 0x98, 0xa0, 0x1f, 0x01, 0xe8, 0xa0, 0x1f, 0x01, + 0x8a, 0xe7, 0xb0, 0x2a, 0x15, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x6f, + 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0xaa, 0x02, 0x0a, 0x11, 0x55, + 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x12, 0x3a, 0x0a, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, + 0x79, 0x52, 0x09, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x27, 0x0a, 0x05, + 0x70, 0x63, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x75, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x43, 0x54, 0x78, 0x52, + 0x04, 0x70, 0x63, 0x54, 0x78, 0x12, 0x3f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x54, 0x78, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x4a, 0x0a, 0x10, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1f, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x0f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x3a, 0x23, 0x98, 0xa0, 0x1f, 0x01, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, + 0x16, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x2a, 0x47, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, + 0x54, 0x78, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x01, + 0x2a, 0x83, 0x02, 0x0a, 0x11, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x55, 0x4e, 0x49, 0x56, 0x45, 0x52, + 0x53, 0x41, 0x4c, 0x5f, 0x54, 0x58, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x49, + 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, + 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x49, 0x4e, 0x42, 0x4f, + 0x55, 0x4e, 0x44, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, + 0x17, 0x0a, 0x13, 0x50, 0x43, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x53, + 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x43, 0x5f, 0x45, + 0x58, 0x45, 0x43, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, + 0x12, 0x15, 0x0a, 0x11, 0x50, 0x43, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x52, + 0x45, 0x56, 0x45, 0x52, 0x54, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x55, 0x54, 0x42, 0x4f, + 0x55, 0x4e, 0x44, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x14, 0x0a, + 0x10, 0x4f, 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, + 0x53, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, + 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x08, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, 0x43, + 0x45, 0x4c, 0x45, 0x44, 0x10, 0x09, 0x2a, 0x42, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0c, + 0x0a, 0x08, 0x4f, 0x42, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, + 0x52, 0x45, 0x56, 0x45, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x8f, 0x01, 0x0a, 0x06, 0x54, + 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x5f, 0x54, 0x58, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x41, 0x53, + 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x41, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x41, + 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x55, 0x4e, 0x44, 0x53, + 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x55, 0x4e, 0x44, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x5f, + 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x41, 0x59, + 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, + 0x44, 0x5f, 0x52, 0x45, 0x56, 0x45, 0x52, 0x54, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x52, 0x45, + 0x53, 0x43, 0x55, 0x45, 0x5f, 0x46, 0x55, 0x4e, 0x44, 0x53, 0x10, 0x07, 0x2a, 0xb4, 0x01, 0x0a, + 0x13, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x54, 0x79, 0x70, 0x65, 0x4c, 0x65, + 0x67, 0x61, 0x63, 0x79, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, + 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x5f, 0x54, 0x58, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x42, 0x4f, 0x55, + 0x4e, 0x44, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x47, 0x41, 0x53, 0x10, 0x01, 0x12, + 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, + 0x59, 0x5f, 0x46, 0x55, 0x4e, 0x44, 0x53, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x42, + 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x46, 0x55, 0x4e, 0x44, + 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x03, 0x12, + 0x22, 0x0a, 0x1e, 0x49, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, + 0x59, 0x5f, 0x47, 0x41, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, + 0x44, 0x10, 0x04, 0x42, 0xb2, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x73, 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 ( @@ -11968,10 +12382,10 @@ var file_uexecutor_v1_types_proto_depIdxs = []int32{ 2, // 7: uexecutor.v1.OutboundTx.outbound_status:type_name -> uexecutor.v1.Status 9, // 8: uexecutor.v1.OutboundTx.revert_instructions:type_name -> uexecutor.v1.RevertInstructions 11, // 9: uexecutor.v1.OutboundTx.pc_revert_execution:type_name -> uexecutor.v1.PCTx - 10, // 10: uexecutor.v1.UniversalTx.inbound_tx:type_name -> uexecutor.v1.Inbound - 11, // 11: uexecutor.v1.UniversalTx.pc_tx:type_name -> uexecutor.v1.PCTx - 14, // 12: uexecutor.v1.UniversalTx.outbound_tx:type_name -> uexecutor.v1.OutboundTx - 1, // 13: uexecutor.v1.UniversalTx.universal_status:type_name -> uexecutor.v1.UniversalTxStatus + 11, // 10: uexecutor.v1.OutboundTx.pc_refund_execution:type_name -> uexecutor.v1.PCTx + 10, // 11: uexecutor.v1.UniversalTx.inbound_tx:type_name -> uexecutor.v1.Inbound + 11, // 12: uexecutor.v1.UniversalTx.pc_tx:type_name -> uexecutor.v1.PCTx + 14, // 13: uexecutor.v1.UniversalTx.outbound_tx:type_name -> uexecutor.v1.OutboundTx 4, // 14: uexecutor.v1.InboundLegacy.tx_type:type_name -> uexecutor.v1.InboundTxTypeLegacy 6, // 15: uexecutor.v1.InboundLegacy.universal_payload:type_name -> uexecutor.v1.UniversalPayload 16, // 16: uexecutor.v1.UniversalTxLegacy.inbound_tx:type_name -> uexecutor.v1.InboundLegacy diff --git a/app/upgrades.go b/app/upgrades.go index 4ad2a032..d2242870 100755 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -6,6 +6,7 @@ import ( upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/pushchain/push-chain-node/app/upgrades" + chainmeta "github.com/pushchain/push-chain-node/app/upgrades/chain-meta" ethhashfix "github.com/pushchain/push-chain-node/app/upgrades/eth-hash-fix" evmrpcfix "github.com/pushchain/push-chain-node/app/upgrades/evm-rpc-fix" feeabs "github.com/pushchain/push-chain-node/app/upgrades/fee-abs" @@ -14,10 +15,10 @@ import ( outbound "github.com/pushchain/push-chain-node/app/upgrades/outbound" pcmintcap "github.com/pushchain/push-chain-node/app/upgrades/pc-mint-cap" proxybytecodefix "github.com/pushchain/push-chain-node/app/upgrades/proxy-bytecode-fix" - supplyslash "github.com/pushchain/push-chain-node/app/upgrades/supply-slash" - supplyburn "github.com/pushchain/push-chain-node/app/upgrades/supply-burn" removefeeabsv1 "github.com/pushchain/push-chain-node/app/upgrades/remove-fee-abs-v1" solanafix "github.com/pushchain/push-chain-node/app/upgrades/solana-fix" + supplyburn "github.com/pushchain/push-chain-node/app/upgrades/supply-burn" + supplyslash "github.com/pushchain/push-chain-node/app/upgrades/supply-slash" tsscore "github.com/pushchain/push-chain-node/app/upgrades/tss-core" tsscoreevmparamsfix "github.com/pushchain/push-chain-node/app/upgrades/tss-core-evm-params-fix" tsscorefix "github.com/pushchain/push-chain-node/app/upgrades/tss-core-fix" @@ -43,6 +44,7 @@ var Upgrades = []upgrades.Upgrade{ proxybytecodefix.NewUpgrade(), supplyslash.NewUpgrade(), supplyburn.NewUpgrade(), + chainmeta.NewUpgrade(), } // RegisterUpgradeHandlers registers the chain upgrade handlers diff --git a/app/upgrades/chain-meta/upgrade.go b/app/upgrades/chain-meta/upgrade.go new file mode 100644 index 00000000..c66433f8 --- /dev/null +++ b/app/upgrades/chain-meta/upgrade.go @@ -0,0 +1,105 @@ +package chainmeta + +import ( + "context" + + storetypes "cosmossdk.io/store/types" + upgradetypes "cosmossdk.io/x/upgrade/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/pushchain/push-chain-node/app/upgrades" +) + +const UpgradeName = "chain-meta" + +// NewUpgrade constructs the upgrade definition +func NewUpgrade() upgrades.Upgrade { + return upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateUpgradeHandler, + StoreUpgrades: storetypes.StoreUpgrades{ + Added: []string{}, + Deleted: []string{}, + }, + } +} + +func CreateUpgradeHandler( + mm upgrades.ModuleManager, + configurator module.Configurator, + ak *upgrades.AppKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + logger := sdkCtx.Logger().With("upgrade", UpgradeName) + logger.Info("Starting upgrade handler") + + // ── Feature 1 ─────────────────────────────────────────────────────────── + // funds_and_payload / payload routes no longer revert the inbound when the + // UEA is not yet deployed. The call simply skips the payload execution and + // marks the tx as PC_EXECUTED_FAILED instead of reverting funds. + // No state migration required – purely behavioural. + logger.Info("Feature: funds_and_payload / payload txs no longer revert when UEA is not deployed") + + // ── Feature 2 ─────────────────────────────────────────────────────────── + // Chain inbound / outbound can now be toggled via ChainConfig.Enabled + // (IsInboundEnabled / IsOutboundEnabled). VoteInbound and + // BuildOutboundsFromReceipt both gate on these flags. + // The Enabled field is already part of ChainConfig in uregistry – no + // additional state migration is required. + logger.Info("Feature: per-chain inbound/outbound enable/disable checks are now enforced") + + // ── Feature 3 ─────────────────────────────────────────────────────────── + // New MsgVoteChainMeta message + ChainMeta store. + // uexecutor module consensus version bumped 4 → 5. + // RunMigrations below triggers MigrateGasPricesToChainMeta which seeds + // ChainMetas from existing GasPrices entries (preserving signers, prices, + // block heights and median index). + logger.Info("Feature: MsgVoteChainMeta added; migrating GasPrices → ChainMetas store (v4 → v5)") + + // ── Feature 4 ─────────────────────────────────────────────────────────── + // GAS and GAS_AND_PAYLOAD inbound routes now call the Uniswap V3 QuoterV2 + // contract to obtain an on-chain swap quote and pass minPCOut (quote × 95%) + // to CallPRC20DepositAutoSwap, replacing the previous 0-slippage call. + // No state migration required. + logger.Info("Feature: Uniswap V3 QuoterV2 used for minPCOut (5% slippage) on GAS / GAS_AND_PAYLOAD routes") + + // ── Feature 5 ─────────────────────────────────────────────────────────── + // OutboundTx proto gains gas_price (field 16) and gas_fee (field 17). + // These are populated from the decoded UniversalTxOutbound EVM event. + // OutboundCreatedEvent and the on-chain event attributes also include + // gas_price and gas_fee. Existing stored OutboundTx records default + // the new fields to "" which is safe – no migration required. + logger.Info("Feature: gas_price and gas_fee fields added to OutboundTx proto and outbound events") + + // ── Feature 6 ─────────────────────────────────────────────────────────── + // On a successful outbound observation, if gas_fee_used < gas_fee the + // excess is refunded to the sender (or fund_recipient) via + // UniversalCore.refundUnusedGas. A swap (gasToken → PC native) is + // attempted first; on failure the raw PRC20 is deposited directly. + // The result is persisted in OutboundTx.pc_refund_execution. + // No state migration required. + logger.Info("Feature: excess gas fee refund executed on successful outbound vote finalisation") + + // ── Feature 7 ─────────────────────────────────────────────────────────── + // OutboundTx proto gains gas_token (field 20) which records the PRC20 + // address of the token used to pay the relayer fee. Populated from the + // decoded UniversalTxOutbound EVM event. Existing records default to "". + // No state migration required. + logger.Info("Feature: gas_token field added to OutboundTx proto") + + // ── State migration ────────────────────────────────────────────────────── + // RunMigrations triggers uexecutor v4 → v5 which calls + // MigrateGasPricesToChainMeta via the registered migration handler. + versionMap, err := mm.RunMigrations(ctx, configurator, fromVM) + if err != nil { + logger.Error("RunMigrations failed", "error", err) + return nil, err + } + + logger.Info("Upgrade complete", "upgrade", UpgradeName) + return versionMap, nil + } +} diff --git a/go.mod b/go.mod index 5944b597..c16d9f95 100755 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ replace ( cosmossdk.io/x/upgrade => cosmossdk.io/x/upgrade v0.1.4 github.com/CosmWasm/wasmd => github.com/CosmWasm/wasmd v0.55.0 // Keep v0.55.0 github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.50.10 // Use stable v0.50.10 - github.com/cosmos/evm => github.com/pushchain/evm v0.2.1-0.20260218064719-823606aa137a + github.com/cosmos/evm => github.com/pushchain/evm v0.2.1-0.20260317061609-b8c20d3d631b github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.10.26-evmos-rc4.0.20250402013457-cf9d288f0147 github.com/spf13/viper => github.com/spf13/viper v1.17.0 github.com/strangelove-ventures/tokenfactory => github.com/strangelove-ventures/tokenfactory v0.50.7-wasmvm2 @@ -111,13 +111,16 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/go-jose/go-jose/v4 v4.1.1 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/gopacket v1.1.19 // indirect diff --git a/go.sum b/go.sum index feba7e36..dfd1543a 100755 --- a/go.sum +++ b/go.sum @@ -961,6 +961,7 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -971,6 +972,7 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -1752,8 +1754,8 @@ github.com/prysmaticlabs/gohashtree v0.0.4-beta.0.20240624100937-73632381301b h1 github.com/prysmaticlabs/gohashtree v0.0.4-beta.0.20240624100937-73632381301b/go.mod h1:HRuvtXLZ4WkaB1MItToVH2e8ZwKwZPY5/Rcby+CvvLY= github.com/prysmaticlabs/prysm/v5 v5.3.0 h1:7Lr8ndapBTZg00YE+MgujN6+yvJR6Bdfn28ZDSJ00II= github.com/prysmaticlabs/prysm/v5 v5.3.0/go.mod h1:r1KhlduqDMIGZ1GhR5pjZ2Ko8Q89noTDYTRoPKwf1+c= -github.com/pushchain/evm v0.2.1-0.20260218064719-823606aa137a h1:lrclI7NrN6aSDHTAW08W+f+OWHclxxgs5IwMzGr/5Hs= -github.com/pushchain/evm v0.2.1-0.20260218064719-823606aa137a/go.mod h1:/4D24vd1xRnUVaXzfNryxTo5Gn1c/phJG5FvpH9OvLQ= +github.com/pushchain/evm v0.2.1-0.20260317061609-b8c20d3d631b h1:qpeWGGZ5gznlTg86yXVnxTbpZzaCpwlPZS0e8qWxC0Y= +github.com/pushchain/evm v0.2.1-0.20260317061609-b8c20d3d631b/go.mod h1:/4D24vd1xRnUVaXzfNryxTo5Gn1c/phJG5FvpH9OvLQ= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= diff --git a/proto/uexecutor/v1/chain_meta.proto b/proto/uexecutor/v1/chain_meta.proto new file mode 100644 index 00000000..c086080e --- /dev/null +++ b/proto/uexecutor/v1/chain_meta.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +package uexecutor.v1; + +import "gogoproto/gogo.proto"; +import "amino/amino.proto"; + +option go_package = "github.com/pushchain/push-chain-node/x/uexecutor/types"; + +// ChainMeta stores aggregated chain metadata (gas price + block height) for a given chain +message ChainMeta { + option (amino.name) = "uexecutor/chain_meta"; + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = false; + + string observed_chain_id = 1; // chain ID of observed external chain (e.g. "eip155:1" for ethereum mainnet) + repeated string signers = 2; // Validators who submitted votes + repeated uint64 prices = 3; // Submitted gas prices + repeated uint64 chain_heights = 4; // Block heights corresponding to each price observation + repeated uint64 stored_ats = 5; // Block time (unix seconds) when each vote was last stored/updated + uint64 median_index = 6; // Index of the median price in 'prices' + uint64 last_applied_chain_height = 7; // Chain height of last successful EVM setChainMeta call +} diff --git a/proto/uexecutor/v1/query.proto b/proto/uexecutor/v1/query.proto index b231151e..b8e9eb25 100755 --- a/proto/uexecutor/v1/query.proto +++ b/proto/uexecutor/v1/query.proto @@ -4,6 +4,7 @@ package uexecutor.v1; import "google/api/annotations.proto"; import "uexecutor/v1/types.proto"; import "uexecutor/v1/gas_price.proto"; +import "uexecutor/v1/chain_meta.proto"; import "cosmos/base/query/v1beta1/pagination.proto"; option go_package = "github.com/pushchain/push-chain-node/x/uexecutor/types"; @@ -39,6 +40,16 @@ service Query { rpc AllGasPrices(QueryAllGasPricesRequest) returns (QueryAllGasPricesResponse) { option (google.api.http).get = "/uexecutor/v1/gas_prices"; } + + // 🔹 Queries chain meta for a specific chain + rpc ChainMeta(QueryChainMetaRequest) returns (QueryChainMetaResponse) { + option (google.api.http).get = "/uexecutor/v1/chain_meta/{chain_id}"; + } + + // 🔹 Queries all chain metas across chains + rpc AllChainMetas(QueryAllChainMetasRequest) returns (QueryAllChainMetasResponse) { + option (google.api.http).get = "/uexecutor/v1/chain_metas"; + } } // ========================== @@ -64,6 +75,25 @@ message QueryAllGasPricesResponse { cosmos.base.query.v1beta1.PageResponse pagination = 2; } +// Single chain meta +message QueryChainMetaRequest { + string chain_id = 1; +} + +message QueryChainMetaResponse { + ChainMeta chain_meta = 1; +} + +// All chain metas +message QueryAllChainMetasRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +message QueryAllChainMetasResponse { + repeated ChainMeta chain_metas = 1; + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + // Existing types message QueryParamsRequest {} diff --git a/proto/uexecutor/v1/tx.proto b/proto/uexecutor/v1/tx.proto index 7eb065aa..f2270e03 100755 --- a/proto/uexecutor/v1/tx.proto +++ b/proto/uexecutor/v1/tx.proto @@ -4,6 +4,7 @@ package uexecutor.v1; import "amino/amino.proto"; import "cosmos/msg/v1/msg.proto"; import "uexecutor/v1/types.proto"; +import "uexecutor/v1/chain_meta.proto"; import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; @@ -32,6 +33,9 @@ service Msg { // VoteGasPrice defines a message for universal validators to vote on the gas price rpc VoteGasPrice(MsgVoteGasPrice) returns (MsgVoteGasPriceResponse); + + // VoteChainMeta defines a message for universal validators to vote on chain metadata (gas price + block height) + rpc VoteChainMeta(MsgVoteChainMeta) returns (MsgVoteChainMetaResponse); } // MsgUpdateParams is the Msg/UpdateParams request type. @@ -139,3 +143,17 @@ message MsgVoteGasPrice { // MsgVoteGasPriceResponse defines the response for MsgVoteGasPrice message MsgVoteGasPriceResponse {} + +// MsgVoteChainMeta is broadcasted by Universal Validators to submit observed chain metadata (gas price + block height) +message MsgVoteChainMeta { + option (amino.name) = "uexecutor/MsgVoteChainMeta"; + option (cosmos.msg.v1.signer) = "signer"; + + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // Universal Validator address submitting the vote + string observed_chain_id = 2; // CAIP-2 chain ID of observed external chain (e.g. "eip155:1") + uint64 price = 3; // Observed gas price in wei + uint64 chain_height = 4; // Block height from which observation was made +} + +// MsgVoteChainMetaResponse defines the response for MsgVoteChainMeta +message MsgVoteChainMetaResponse {} diff --git a/proto/uexecutor/v1/types.proto b/proto/uexecutor/v1/types.proto index 63a552fd..e5322ef5 100644 --- a/proto/uexecutor/v1/types.proto +++ b/proto/uexecutor/v1/types.proto @@ -88,6 +88,7 @@ enum TxType { FUNDS_AND_PAYLOAD = 4; PAYLOAD = 5; INBOUND_REVERT = 6; + RESCUE_FUNDS = 7; } message RevertInstructions { @@ -137,6 +138,7 @@ message OutboundObservation { uint64 block_height = 2; // block height on external chain string tx_hash = 3; // external chain tx hash string error_msg = 4; + string gas_fee_used = 5; // actual gas fee consumed on destination chain; used to compute excess refund } message OriginatingPcTx { @@ -167,6 +169,11 @@ message OutboundTx { Status outbound_status = 13; // status of outbound tx RevertInstructions revert_instructions = 14; PCTx pc_revert_execution = 15; + string gas_price = 16; // gas price on destination chain at time of outbound + string gas_fee = 17; // gas fee paid to relayer on destination chain + PCTx pc_refund_execution = 18; // PC tx that executed the gas refund (non-nil if refund ran) + string refund_swap_error = 19; // non-empty if swap-refund failed and we fell back to no-swap + string gas_token = 20; // gas token PRC20 address used to pay relayer fee } message UniversalTx { @@ -178,7 +185,6 @@ message UniversalTx { Inbound inbound_tx = 2; // Full inbound tx data repeated PCTx pc_tx = 3; // Execution details on Push Chain repeated OutboundTx outbound_tx = 4; // Outbound tx triggered by this tx - UniversalTxStatus universal_status = 5; // Current status } // LEGACY TYPES diff --git a/test/integration/uexecutor/chain_enabled_test.go b/test/integration/uexecutor/chain_enabled_test.go index 7d650590..ee65cecf 100644 --- a/test/integration/uexecutor/chain_enabled_test.go +++ b/test/integration/uexecutor/chain_enabled_test.go @@ -182,7 +182,8 @@ func TestVoteInbound_ChainEnabled(t *testing.T) { utx, found, err := testApp.UexecutorKeeper.GetUniversalTx(ctx, uexecutortypes.GetInboundUniversalTxKey(*inbound)) require.NoError(t, err) require.True(t, found, "UTX should be created when inbound is enabled and quorum reached") - require.Equal(t, uexecutortypes.UniversalTxStatus_PC_EXECUTED_SUCCESS, utx.UniversalStatus) + require.NotEmpty(t, utx.PcTx, "PC tx should be recorded after inbound execution") + require.Equal(t, "SUCCESS", utx.PcTx[len(utx.PcTx)-1].Status) }) } diff --git a/test/integration/uexecutor/gas_fee_refund_test.go b/test/integration/uexecutor/gas_fee_refund_test.go new file mode 100644 index 00000000..18aa82db --- /dev/null +++ b/test/integration/uexecutor/gas_fee_refund_test.go @@ -0,0 +1,240 @@ +package integrationtest + +import ( + "fmt" + "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" +) + +func TestGasFeeRefund(t *testing.T) { + + t.Run("vote with empty gasFeeUsed is always rejected", func(t *testing.T) { + // gas_fee_used is mandatory for both success and failure votes. + for _, success := range []bool{true, false} { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + valAddr, err := sdk.ValAddressFromBech32(coreVals[0].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + + revertReason := "" + if !success { + revertReason = "execution failed" + } + + err = utils.ExecVoteOutbound( + t, ctx, app, vals[0], coreAcc, utxId, outbound, + success, revertReason, "", // empty gas_fee_used → must be rejected + ) + require.Error(t, err) + require.Contains(t, err.Error(), "observed_tx.gas_fee_used is required") + } + }) + + t.Run("no refund when gasFeeUsed equals gasFee", func(t *testing.T) { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + // The mock contract sets GasFee = 111; reporting all 111 consumed → no excess + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteOutbound( + t, + ctx, + app, + vals[i], + coreAcc, + utxId, + outbound, + true, + "", + outbound.GasFee, // gasFeeUsed == gasFee → no excess + ) + require.NoError(t, err) + } + + utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + ob := utx.OutboundTx[0] + require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) + require.Nil(t, ob.PcRefundExecution, "no refund expected when gasFeeUsed equals gasFee") + require.Empty(t, ob.RefundSwapError) + }) + + t.Run("no refund when gasFeeUsed exceeds gasFee", func(t *testing.T) { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + // gasFeeUsed > gasFee (e.g. 999 > 111) → gasFee - gasFeeUsed <= 0 → no refund + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteOutbound( + t, + ctx, + app, + vals[i], + coreAcc, + utxId, + outbound, + true, + "", + "999", // gasFeeUsed > gasFee(111) → no excess + ) + require.NoError(t, err) + } + + utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + ob := utx.OutboundTx[0] + require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) + require.Nil(t, ob.PcRefundExecution, "no refund expected when gasFeeUsed > gasFee") + require.Empty(t, ob.RefundSwapError) + }) + + t.Run("refund execution recorded when gasFee exceeds gasFeeUsed", func(t *testing.T) { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + // gasFee = 111 (set by mock), gasFeeUsed = 50 → 61 excess to refund + gasFeeUsed := "50" + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteOutbound( + t, + ctx, + app, + vals[i], + coreAcc, + utxId, + outbound, + true, + "", + gasFeeUsed, + ) + require.NoError(t, err) + } + + utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + fmt.Println(utx) + + ob := utx.OutboundTx[0] + require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) + require.True(t, ob.ObservedTx.Success) + + // Refund was attempted → PcRefundExecution must be set + require.NotNil(t, ob.PcRefundExecution, + "PcRefundExecution must be set when excess gas fee exists") + + // In the test environment the UniversalCore stub may or may not implement + // refundUnusedGas. The important invariant is that the execution record + // is stored regardless of EVM success/failure. + require.NotEmpty(t, ob.PcRefundExecution.Status, + "PcRefundExecution.Status must be set") + }) + + t.Run("swap fallback reason stored when swap refund fails", func(t *testing.T) { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + // gasFee = 111, gasFeeUsed = 1 → large excess triggers refund attempt. + // The test handler's defaultFeeTier for an unknown gas token will either + // return 0 or fail, causing the swap path to fall back. In either case + // RefundSwapError must be non-empty (swap was not clean) or PcRefundExecution + // must exist. + gasFeeUsed := "1" + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteOutbound( + t, + ctx, + app, + vals[i], + coreAcc, + utxId, + outbound, + true, + "", + gasFeeUsed, + ) + require.NoError(t, err) + } + + utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + ob := utx.OutboundTx[0] + require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) + + // Refund execution must always be recorded when excess gas exists + require.NotNil(t, ob.PcRefundExecution) + + // The outbound status stays OBSERVED (refund failure does not revert the outbound) + require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) + }) + + t.Run("failed outbound performs both revert and gas refund", func(t *testing.T) { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + // gasFee = 111 (mock), gasFeeUsed = 50 → 61 excess to refund. + // Both the bridged funds revert AND the excess gas refund must happen. + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteOutbound( + t, + ctx, + app, + vals[i], + coreAcc, + utxId, + outbound, + false, + "execution failed", + "50", // gasFeeUsed=50 < gasFee=111 → 61 excess + ) + require.NoError(t, err) + } + + utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + ob := utx.OutboundTx[0] + require.Equal(t, uexecutortypes.Status_REVERTED, ob.OutboundStatus) + + // Revert: bridged funds minted back + require.NotNil(t, ob.PcRevertExecution) + require.Equal(t, "SUCCESS", ob.PcRevertExecution.Status) + + // Gas refund: excess gas must also be returned on failure + require.NotNil(t, ob.PcRefundExecution, + "excess gas must be refunded even when outbound failed") + require.NotEmpty(t, ob.PcRefundExecution.Status) + }) +} diff --git a/test/integration/uexecutor/inbound_cea_payload_test.go b/test/integration/uexecutor/inbound_cea_payload_test.go index 3a41dc0f..df46b5d6 100644 --- a/test/integration/uexecutor/inbound_cea_payload_test.go +++ b/test/integration/uexecutor/inbound_cea_payload_test.go @@ -246,15 +246,15 @@ func TestInboundCEAFundsAndPayload(t *testing.T) { "UEA should have received the deposited PRC20 amount") }) - t.Run("fails with PC_EXECUTED_FAILED when isCEA is true and recipient is not a deployed UEA", func(t *testing.T) { + t.Run("deposit and executeUniversalTx called for EOA recipient when isCEA is true", func(t *testing.T) { chainApp, ctx, vals, _, coreVals, _ := setupInboundCEAPayloadTest(t, 4) usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr - // Use a valid hex address that has never been deployed as a UEA - nonUEARecipient := utils.GetDefaultAddresses().TargetAddr2 + // Use a valid hex address that is a plain EOA (no code deployed) + eoaRecipient := utils.GetDefaultAddresses().TargetAddr2 validUP := &uexecutortypes.UniversalPayload{ - To: nonUEARecipient, + To: eoaRecipient, Value: "1000000", Data: "0xa9059cbb000000000000000000000000527f3692f5c53cfa83f7689885995606f93b616400000000000000000000000000000000000000000000000000000000000f4240", GasLimit: "21000000", @@ -265,11 +265,11 @@ func TestInboundCEAFundsAndPayload(t *testing.T) { VType: uexecutortypes.VerificationType(1), } - inboundWithNonUEA := &uexecutortypes.Inbound{ + inboundWithEOA := &uexecutortypes.Inbound{ SourceChain: "eip155:11155111", TxHash: "0xcea02", Sender: utils.GetDefaultAddresses().DefaultTestAddr, - Recipient: nonUEARecipient, + Recipient: eoaRecipient, Amount: "1000000", AssetAddr: usdcAddress.String(), LogIndex: "1", @@ -287,32 +287,32 @@ func TestInboundCEAFundsAndPayload(t *testing.T) { require.NoError(t, err) coreValAcc := sdk.AccAddress(valAddr).String() - err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inboundWithNonUEA) + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inboundWithEOA) require.NoError(t, err) } - utxKey := uexecutortypes.GetInboundUniversalTxKey(*inboundWithNonUEA) + utxKey := uexecutortypes.GetInboundUniversalTxKey(*inboundWithEOA) utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) require.NoError(t, err) require.True(t, found, "universal tx should exist after quorum is reached") - require.NotEmpty(t, utx.PcTx) - // Deposit step should fail with the expected error - lastPcTx := utx.PcTx[len(utx.PcTx)-1] - require.Contains(t, lastPcTx.ErrorMsg, "recipient is not a valid UEA") - require.Equal(t, "FAILED", lastPcTx.Status) - require.Equal(t, uexecutortypes.UniversalTxStatus_PC_EXECUTED_FAILED, utx.UniversalStatus) + // Expect 2 PCTxs: deposit + executeUniversalTx (calling to EOA succeeds in EVM) + require.GreaterOrEqual(t, len(utx.PcTx), 2, "should have deposit and executeUniversalTx PCTxs") + require.Equal(t, "SUCCESS", utx.PcTx[0].Status, "deposit should succeed for EOA recipient") + // isCEA path never creates a revert outbound + require.Empty(t, utx.OutboundTx, "no revert outbound should be created for isCEA inbounds") }) - t.Run("creates revert outbound when isCEA is true and recipient is not a UEA", func(t *testing.T) { + t.Run("no revert outbound created when isCEA is true regardless of recipient type", func(t *testing.T) { chainApp, ctx, vals, _, coreVals, _ := setupInboundCEAPayloadTest(t, 4) usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr testAddress := utils.GetDefaultAddresses().DefaultTestAddr - nonUEARecipient := utils.GetDefaultAddresses().TargetAddr2 + // Plain EOA recipient — deposit + executeUniversalTx called, no INBOUND_REVERT + eoaRecipient := utils.GetDefaultAddresses().TargetAddr2 validUP := &uexecutortypes.UniversalPayload{ - To: nonUEARecipient, + To: eoaRecipient, Value: "1000000", Data: "0xa9059cbb000000000000000000000000527f3692f5c53cfa83f7689885995606f93b616400000000000000000000000000000000000000000000000000000000000f4240", GasLimit: "21000000", @@ -323,11 +323,11 @@ func TestInboundCEAFundsAndPayload(t *testing.T) { VType: uexecutortypes.VerificationType(1), } - inboundWithNonUEA := &uexecutortypes.Inbound{ + inboundWithEOA := &uexecutortypes.Inbound{ SourceChain: "eip155:11155111", TxHash: "0xcea03", Sender: testAddress, - Recipient: nonUEARecipient, + Recipient: eoaRecipient, Amount: "1000000", AssetAddr: usdcAddress.String(), LogIndex: "1", @@ -345,28 +345,20 @@ func TestInboundCEAFundsAndPayload(t *testing.T) { require.NoError(t, err) coreValAcc := sdk.AccAddress(valAddr).String() - err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inboundWithNonUEA) + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inboundWithEOA) require.NoError(t, err) } - utxKey := uexecutortypes.GetInboundUniversalTxKey(*inboundWithNonUEA) + utxKey := uexecutortypes.GetInboundUniversalTxKey(*inboundWithEOA) utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) require.NoError(t, err) require.True(t, found) - // A revert outbound should be created for the failed CEA inbound - foundRevert := false + // isCEA path never creates a revert outbound for _, ob := range utx.OutboundTx { - if ob.TxType == uexecutortypes.TxType_INBOUND_REVERT { - foundRevert = true - require.Equal(t, inboundWithNonUEA.SourceChain, ob.DestinationChain) - require.Equal(t, inboundWithNonUEA.Amount, ob.Amount) - require.Equal(t, inboundWithNonUEA.AssetAddr, ob.ExternalAssetAddr) - require.Equal(t, inboundWithNonUEA.RevertInstructions.FundRecipient, ob.Recipient) - require.Equal(t, uexecutortypes.Status_PENDING, ob.OutboundStatus) - } + require.NotEqual(t, uexecutortypes.TxType_INBOUND_REVERT, ob.TxType, + "no INBOUND_REVERT outbound should be created for isCEA inbounds") } - require.True(t, foundRevert, "expected INBOUND_REVERT outbound to be created when recipient is not a UEA") }) t.Run("vote fails at ValidateBasic when isCEA is true but recipient has no 0x prefix", func(t *testing.T) { diff --git a/test/integration/uexecutor/inbound_cea_smart_contract_test.go b/test/integration/uexecutor/inbound_cea_smart_contract_test.go new file mode 100644 index 00000000..5e563175 --- /dev/null +++ b/test/integration/uexecutor/inbound_cea_smart_contract_test.go @@ -0,0 +1,348 @@ +package integrationtest + +import ( + "fmt" + "math/big" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + authz "github.com/cosmos/cosmos-sdk/x/authz" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common" + + "github.com/pushchain/push-chain-node/app" + utils "github.com/pushchain/push-chain-node/test/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" + "github.com/stretchr/testify/require" +) + +// mockRecipientContractAddr is a fixed address for the minimal mock recipient contract. +// This is a deterministic address used only in tests. +var mockRecipientContractAddr = common.HexToAddress("0x00000000000000000000000000000000000000C3") + +// deployMockRecipientContract deploys a minimal smart contract that accepts any call +// without reverting. Bytecode "00" = STOP opcode — succeeds with empty output. +func deployMockRecipientContract(t *testing.T, chainApp *app.ChainApp, ctx sdk.Context) common.Address { + t.Helper() + // "00" = STOP opcode: accepts any function call, returns success with empty data + return utils.DeployContract(t, chainApp, ctx, mockRecipientContractAddr, "00") +} + +// setupInboundCEASmartContractTest mirrors setupInboundCEAPayloadTest but deploys +// a mock smart-contract recipient instead of a UEA. +func setupInboundCEASmartContractTest( + t *testing.T, + numVals int, +) (*app.ChainApp, sdk.Context, []string, *uexecutortypes.Inbound, []stakingtypes.Validator, common.Address) { + t.Helper() + + chainApp, ctx, _, validators := utils.SetAppWithMultipleValidators(t, numVals) + + chainConfigTest := uregistrytypes.ChainConfig{ + Chain: "eip155:11155111", + VmType: uregistrytypes.VmType_EVM, + PublicRpcUrl: "https://sepolia.drpc.org", + GatewayAddress: "0x28E0F09bE2321c1420Dc60Ee146aACbD68B335Fe", + BlockConfirmation: &uregistrytypes.BlockConfirmation{ + FastInbound: 5, + StandardInbound: 12, + }, + GatewayMethods: []*uregistrytypes.GatewayMethods{{ + Name: "addFunds", + Identifier: "", + EventIdentifier: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", + ConfirmationType: 5, + }}, + Enabled: &uregistrytypes.ChainEnabled{ + IsInboundEnabled: true, + IsOutboundEnabled: true, + }, + } + + prc20Address := utils.GetDefaultAddresses().PRC20USDCAddr + testAddress := utils.GetDefaultAddresses().DefaultTestAddr + usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr + + tokenConfigTest := uregistrytypes.TokenConfig{ + Chain: "eip155:11155111", + Address: usdcAddress.String(), + Name: "USD Coin", + Symbol: "USDC", + Decimals: 6, + Enabled: true, + LiquidityCap: "1000000000000000000000000", + TokenType: 1, + NativeRepresentation: &uregistrytypes.NativeRepresentation{ + Denom: "", + ContractAddress: prc20Address.String(), + }, + } + + chainApp.UregistryKeeper.AddChainConfig(ctx, &chainConfigTest) + chainApp.UregistryKeeper.AddTokenConfig(ctx, &tokenConfigTest) + + universalVals := make([]string, len(validators)) + for i, val := range validators { + coreValAddr := val.OperatorAddress + universalValAddr := sdk.AccAddress([]byte( + fmt.Sprintf("universal-validator-%d", i), + )).String() + + network := uvalidatortypes.NetworkInfo{PeerId: fmt.Sprintf("temp%d", i+1), MultiAddrs: []string{"temp"}} + + err := chainApp.UvalidatorKeeper.AddUniversalValidator(ctx, coreValAddr, network) + require.NoError(t, err) + + universalVals[i] = universalValAddr + } + + for i, val := range validators { + accAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress) + require.NoError(t, err) + + coreValAddr := sdk.AccAddress(accAddr) + uniValAddr := sdk.MustAccAddressFromBech32(universalVals[i]) + + msgType := sdk.MsgTypeURL(&uexecutortypes.MsgVoteInbound{}) + auth := authz.NewGenericAuthorization(msgType) + exp := ctx.BlockTime().Add(time.Hour) + + err = chainApp.AuthzKeeper.SaveGrant(ctx, uniValAddr, coreValAddr, auth, &exp) + require.NoError(t, err) + } + + // Deploy the mock smart contract recipient + contractAddr := deployMockRecipientContract(t, chainApp, ctx) + + validUP := &uexecutortypes.UniversalPayload{ + To: contractAddr.String(), + Value: "1000000", + Data: "0xdeadbeef", + GasLimit: "21000000", + MaxFeePerGas: "1000000000", + MaxPriorityFeePerGas: "200000000", + Nonce: "1", + Deadline: "9999999999", + VType: uexecutortypes.VerificationType(1), + } + + inbound := &uexecutortypes.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xsc01", + Sender: testAddress, + Recipient: contractAddr.String(), + Amount: "1000000", + AssetAddr: usdcAddress.String(), + LogIndex: "1", + TxType: uexecutortypes.TxType_FUNDS_AND_PAYLOAD, + UniversalPayload: validUP, + VerificationData: "", + IsCEA: true, + RevertInstructions: &uexecutortypes.RevertInstructions{ + FundRecipient: testAddress, + }, + } + + return chainApp, ctx, universalVals, inbound, validators, contractAddr +} + +func TestInboundCEASmartContractRecipient(t *testing.T) { + t.Run("quorum reached executes deposit and calls executeUniversalTx on smart contract", func(t *testing.T) { + chainApp, ctx, vals, inbound, coreVals, _ := setupInboundCEASmartContractTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inbound) + require.NoError(t, err) + } + + isPending, err := chainApp.UexecutorKeeper.IsPendingInbound(ctx, *inbound) + require.NoError(t, err) + require.False(t, isPending, "inbound should be executed after quorum") + + utxKey := uexecutortypes.GetInboundUniversalTxKey(*inbound) + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) + require.NoError(t, err) + require.True(t, found) + + // Expect 2 PCTxs: deposit + executeUniversalTx + require.GreaterOrEqual(t, len(utx.PcTx), 2, "should have at least 2 PCTxs: deposit and executeUniversalTx") + }) + + t.Run("deposit PCTx succeeds for smart contract recipient", func(t *testing.T) { + chainApp, ctx, vals, inbound, coreVals, _ := setupInboundCEASmartContractTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inbound) + require.NoError(t, err) + } + + utxKey := uexecutortypes.GetInboundUniversalTxKey(*inbound) + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) + require.NoError(t, err) + require.True(t, found) + require.GreaterOrEqual(t, len(utx.PcTx), 1) + + depositPcTx := utx.PcTx[0] + require.Equal(t, "SUCCESS", depositPcTx.Status, "deposit PCTx should succeed for smart contract recipient") + require.Empty(t, depositPcTx.ErrorMsg) + }) + + t.Run("PRC20 balance is deposited into smart contract", func(t *testing.T) { + prc20ABI, err := uexecutortypes.ParsePRC20ABI() + require.NoError(t, err) + prc20Address := utils.GetDefaultAddresses().PRC20USDCAddr + + chainApp, ctx, vals, inbound, coreVals, contractAddr := setupInboundCEASmartContractTest(t, 4) + ueModuleAccAddress, _ := chainApp.UexecutorKeeper.GetUeModuleAddress(ctx) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inbound) + require.NoError(t, err) + } + + res, err := chainApp.EVMKeeper.CallEVM( + ctx, + prc20ABI, + ueModuleAccAddress, + prc20Address, + false, + "balanceOf", + contractAddr, + ) + require.NoError(t, err) + + balances, err := prc20ABI.Unpack("balanceOf", res.Ret) + require.NoError(t, err) + require.Len(t, balances, 1) + + expectedAmount := new(big.Int) + expectedAmount.SetString(inbound.Amount, 10) + require.Equal(t, 0, balances[0].(*big.Int).Cmp(expectedAmount), + "smart contract should have received the deposited PRC20 amount") + }) + + t.Run("no INBOUND_REVERT outbound created for smart contract path", func(t *testing.T) { + chainApp, ctx, vals, inbound, coreVals, _ := setupInboundCEASmartContractTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inbound) + require.NoError(t, err) + } + + utxKey := uexecutortypes.GetInboundUniversalTxKey(*inbound) + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) + require.NoError(t, err) + require.True(t, found) + + for _, ob := range utx.OutboundTx { + require.NotEqual(t, uexecutortypes.TxType_INBOUND_REVERT, ob.TxType, + "no INBOUND_REVERT outbound should be created for the smart contract path") + } + }) + + t.Run("executeUniversalTx PCTx is recorded for smart contract recipient", func(t *testing.T) { + chainApp, ctx, vals, inbound, coreVals, _ := setupInboundCEASmartContractTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inbound) + require.NoError(t, err) + } + + utxKey := uexecutortypes.GetInboundUniversalTxKey(*inbound) + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) + require.NoError(t, err) + require.True(t, found) + + // Second PCTx is the executeUniversalTx call + require.GreaterOrEqual(t, len(utx.PcTx), 2) + callPcTx := utx.PcTx[1] + require.Equal(t, "SUCCESS", callPcTx.Status, "executeUniversalTx PCTx should succeed") + require.Empty(t, callPcTx.ErrorMsg) + }) + + t.Run("EOA recipient receives deposit and executeUniversalTx call", func(t *testing.T) { + chainApp, ctx, vals, _, coreVals, _ := setupInboundCEASmartContractTest(t, 4) + usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr + testAddress := utils.GetDefaultAddresses().DefaultTestAddr + + // TargetAddr2 is a plain EOA — deposit lands there and executeUniversalTx is called + // (calling to an EOA in EVM succeeds with empty output) + eoaRecipient := utils.GetDefaultAddresses().TargetAddr2 + + validUP := &uexecutortypes.UniversalPayload{ + To: eoaRecipient, + Value: "1000000", + Data: "0xdeadbeef", + GasLimit: "21000000", + MaxFeePerGas: "1000000000", + MaxPriorityFeePerGas: "200000000", + Nonce: "1", + Deadline: "9999999999", + VType: uexecutortypes.VerificationType(1), + } + + eoaInbound := &uexecutortypes.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xsc02", + Sender: testAddress, + Recipient: eoaRecipient, + Amount: "1000000", + AssetAddr: usdcAddress.String(), + LogIndex: "1", + TxType: uexecutortypes.TxType_FUNDS_AND_PAYLOAD, + UniversalPayload: validUP, + VerificationData: "", + IsCEA: true, + RevertInstructions: &uexecutortypes.RevertInstructions{ + FundRecipient: testAddress, + }, + } + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, eoaInbound) + require.NoError(t, err) + } + + utxKey := uexecutortypes.GetInboundUniversalTxKey(*eoaInbound) + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) + require.NoError(t, err) + require.True(t, found) + + // Expect 2 PCTxs: deposit + executeUniversalTx + require.GreaterOrEqual(t, len(utx.PcTx), 2, "should have deposit and executeUniversalTx PCTxs") + require.Equal(t, "SUCCESS", utx.PcTx[0].Status, "deposit should succeed for EOA recipient") + + // isCEA path never creates a revert outbound + for _, ob := range utx.OutboundTx { + require.NotEqual(t, uexecutortypes.TxType_INBOUND_REVERT, ob.TxType, + "EOA isCEA inbound should NOT create INBOUND_REVERT") + } + }) +} diff --git a/test/integration/uexecutor/query_chain_meta_test.go b/test/integration/uexecutor/query_chain_meta_test.go new file mode 100644 index 00000000..188302ad --- /dev/null +++ b/test/integration/uexecutor/query_chain_meta_test.go @@ -0,0 +1,152 @@ +package integrationtest + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + utils "github.com/pushchain/push-chain-node/test/utils" + uexecutorkeeper "github.com/pushchain/push-chain-node/x/uexecutor/keeper" + uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// TestQueryChainMeta tests the ChainMeta and AllChainMetas query handlers +func TestQueryChainMeta(t *testing.T) { + chainId := "eip155:11155111" + chainId2 := "eip155:1" + + t.Run("returns not found when chain meta absent", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + _, err := querier.ChainMeta(ctx, &uexecutortypes.QueryChainMetaRequest{ChainId: chainId}) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + }) + + t.Run("returns error for empty chain_id", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + _, err := querier.ChainMeta(ctx, &uexecutortypes.QueryChainMetaRequest{ChainId: ""}) + require.Error(t, err) + require.Equal(t, codes.InvalidArgument, status.Code(err)) + }) + + t.Run("returns chain meta after vote", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 2) + + coreVal0, _ := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + coreVal1, _ := sdk.ValAddressFromBech32(vals[1].OperatorAddress) + + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], sdk.AccAddress(coreVal0).String(), chainId, 100_000_000_000, 12345)) + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[1], sdk.AccAddress(coreVal1).String(), chainId, 200_000_000_000, 12346)) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + resp, err := querier.ChainMeta(ctx, &uexecutortypes.QueryChainMetaRequest{ChainId: chainId}) + require.NoError(t, err) + require.NotNil(t, resp.ChainMeta) + require.Equal(t, chainId, resp.ChainMeta.ObservedChainId) + require.Len(t, resp.ChainMeta.Prices, 2) + require.Len(t, resp.ChainMeta.ChainHeights, 2) + require.Len(t, resp.ChainMeta.ChainHeights, 2) + }) + + t.Run("all chain metas returns empty when nothing stored", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + resp, err := querier.AllChainMetas(ctx, &uexecutortypes.QueryAllChainMetasRequest{}) + require.NoError(t, err) + require.Empty(t, resp.ChainMetas) + }) + + t.Run("all chain metas returns all entries", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + require.NoError(t, testApp.UexecutorKeeper.SetChainMeta(ctx, chainId, uexecutortypes.ChainMeta{ + ObservedChainId: chainId, + Signers: []string{"cosmos1abc"}, + Prices: []uint64{100}, + ChainHeights: []uint64{1}, + MedianIndex: 0, + })) + require.NoError(t, testApp.UexecutorKeeper.SetChainMeta(ctx, chainId2, uexecutortypes.ChainMeta{ + ObservedChainId: chainId2, + Signers: []string{"cosmos1def"}, + Prices: []uint64{200}, + ChainHeights: []uint64{2}, + MedianIndex: 0, + })) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + resp, err := querier.AllChainMetas(ctx, &uexecutortypes.QueryAllChainMetasRequest{}) + require.NoError(t, err) + require.Len(t, resp.ChainMetas, 2) + }) +} + +// TestQueryGasPriceFromChainMeta ensures the legacy GasPrice query routes through ChainMetas +func TestQueryGasPriceFromChainMeta(t *testing.T) { + chainId := "eip155:11155111" + + t.Run("gas price query reads from chain metas", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + require.NoError(t, testApp.UexecutorKeeper.SetChainMeta(ctx, chainId, uexecutortypes.ChainMeta{ + ObservedChainId: chainId, + Signers: []string{"cosmos1abc", "cosmos1def"}, + Prices: []uint64{100_000_000_000, 200_000_000_000}, + ChainHeights: []uint64{12345, 12346}, + MedianIndex: 1, + })) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + resp, err := querier.GasPrice(ctx, &uexecutortypes.QueryGasPriceRequest{ChainId: chainId}) + require.NoError(t, err) + require.NotNil(t, resp.GasPrice) + require.Equal(t, chainId, resp.GasPrice.ObservedChainId) + require.Equal(t, []uint64{100_000_000_000, 200_000_000_000}, resp.GasPrice.Prices) + // ChainHeights should be mapped back to BlockNums for backward compat + require.Equal(t, []uint64{12345, 12346}, resp.GasPrice.BlockNums) + require.Equal(t, uint64(1), resp.GasPrice.MedianIndex) + }) + + t.Run("gas price query falls back to legacy store when chain meta absent", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + require.NoError(t, testApp.UexecutorKeeper.SetGasPrice(ctx, chainId, uexecutortypes.GasPrice{ + ObservedChainId: chainId, + Signers: []string{"cosmos1abc"}, + Prices: []uint64{50_000_000_000}, + BlockNums: []uint64{9999}, + MedianIndex: 0, + })) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + resp, err := querier.GasPrice(ctx, &uexecutortypes.QueryGasPriceRequest{ChainId: chainId}) + require.NoError(t, err) + require.Equal(t, uint64(50_000_000_000), resp.GasPrice.Prices[0]) + require.Equal(t, uint64(9999), resp.GasPrice.BlockNums[0]) + }) + + t.Run("all gas prices sources from chain metas", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + require.NoError(t, testApp.UexecutorKeeper.SetChainMeta(ctx, chainId, uexecutortypes.ChainMeta{ + ObservedChainId: chainId, + Prices: []uint64{100}, + ChainHeights: []uint64{1}, + MedianIndex: 0, + })) + + querier := uexecutorkeeper.NewQuerier(testApp.UexecutorKeeper) + resp, err := querier.AllGasPrices(ctx, &uexecutortypes.QueryAllGasPricesRequest{}) + require.NoError(t, err) + require.Len(t, resp.GasPrices, 1) + require.Equal(t, chainId, resp.GasPrices[0].ObservedChainId) + }) +} diff --git a/test/integration/uexecutor/query_v2_test.go b/test/integration/uexecutor/query_v2_test.go index 0000e44e..61092554 100644 --- a/test/integration/uexecutor/query_v2_test.go +++ b/test/integration/uexecutor/query_v2_test.go @@ -170,7 +170,7 @@ func TestGetUniversalTxV2(t *testing.T) { "v1 OutboundTx should be the legacy single-entry type") }) - t.Run("v2 universal_status matches underlying store", func(t *testing.T) { + t.Run("v2 does not expose universal_status, v1 computes and returns it", func(t *testing.T) { chainApp, ctx, vals, inbound, coreVals := setupInboundBridgeTest(t, 4) for i := 0; i < 3; i++ { @@ -183,22 +183,27 @@ func TestGetUniversalTxV2(t *testing.T) { utxKey := uexecutortypes.GetInboundUniversalTxKey(*inbound) - // Fetch directly from keeper store - directUtx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxKey) + // v2: UniversalTx has no universal_status field — confirmed at compile time by proto removal + qV2 := uexecutorkeeper.QuerierV2{Keeper: chainApp.UexecutorKeeper} + respV2, err := qV2.GetUniversalTx(sdk.WrapSDKContext(ctx), &typesv2.QueryGetUniversalTxRequest{ + Id: utxKey, + }) require.NoError(t, err) - require.True(t, found) + require.NotNil(t, respV2.UniversalTx) + require.NotEmpty(t, respV2.UniversalTx.PcTx, "v2 should have pc_tx after execution") - // Fetch via v2 query - q := uexecutorkeeper.QuerierV2{Keeper: chainApp.UexecutorKeeper} - resp, err := q.GetUniversalTx(sdk.WrapSDKContext(ctx), &typesv2.QueryGetUniversalTxRequest{ + // v1: UniversalTxLegacy still carries universal_status computed on-the-fly + qV1 := uexecutorkeeper.Querier{Keeper: chainApp.UexecutorKeeper} + respV1, err := qV1.GetUniversalTx(sdk.WrapSDKContext(ctx), &uexecutortypes.QueryGetUniversalTxRequest{ Id: utxKey, }) require.NoError(t, err) - - require.Equal(t, directUtx.UniversalStatus, resp.UniversalTx.UniversalStatus, - "v2 universal_status should match what is stored in the keeper") - require.Equal(t, directUtx.Id, resp.UniversalTx.Id, - "v2 ID should match what is stored in the keeper") + require.NotNil(t, respV1.UniversalTx) + require.Equal(t, + uexecutortypes.UniversalTxStatus_PC_EXECUTED_SUCCESS, + respV1.UniversalTx.UniversalStatus, + "v1 should return computed universal_status from pc_tx state", + ) }) t.Run("v2 TxType preserves native enum, v1 maps to legacy enum", func(t *testing.T) { diff --git a/test/integration/uexecutor/rescue_funds_test.go b/test/integration/uexecutor/rescue_funds_test.go new file mode 100644 index 00000000..378d88b2 --- /dev/null +++ b/test/integration/uexecutor/rescue_funds_test.go @@ -0,0 +1,600 @@ +package integrationtest + +import ( + "encoding/hex" + "fmt" + "math/big" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + authz "github.com/cosmos/cosmos-sdk/x/authz" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/app" + utils "github.com/pushchain/push-chain-node/test/utils" + uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// buildRescueFundsLog constructs a synthetic evmtypes.Log that looks exactly like a +// RescueFundsOnSourceChain event emitted by UniversalGatewayPC. This lets integration +// tests drive AttachRescueOutboundFromReceipt without a real on-chain call. +// +// Event: RescueFundsOnSourceChain(bytes32 indexed universalTxId, address indexed prc20, +// +// string chainNamespace, address indexed sender, uint8 txType, +// uint256 gasFee, uint256 gasPrice, uint256 gasLimit) +func buildRescueFundsLog( + t *testing.T, + utxId string, // UTX key (64-char hex, no 0x prefix) + prc20Addr common.Address, + senderAddr common.Address, + chainNamespace string, + gasFee, gasPrice, gasLimit *big.Int, +) *evmtypes.Log { + t.Helper() + + stringType, _ := abi.NewType("string", "", nil) + uint8Type, _ := abi.NewType("uint8", "", nil) + uint256Type, _ := abi.NewType("uint256", "", nil) + + args := abi.Arguments{ + {Type: stringType}, // chainNamespace + {Type: uint8Type}, // txType (RESCUE_FUNDS = 4) + {Type: uint256Type}, // gasFee + {Type: uint256Type}, // gasPrice + {Type: uint256Type}, // gasLimit + } + data, err := args.Pack(chainNamespace, uint8(4), gasFee, gasPrice, gasLimit) + require.NoError(t, err) + + // UTX ID is stored as a bytes32 topic: "0x" + the 64-char hex UTX key. + utxIdTopic := "0x" + utxId + + gwPCAddr := utils.GetDefaultAddresses().UniversalGatewayPCAddr + + return &evmtypes.Log{ + Address: gwPCAddr.Hex(), + Topics: []string{ + uexecutortypes.RescueFundsOnSourceChainEventSig, + utxIdTopic, + common.BytesToHash(prc20Addr.Bytes()).Hex(), // indexed prc20 + common.BytesToHash(senderAddr.Bytes()).Hex(), // indexed sender + }, + Data: data, + Removed: false, + } +} + +// setupRescueFundsTest creates a CEA inbound whose deposit will fail (asset address has +// no registered token config), drives it to quorum, and returns the UTX key of the failed UTX. +// The returned UTX has at least one FAILED PCTx and is ready for a rescue outbound. +func setupRescueFundsTest( + t *testing.T, + numVals int, +) ( + *app.ChainApp, + sdk.Context, + []string, // universalVals + string, // utxId of the failed CEA UTX + []stakingtypes.Validator, +) { + t.Helper() + + // Reuse the CEA environment (validators, chain/token config, authz for inbound voting). + chainApp, ctx, vals, _, coreVals, _ := setupInboundCEAPayloadTest(t, numVals) + + testAddress := utils.GetDefaultAddresses().DefaultTestAddr + recipient := utils.GetDefaultAddresses().TargetAddr2 + // Use an asset address that has no registered token config — depositPRC20 will fail. + unregisteredAsset := common.HexToAddress("0x000000000000000000000000000000000000DEAD") + + inbound := &uexecutortypes.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xrescue01", + Sender: testAddress, + Recipient: recipient, + Amount: "1000000", + AssetAddr: unregisteredAsset.String(), + LogIndex: "1", + TxType: uexecutortypes.TxType_FUNDS_AND_PAYLOAD, + UniversalPayload: &uexecutortypes.UniversalPayload{ + To: recipient, + Value: "1000000", + Data: "0x", + GasLimit: "21000000", + MaxFeePerGas: "1000000000", + MaxPriorityFeePerGas: "200000000", + Nonce: "1", + Deadline: "9999999999", + VType: uexecutortypes.VerificationType(1), + }, + IsCEA: true, + RevertInstructions: &uexecutortypes.RevertInstructions{ + FundRecipient: testAddress, + }, + } + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], coreValAcc, inbound) + require.NoError(t, err) + } + + utxId := uexecutortypes.GetInboundUniversalTxKey(*inbound) + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.True(t, found, "UTX must exist after quorum") + + require.NotEmpty(t, utx.PcTx, "setup: at least one PCTx must exist") + require.Equal(t, "FAILED", utx.PcTx[0].Status, "setup: deposit must fail for unregistered asset") + + return chainApp, ctx, vals, utxId, coreVals +} + +// makeRescueReceipt wraps a single RescueFundsOnSourceChain log into a receipt. +func makeRescueReceipt(t *testing.T, txHash string, log *evmtypes.Log) *evmtypes.MsgEthereumTxResponse { + t.Helper() + return &evmtypes.MsgEthereumTxResponse{ + Hash: txHash, + Logs: []*evmtypes.Log{log}, + } +} + +func TestRescueFunds(t *testing.T) { + prc20Addr := utils.GetDefaultAddresses().PRC20USDCAddr + senderAddr := common.HexToAddress(utils.GetDefaultAddresses().DefaultTestAddr) + + t.Run("rescue outbound is attached to original UTX on valid CEA inbound with failed deposit", func(t *testing.T) { + chainApp, ctx, _, utxId, _ := setupRescueFundsTest(t, 4) + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + receipt := makeRescueReceipt(t, "0xrescuetx01", log) + pcTx := uexecutortypes.PCTx{TxHash: "0xrescuetx01", Status: "SUCCESS"} + + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, receipt, pcTx) + require.NoError(t, err) + + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.True(t, found) + + rescueObs := findRescueOutbound(utx) + require.NotNil(t, rescueObs, "RESCUE_FUNDS outbound must be attached") + require.Equal(t, uexecutortypes.Status_PENDING, rescueObs.OutboundStatus) + require.Equal(t, uexecutortypes.TxType_RESCUE_FUNDS, rescueObs.TxType) + require.Equal(t, "eip155:11155111", rescueObs.DestinationChain) + require.Equal(t, "1000000", rescueObs.Amount) + require.Equal(t, "111", rescueObs.GasFee) + + // The rescue call must be recorded as a PCTx in the UTX history. + // UTX already had the failed deposit PCTx; the rescue pcTx is appended after it. + require.Greater(t, len(utx.PcTx), 1, "rescue PCTx must be appended to UTX history") + lastPcTx := utx.PcTx[len(utx.PcTx)-1] + require.Equal(t, "0xrescuetx01", lastPcTx.TxHash) + require.Equal(t, "SUCCESS", lastPcTx.Status) + }) + + t.Run("rescue outbound recipient defaults to inbound sender when no revert instructions", func(t *testing.T) { + chainApp, ctx, _, utxId, _ := setupRescueFundsTest(t, 4) + + // Remove revert instructions from the stored UTX + err := chainApp.UexecutorKeeper.UpdateUniversalTx(ctx, utxId, func(utx *uexecutortypes.UniversalTx) error { + if utx.InboundTx != nil { + utx.InboundTx.RevertInstructions = nil + } + return nil + }) + require.NoError(t, err) + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err = chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx02", log), uexecutortypes.PCTx{TxHash: "0xrescuetx02", Status: "SUCCESS"}) + require.NoError(t, err) + + utx, _, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + rescueOb := findRescueOutbound(utx) + require.NotNil(t, rescueOb) + // Falls back to original inbound sender + require.Equal(t, utils.GetDefaultAddresses().DefaultTestAddr, rescueOb.Recipient) + }) + + t.Run("rescue is rejected for non-CEA inbound with no reverted auto-revert", func(t *testing.T) { + // Non-CEA FUNDS inbound: minting succeeds, so no INBOUND_REVERT outbound exists. + // Rescue must be rejected because the auto-revert has not been attempted and reverted. + chainApp, ctx, vals, inbound, coreVals := setupInboundBridgeTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], sdk.AccAddress(valAddr).String(), inbound) + require.NoError(t, err) + } + utxId := uexecutortypes.GetInboundUniversalTxKey(*inbound) + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx03", log), uexecutortypes.PCTx{TxHash: "0xrescuetx03", Status: "SUCCESS"}) + require.Error(t, err) + require.Contains(t, err.Error(), "no reverted inbound-revert outbound") + }) + + t.Run("rescue is rejected for non-CEA inbound when auto-revert is PENDING", func(t *testing.T) { + chainApp, ctx, vals, inbound, coreVals := setupInboundBridgeTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], sdk.AccAddress(valAddr).String(), inbound) + require.NoError(t, err) + } + utxId := uexecutortypes.GetInboundUniversalTxKey(*inbound) + + // Manually inject a PENDING INBOUND_REVERT outbound. + err := chainApp.UexecutorKeeper.UpdateUniversalTx(ctx, utxId, func(utx *uexecutortypes.UniversalTx) error { + utx.OutboundTx = append(utx.OutboundTx, &uexecutortypes.OutboundTx{ + Id: "pending-revert-id", + TxType: uexecutortypes.TxType_INBOUND_REVERT, + OutboundStatus: uexecutortypes.Status_PENDING, + }) + return nil + }) + require.NoError(t, err) + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err = chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx03b", log), uexecutortypes.PCTx{TxHash: "0xrescuetx03b", Status: "SUCCESS"}) + require.Error(t, err) + require.Contains(t, err.Error(), "no reverted inbound-revert outbound") + }) + + t.Run("rescue succeeds for non-CEA inbound with reverted auto-revert", func(t *testing.T) { + chainApp, ctx, vals, inbound, coreVals := setupInboundBridgeTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], sdk.AccAddress(valAddr).String(), inbound) + require.NoError(t, err) + } + utxId := uexecutortypes.GetInboundUniversalTxKey(*inbound) + + // Inject a REVERTED INBOUND_REVERT outbound to simulate a failed auto-revert. + err := chainApp.UexecutorKeeper.UpdateUniversalTx(ctx, utxId, func(utx *uexecutortypes.UniversalTx) error { + utx.OutboundTx = append(utx.OutboundTx, &uexecutortypes.OutboundTx{ + Id: "reverted-revert-id", + TxType: uexecutortypes.TxType_INBOUND_REVERT, + OutboundStatus: uexecutortypes.Status_REVERTED, + }) + return nil + }) + require.NoError(t, err) + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(222), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err = chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx03c", log), uexecutortypes.PCTx{TxHash: "0xrescuetx03c", Status: "SUCCESS"}) + require.NoError(t, err) + + utx, _, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + rescueOb := findRescueOutbound(utx) + require.NotNil(t, rescueOb, "RESCUE_FUNDS outbound must be attached for non-CEA with reverted auto-revert") + require.Equal(t, uexecutortypes.Status_PENDING, rescueOb.OutboundStatus) + require.Equal(t, uexecutortypes.TxType_RESCUE_FUNDS, rescueOb.TxType) + require.Equal(t, "eip155:11155111", rescueOb.DestinationChain) + require.Equal(t, "222", rescueOb.GasFee) + }) + + t.Run("rescue is rejected when deposit did not fail", func(t *testing.T) { + // CEA inbound with valid UEA recipient: deposit succeeds (first PCTx = SUCCESS). + // Even if the payload execution later fails, rescue must be rejected because + // the funds were already minted onto Push Chain by the successful deposit. + chainApp, ctx, vals, inbound, coreVals, _ := setupInboundCEAPayloadTest(t, 4) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + err = utils.ExecVoteInbound(t, ctx, chainApp, vals[i], sdk.AccAddress(valAddr).String(), inbound) + require.NoError(t, err) + } + utxId := uexecutortypes.GetInboundUniversalTxKey(*inbound) + + utx, found, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.True(t, found) + require.NotEmpty(t, utx.PcTx) + // Confirm first PCTx (deposit) succeeded — that's the invariant we rely on. + require.Equal(t, "SUCCESS", utx.PcTx[0].Status, "deposit must have succeeded for this test to be meaningful") + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err = chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx04", log), uexecutortypes.PCTx{TxHash: "0xrescuetx04", Status: "SUCCESS"}) + require.Error(t, err) + require.Contains(t, err.Error(), "deposit did not fail") + }) + + t.Run("second rescue is rejected when first is PENDING", func(t *testing.T) { + chainApp, ctx, _, utxId, _ := setupRescueFundsTest(t, 4) + + // First rescue — succeeds + log1 := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx05a", log1), uexecutortypes.PCTx{TxHash: "0xrescuetx05a", Status: "SUCCESS"}) + require.NoError(t, err) + + // Second rescue — rejected because first is PENDING + log2 := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err = chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx05b", log2), uexecutortypes.PCTx{TxHash: "0xrescuetx05b", Status: "SUCCESS"}) + require.Error(t, err) + require.Contains(t, err.Error(), "already has an active rescue outbound") + }) + + t.Run("second rescue is rejected when first is OBSERVED", func(t *testing.T) { + chainApp, ctx, vals, utxId, coreVals := setupRescueFundsTest(t, 4) + + // Grant authz for outbound voting + for i, val := range coreVals { + accAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(accAddr) + uniAcc := sdk.MustAccAddressFromBech32(vals[i]) + auth := authz.NewGenericAuthorization(sdk.MsgTypeURL(&uexecutortypes.MsgVoteOutbound{})) + exp := ctx.BlockTime().Add(time.Hour) + err = chainApp.AuthzKeeper.SaveGrant(ctx, uniAcc, coreAcc, auth, &exp) + require.NoError(t, err) + } + + // Attach first rescue outbound + log1 := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx06a", log1), uexecutortypes.PCTx{TxHash: "0xrescuetx06a", Status: "SUCCESS"}) + require.NoError(t, err) + + utx, _, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + rescueOb := findRescueOutbound(utx) + require.NotNil(t, rescueOb) + + // Vote to reach quorum with success → status becomes OBSERVED + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + err = utils.ExecVoteOutbound(t, ctx, chainApp, vals[i], coreAcc, utxId, rescueOb, true, "", rescueOb.GasFee) + require.NoError(t, err) + } + + utx, _, err = chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.Equal(t, uexecutortypes.Status_OBSERVED, findRescueOutbound(utx).OutboundStatus) + + // Second rescue rejected because first is OBSERVED + log2 := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err = chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx06b", log2), uexecutortypes.PCTx{TxHash: "0xrescuetx06b", Status: "SUCCESS"}) + require.Error(t, err) + require.Contains(t, err.Error(), "already has an active rescue outbound") + }) + + t.Run("rescue can be retried after previous rescue is REVERTED", func(t *testing.T) { + chainApp, ctx, vals, utxId, coreVals := setupRescueFundsTest(t, 4) + + // Grant authz for outbound voting + for i, val := range coreVals { + accAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(accAddr) + uniAcc := sdk.MustAccAddressFromBech32(vals[i]) + auth := authz.NewGenericAuthorization(sdk.MsgTypeURL(&uexecutortypes.MsgVoteOutbound{})) + exp := ctx.BlockTime().Add(time.Hour) + err = chainApp.AuthzKeeper.SaveGrant(ctx, uniAcc, coreAcc, auth, &exp) + require.NoError(t, err) + } + + // First rescue outbound + log1 := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx07a", log1), uexecutortypes.PCTx{TxHash: "0xrescuetx07a", Status: "SUCCESS"}) + require.NoError(t, err) + + utx, _, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + rescueOb := findRescueOutbound(utx) + require.NotNil(t, rescueOb) + + // Vote to reach quorum with FAILURE → status becomes REVERTED + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + err = utils.ExecVoteOutbound(t, ctx, chainApp, vals[i], coreAcc, utxId, rescueOb, false, "rescue failed", rescueOb.GasFee) + require.NoError(t, err) + } + + utx, _, err = chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.Equal(t, uexecutortypes.Status_REVERTED, findRescueOutbound(utx).OutboundStatus) + + // Second rescue is now allowed since the first is REVERTED + log2 := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err = chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx07b", log2), uexecutortypes.PCTx{TxHash: "0xrescuetx07b", Status: "SUCCESS"}) + require.NoError(t, err) + + utx, _, err = chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + // Two rescue outbounds exist: first REVERTED, second PENDING + var rescueObs []*uexecutortypes.OutboundTx + for _, ob := range utx.OutboundTx { + if ob != nil && ob.TxType == uexecutortypes.TxType_RESCUE_FUNDS { + rescueObs = append(rescueObs, ob) + } + } + require.Len(t, rescueObs, 2, "two rescue outbounds expected after retry") + require.Equal(t, uexecutortypes.Status_REVERTED, rescueObs[0].OutboundStatus) + require.Equal(t, uexecutortypes.Status_PENDING, rescueObs[1].OutboundStatus) + }) + + t.Run("rescue outbound finalizes to OBSERVED after quorum success votes", func(t *testing.T) { + chainApp, ctx, vals, utxId, coreVals := setupRescueFundsTest(t, 4) + + // Grant authz for outbound voting + for i, val := range coreVals { + accAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(accAddr) + uniAcc := sdk.MustAccAddressFromBech32(vals[i]) + auth := authz.NewGenericAuthorization(sdk.MsgTypeURL(&uexecutortypes.MsgVoteOutbound{})) + exp := ctx.BlockTime().Add(time.Hour) + err = chainApp.AuthzKeeper.SaveGrant(ctx, uniAcc, coreAcc, auth, &exp) + require.NoError(t, err) + } + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx08", log), uexecutortypes.PCTx{TxHash: "0xrescuetx08", Status: "SUCCESS"}) + require.NoError(t, err) + + utx, _, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + rescueOb := findRescueOutbound(utx) + require.NotNil(t, rescueOb) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + err = utils.ExecVoteOutbound(t, ctx, chainApp, vals[i], coreAcc, utxId, rescueOb, true, "", rescueOb.GasFee) + require.NoError(t, err) + } + + utx, _, err = chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + ob := findRescueOutbound(utx) + require.NotNil(t, ob) + require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) + require.NotNil(t, ob.ObservedTx) + require.True(t, ob.ObservedTx.Success) + // No PC revert expected for RESCUE_FUNDS on success + require.Nil(t, ob.PcRevertExecution) + }) + + t.Run("failed rescue outbound marks REVERTED with no PC-side revert", func(t *testing.T) { + chainApp, ctx, vals, utxId, coreVals := setupRescueFundsTest(t, 4) + + // Grant authz for outbound voting + for i, val := range coreVals { + accAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(accAddr) + uniAcc := sdk.MustAccAddressFromBech32(vals[i]) + auth := authz.NewGenericAuthorization(sdk.MsgTypeURL(&uexecutortypes.MsgVoteOutbound{})) + exp := ctx.BlockTime().Add(time.Hour) + err = chainApp.AuthzKeeper.SaveGrant(ctx, uniAcc, coreAcc, auth, &exp) + require.NoError(t, err) + } + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, makeRescueReceipt(t, "0xrescuetx09", log), uexecutortypes.PCTx{TxHash: "0xrescuetx09", Status: "SUCCESS"}) + require.NoError(t, err) + + utx, _, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + rescueOb := findRescueOutbound(utx) + require.NotNil(t, rescueOb) + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(valAddr).String() + err = utils.ExecVoteOutbound(t, ctx, chainApp, vals[i], coreAcc, utxId, rescueOb, false, "rescue tx reverted", rescueOb.GasFee) + require.NoError(t, err) + } + + utx, _, err = chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + + ob := findRescueOutbound(utx) + require.NotNil(t, ob) + require.Equal(t, uexecutortypes.Status_REVERTED, ob.OutboundStatus) + // RESCUE_FUNDS failure must NOT trigger a PC-side revert (no funds locked on PC). + require.Nil(t, ob.PcRevertExecution, "no PC revert expected for a failed rescue outbound") + }) + + t.Run("rescue outbound ID is deterministic from push chain caip, pc tx hash and log index", func(t *testing.T) { + pushChainCaip := "eip155:2240" + pcTxHash := "0xrescuetx10" + logIndex := "0" + id1 := uexecutortypes.GetRescueFundsOutboundId(pushChainCaip, pcTxHash, logIndex) + id2 := uexecutortypes.GetRescueFundsOutboundId(pushChainCaip, pcTxHash, logIndex) + require.Equal(t, id1, id2, "ID must be deterministic") + require.Len(t, id1, 64, "ID must be a 32-byte hex string") + + // Different inputs produce different IDs + id3 := uexecutortypes.GetRescueFundsOutboundId(pushChainCaip, "0xother", logIndex) + require.NotEqual(t, id1, id3) + + // Different push chain caips produce different IDs + id4 := uexecutortypes.GetRescueFundsOutboundId("eip155:9999", pcTxHash, logIndex) + require.NotEqual(t, id1, id4) + }) + + t.Run("rescue log from wrong contract address is ignored", func(t *testing.T) { + chainApp, ctx, _, utxId, _ := setupRescueFundsTest(t, 4) + + log := buildRescueFundsLog(t, utxId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + // Override address to a random contract — not UNIVERSAL_GATEWAY_PC + log.Address = "0x000000000000000000000000000000000000dead" + + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, + makeRescueReceipt(t, "0xrescuetx11", log), + uexecutortypes.PCTx{TxHash: "0xrescuetx11", Status: "SUCCESS"}) + require.NoError(t, err) // silently ignored — no rescue outbound created + + utx, _, err := chainApp.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.Nil(t, findRescueOutbound(utx), "wrong-contract log must be ignored") + }) + + t.Run("rescue with unknown universalTxId returns error", func(t *testing.T) { + chainApp, ctx, _, _, _ := setupRescueFundsTest(t, 4) + + unknownId := hex.EncodeToString(make([]byte, 32)) // 64 zero chars + log := buildRescueFundsLog(t, unknownId, prc20Addr, senderAddr, + "eip155", big.NewInt(111), big.NewInt(1_000_000_000), big.NewInt(200_000)) + + err := chainApp.UexecutorKeeper.AttachRescueOutboundFromReceipt(ctx, + makeRescueReceipt(t, "0xrescuetx12", log), + uexecutortypes.PCTx{TxHash: "0xrescuetx12", Status: "SUCCESS"}) + require.Error(t, err) + require.Contains(t, err.Error(), "not found") + }) +} + +// findRescueOutbound returns the first RESCUE_FUNDS outbound from a UTX, or nil. +func findRescueOutbound(utx uexecutortypes.UniversalTx) *uexecutortypes.OutboundTx { + for _, ob := range utx.OutboundTx { + if ob != nil && ob.TxType == uexecutortypes.TxType_RESCUE_FUNDS { + return ob + } + } + return nil +} + +// Ensure the fmt import is used. +var _ = fmt.Sprintf diff --git a/test/integration/uexecutor/vote_chain_meta_test.go b/test/integration/uexecutor/vote_chain_meta_test.go new file mode 100644 index 00000000..96cb1b02 --- /dev/null +++ b/test/integration/uexecutor/vote_chain_meta_test.go @@ -0,0 +1,353 @@ +package integrationtest + +import ( + "fmt" + "math/big" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + authz "github.com/cosmos/cosmos-sdk/x/authz" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/app" + utils "github.com/pushchain/push-chain-node/test/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" +) + +func setupVoteChainMetaTest(t *testing.T, numVals int) (*app.ChainApp, sdk.Context, []string, []stakingtypes.Validator) { + testApp, ctx, _, validators := utils.SetAppWithMultipleValidators(t, numVals) + + chainConfig := uregistrytypes.ChainConfig{ + Chain: "eip155:11155111", + VmType: uregistrytypes.VmType_EVM, + PublicRpcUrl: "https://sepolia.drpc.org", + GatewayAddress: "0x28E0F09bE2321c1420Dc60Ee146aACbD68B335Fe", + Enabled: &uregistrytypes.ChainEnabled{ + IsInboundEnabled: true, + IsOutboundEnabled: true, + }, + } + require.NoError(t, testApp.UregistryKeeper.AddChainConfig(ctx, &chainConfig)) + + universalVals := make([]string, len(validators)) + for i, val := range validators { + network := uvalidatortypes.NetworkInfo{PeerId: fmt.Sprintf("temp%d", i+1), MultiAddrs: []string{"temp"}} + require.NoError(t, testApp.UvalidatorKeeper.AddUniversalValidator(ctx, val.OperatorAddress, network)) + universalVals[i] = sdk.AccAddress([]byte(fmt.Sprintf("universal-validator-%d", i))).String() + } + + for i, val := range validators { + accAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(accAddr) + uniAcc := sdk.MustAccAddressFromBech32(universalVals[i]) + auth := authz.NewGenericAuthorization(sdk.MsgTypeURL(&uexecutortypes.MsgVoteChainMeta{})) + exp := ctx.BlockTime().Add(time.Hour) + require.NoError(t, testApp.AuthzKeeper.SaveGrant(ctx, uniAcc, coreAcc, auth, &exp)) + } + + return testApp, ctx, universalVals, validators +} + +func TestVoteChainMetaIntegration(t *testing.T) { + t.Parallel() + chainId := "eip155:11155111" + + t.Run("single validator vote stores chain meta", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 1) + + coreVal, err := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(coreVal).String() + + err = utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 100_000_000_000, 12345) + require.NoError(t, err) + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + require.Len(t, stored.Prices, 1) + require.Equal(t, uint64(100_000_000_000), stored.Prices[0]) + require.Len(t, stored.ChainHeights, 1) + require.Equal(t, uint64(12345), stored.ChainHeights[0]) + require.Len(t, stored.StoredAts, 1) + require.Equal(t, uint64(ctx.BlockTime().Unix()), stored.StoredAts[0]) + require.Equal(t, uint64(12345), stored.LastAppliedChainHeight) + }) + + t.Run("multiple validators vote and independent medians calculated", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 4) + + // Heights must be strictly increasing to pass the lastApplied check on each vote. + votes := []struct { + uniVal string + price uint64 + height uint64 + }{ + {uvals[0], 300_000_000_000, 12345}, + {uvals[1], 200_000_000_000, 12346}, + {uvals[2], 400_000_000_000, 12347}, + {uvals[3], 250_000_000_000, 12348}, + } + + for i, v := range votes { + coreVal, err := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(coreVal).String() + err = utils.ExecVoteChainMeta(t, ctx, testApp, v.uniVal, coreAcc, chainId, v.price, v.height) + require.NoError(t, err) + } + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + require.Len(t, stored.Prices, 4) + require.Len(t, stored.ChainHeights, 4) + require.Len(t, stored.StoredAts, 4) + + // Price median: sorted [200B, 250B, 300B, 400B], upper median at index 2 = 300B + medianPrice := stored.Prices[stored.MedianIndex] + require.Equal(t, uint64(300_000_000_000), medianPrice) + }) + + t.Run("update existing vote", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 1) + + coreVal, err := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(coreVal).String() + + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 100_000_000_000, 12345)) + // Update same validator's vote with a higher height + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 400_000_000_000, 12350)) + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + require.Len(t, stored.Prices, 1, "should have only one entry (updated in-place)") + require.Equal(t, uint64(400_000_000_000), stored.Prices[0]) + require.Equal(t, uint64(12350), stored.ChainHeights[0]) + }) + + t.Run("odd number of votes median", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 3) + + // Heights: 1, 2, 3 — each strictly greater than lastApplied after previous vote. + // After vote 1 (height=1): lastApplied=1. + // After vote 2 (height=2): lastApplied=2 (median of [1,2]). + // After vote 3 (height=3): median heights = [1,2,3] → upper median = 2. lastApplied=2. + heights := []uint64{1, 2, 3} + prices := []uint64{100, 300, 200} + + for i, price := range prices { + coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + coreAcc := sdk.AccAddress(coreVal).String() + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, price, heights[i])) + } + + stored, _, _ := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + median := stored.Prices[stored.MedianIndex] + // sorted prices: [100, 200, 300] → upper median at index 1 = 200 + require.Equal(t, uint64(200), median) + }) + + t.Run("vote rejected when chain height not greater than last applied", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 1) + + coreVal, err := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(coreVal).String() + + // First vote — establishes lastAppliedChainHeight=100 + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 100_000_000_000, 100)) + + // Same height → rejected + err = utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 200_000_000_000, 100) + require.Error(t, err) + require.Contains(t, err.Error(), "not greater than last applied chain height") + + // Lower height → rejected + err = utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 200_000_000_000, 99) + require.Error(t, err) + require.Contains(t, err.Error(), "not greater than last applied chain height") + + // Higher height → accepted + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 200_000_000_000, 101)) + }) + + t.Run("stale votes excluded from median", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 3) + + coreAccs := make([]string, 3) + for i := range vals { + coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + coreAccs[i] = sdk.AccAddress(coreVal).String() + } + + // All 3 validators vote at T. Heights 1, 2, 3 to pass lastApplied checks. + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAccs[0], chainId, 100, 1)) + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[1], coreAccs[1], chainId, 300, 2)) + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[2], coreAccs[2], chainId, 200, 3)) + + // After all 3 votes at T: sorted prices [100,200,300], upper median=200. lastApplied = median height = 2. + stored, _, _ := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.Equal(t, uint64(2), stored.LastAppliedChainHeight) + + // Advance block time by 301 seconds — old votes become stale. + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(301 * time.Second)) + + // val0 re-votes with price=900, height=3 (> lastApplied=2). + // Only this fresh vote contributes to the new median. + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAccs[0], chainId, 900, 3)) + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + // LastAppliedChainHeight should now be 3 (only fresh vote: height=3) + require.Equal(t, uint64(3), stored.LastAppliedChainHeight) + + // Verify the applied price via EVM contract — only val0's fresh vote (900) should have been used, + // not the stale votes (100, 300). MedianIndex on the stored entry reflects the full-slice + // median, so we must query the contract directly for the actually-applied value. + universalCoreAddr := utils.GetDefaultAddresses().HandlerAddr + ucABI, err := uexecutortypes.ParseUniversalCoreABI() + require.NoError(t, err) + caller, _ := testApp.UexecutorKeeper.GetUeModuleAddress(ctx) + res, err := testApp.EVMKeeper.CallEVM(ctx, ucABI, caller, universalCoreAddr, false, "gasPriceByChainNamespace", chainId) + require.NoError(t, err) + appliedPrice := new(big.Int).SetBytes(res.Ret) + require.Equal(t, new(big.Int).SetUint64(900), appliedPrice, "stale votes must not influence the applied median price") + }) + + t.Run("last applied chain height updated after EVM call", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 2) + + coreVal0, _ := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + coreVal1, _ := sdk.ValAddressFromBech32(vals[1].OperatorAddress) + coreAcc0 := sdk.AccAddress(coreVal0).String() + coreAcc1 := sdk.AccAddress(coreVal1).String() + + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc0, chainId, 100_000_000_000, 1000)) + // lastApplied=1000 after first vote + + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[1], coreAcc1, chainId, 200_000_000_000, 2000)) + // Median height of [1000, 2000] = upper = 2000. lastApplied=2000. + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, uint64(2000), stored.LastAppliedChainHeight) + }) +} + +func TestMigrateGasPricesToChainMeta(t *testing.T) { + chainId := "eip155:11155111" + + t.Run("migrates gas prices to chain meta with zero stored_ats", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + // Seed a GasPrice entry manually (simulating pre-upgrade state) + require.NoError(t, testApp.UexecutorKeeper.SetGasPrice(ctx, chainId, uexecutortypes.GasPrice{ + ObservedChainId: chainId, + Signers: []string{"cosmos1abc", "cosmos1def"}, + Prices: []uint64{100_000_000_000, 200_000_000_000}, + BlockNums: []uint64{12345, 12346}, + MedianIndex: 1, + })) + + // Run migration + require.NoError(t, testApp.UexecutorKeeper.MigrateGasPricesToChainMeta(ctx)) + + // Verify ChainMeta was created + cm, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + + require.Equal(t, chainId, cm.ObservedChainId) + require.Equal(t, []string{"cosmos1abc", "cosmos1def"}, cm.Signers) + require.Equal(t, []uint64{100_000_000_000, 200_000_000_000}, cm.Prices) + // block_nums from GasPrice become chain_heights in ChainMeta + require.Equal(t, []uint64{12345, 12346}, cm.ChainHeights) + require.Equal(t, uint64(1), cm.MedianIndex) + // StoredAts should be zero-filled (migrated votes are treated as stale until re-voted) + require.Equal(t, []uint64{0, 0}, cm.StoredAts) + require.Equal(t, uint64(0), cm.LastAppliedChainHeight) + }) + + t.Run("migration is idempotent: does not overwrite existing chain meta", func(t *testing.T) { + testApp, ctx, _, _ := utils.SetAppWithMultipleValidators(t, 1) + + // Pre-seed a GasPrice entry + require.NoError(t, testApp.UexecutorKeeper.SetGasPrice(ctx, chainId, uexecutortypes.GasPrice{ + ObservedChainId: chainId, + Signers: []string{"cosmos1abc"}, + Prices: []uint64{100_000_000_000}, + BlockNums: []uint64{12345}, + MedianIndex: 0, + })) + + // Pre-seed a ChainMeta entry (simulating a validator already voted post-upgrade) + require.NoError(t, testApp.UexecutorKeeper.SetChainMeta(ctx, chainId, uexecutortypes.ChainMeta{ + ObservedChainId: chainId, + Signers: []string{"cosmos1xyz"}, + Prices: []uint64{999_000_000_000}, + ChainHeights: []uint64{99999}, + StoredAts: []uint64{0}, + MedianIndex: 0, + })) + + // Run migration — should skip because ChainMeta already exists + require.NoError(t, testApp.UexecutorKeeper.MigrateGasPricesToChainMeta(ctx)) + + // Verify the existing entry was NOT overwritten + cm, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, []string{"cosmos1xyz"}, cm.Signers, "existing chain meta should not be overwritten") + require.Equal(t, uint64(999_000_000_000), cm.Prices[0]) + }) +} + +// TestVoteChainMetaContractState verifies that after voting, the UniversalCore contract's +// on-chain storage reflects the correct gas price and chain height. +// The contract records block.timestamp as the observed-at value (no longer passed by the caller). +func TestVoteChainMetaContractState(t *testing.T) { + chainId := "eip155:11155111" + const ( + price = uint64(100_000_000_000) + height = uint64(12345) + ) + + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 1) + + coreVal, err := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(coreVal).String() + + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, price, height)) + + // Read from the UniversalCore contract using the public mapping getters + universalCoreAddr := utils.GetDefaultAddresses().HandlerAddr + ucABI, err := uexecutortypes.ParseUniversalCoreABI() + require.NoError(t, err) + + caller, _ := testApp.UexecutorKeeper.GetUeModuleAddress(ctx) + + t.Run("gasPriceByChainNamespace matches voted price", func(t *testing.T) { + res, err := testApp.EVMKeeper.CallEVM(ctx, ucABI, caller, universalCoreAddr, false, "gasPriceByChainNamespace", chainId) + require.NoError(t, err) + got := new(big.Int).SetBytes(res.Ret) + require.Equal(t, new(big.Int).SetUint64(price), got) + }) + + t.Run("chainHeightByChainNamespace matches voted height", func(t *testing.T) { + res, err := testApp.EVMKeeper.CallEVM(ctx, ucABI, caller, universalCoreAddr, false, "chainHeightByChainNamespace", chainId) + require.NoError(t, err) + got := new(big.Int).SetBytes(res.Ret) + require.Equal(t, new(big.Int).SetUint64(height), got) + }) +} diff --git a/test/integration/uexecutor/vote_outbound_test.go b/test/integration/uexecutor/vote_outbound_test.go index 55312e7c..9c5e31cc 100644 --- a/test/integration/uexecutor/vote_outbound_test.go +++ b/test/integration/uexecutor/vote_outbound_test.go @@ -94,6 +94,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + outbound.GasFee, ) require.NoError(t, err) @@ -125,6 +126,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + outbound.GasFee, ) require.NoError(t, err) } @@ -155,6 +157,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + outbound.GasFee, ) require.NoError(t, err) @@ -168,6 +171,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + outbound.GasFee, ) require.Error(t, err) require.Contains(t, err.Error(), "already voted") @@ -192,6 +196,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + outbound.GasFee, ) require.NoError(t, err) } @@ -210,6 +215,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + outbound.GasFee, ) require.Error(t, err) require.Contains(t, err.Error(), "already finalized") @@ -234,6 +240,7 @@ func TestOutboundVoting(t *testing.T) { outbound, false, "execution reverted", // revert reason + outbound.GasFee, // gas_fee_used required; use full fee → no excess refund ) require.NoError(t, err) } @@ -274,6 +281,7 @@ func TestOutboundVoting(t *testing.T) { outbound, false, "failed", + outbound.GasFee, // gas_fee_used required; use full fee → no excess refund ) require.NoError(t, err) } @@ -312,6 +320,7 @@ func TestOutboundVoting(t *testing.T) { &prefixedOutbound, true, "", + outbound.GasFee, ) require.NoError(t, err) } @@ -342,6 +351,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + outbound.GasFee, ) require.Error(t, err) require.Contains(t, err.Error(), "not found") @@ -367,6 +377,7 @@ func TestOutboundVoting(t *testing.T) { &badOutbound, true, "", + outbound.GasFee, ) require.Error(t, err) require.Contains(t, err.Error(), "not found") diff --git a/test/utils/bytecode.go b/test/utils/bytecode.go index 7e8177be..664df26f 100644 --- a/test/utils/bytecode.go +++ b/test/utils/bytecode.go @@ -6,11 +6,11 @@ const UEA_SVM_BYTECODE = "6080604052348015600e575f80fd5b5060015f55611cf780610020 const UEA_PROXY_BYTECODE = "608060405260043610610028575f3560e01c806323efa7ec14610032578063aaf10f4214610051575b6100306100a8565b005b34801561003d575f80fd5b5061003061004c366004610368565b6100ba565b34801561005c575f80fd5b507f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5460405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100b86100b36102cc565b61034a565b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156101045750825b90505f8267ffffffffffffffff1660011480156101205750303b155b90508115801561012e575080155b15610165576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156101c65784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b5f6101ef7f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5490565b905073ffffffffffffffffffffffffffffffffffffffff81161561023f576040517fae962d4e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b867f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d555083156102c45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f806102f67f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610345576040517fae962d4e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b365f80375f80365f845af43d5f803e808015610364573d5ff35b3d5ffd5b5f60208284031215610378575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461039b575f80fd5b939250505056fea2646970667358221220c4b8f9457567bdcd08b95faef7df86de4e9daead65e2db22018126d9eb77d85864736f6c634300081a0033" -const HANDLER_CONTRACT_BYTECODE = "6080604052600436106102ae575f3560e01c80638456cb5911610165578063c6f1b7e7116100c6578063dcc16b5c1161007c578063f220e73e11610062578063f220e73e14610924578063f8c8765e14610971578063fb46e99d14610990575f80fd5b8063dcc16b5c146108d2578063ec87621c146108f1575f80fd5b8063d17c872c116100ac578063d17c872c14610875578063d547741f14610894578063db9a0daf146108b3575f80fd5b8063c6f1b7e71461080b578063c98018971461083e575f80fd5b8063a861469f1161011b578063b8efe33411610101578063b8efe33414610794578063be0580c0146107c0578063c344869f146107df575f80fd5b8063a861469f14610722578063ad14d38514610766575f80fd5b806391d148541161014b57806391d14854146106805780639be7fdb2146106f0578063a217fddf1461070f575f80fd5b80638456cb591461064d578063870152b714610661575f80fd5b80634eb7d1a11161020f5780636d4008a8116101c557806378a88127116101ab57806378a88127146105b55780637efbce04146105d457806380f5db8c14610621575f80fd5b80636d4008a81461056b578063780ad82714610596575f80fd5b80635c975abb116101f55780635c975abb146104f75780636341c64d1461052d57806364f10e501461054c575f80fd5b80634eb7d1a11461049757806357724c41146104d8575f80fd5b80632f2ff15d116102645780633f4ba83a1161024a5780633f4ba83a146103f157806346c72fdd146104055780634b1d2eeb14610456575f80fd5b80632f2ff15d146103b357806336568abe146103d2575f80fd5b80630ac6eb77116102945780630ac6eb771461030e5780631a4e49d41461032d578063248a9ca314610366575f80fd5b806301ffc9a7146102b95780630379eae8146102ed575f80fd5b366102b557005b5f80fd5b3480156102c4575f80fd5b506102d86102d3366004612be8565b6109a5565b60405190151581526020015b60405180910390f35b3480156102f8575f80fd5b5061030c610307366004612d23565b610a3d565b005b348015610319575f80fd5b5061030c610328366004612d93565b610a9d565b348015610338575f80fd5b50610358610347366004612dca565b5f6020819052908152604090205481565b6040519081526020016102e4565b348015610371575f80fd5b50610358610380366004612dca565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b3480156103be575f80fd5b5061030c6103cd366004612de1565b610b8a565b3480156103dd575f80fd5b5061030c6103ec366004612de1565b610bd3565b3480156103fc575f80fd5b5061030c610c31565b348015610410575f80fd5b50600a546104319073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102e4565b348015610461575f80fd5b50610431610470366004612dca565b60016020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156104a2575f80fd5b506104316104b1366004612dca565b60026020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e3575f80fd5b5061030c6104f2366004612e04565b610ca2565b348015610502575f80fd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff166102d8565b348015610538575f80fd5b5061030c610547366004612e2e565b610df7565b348015610557575f80fd5b5061030c610566366004612e49565b610f25565b348015610576575f80fd5b50610358610585366004612e2e565b60056020525f908152604090205481565b3480156105a1575f80fd5b5061030c6105b0366004612e9f565b6110ef565b3480156105c0575f80fd5b5061030c6105cf366004612e49565b611a28565b3480156105df575f80fd5b506104316105ee366004612efe565b8051602081830181018051600d8252928201919093012091525473ffffffffffffffffffffffffffffffffffffffff1681565b34801561062c575f80fd5b506007546104319073ffffffffffffffffffffffffffffffffffffffff1681565b348015610658575f80fd5b5061030c611a8f565b34801561066c575f80fd5b5061035861067b366004612f30565b611afe565b34801561068b575f80fd5b506102d861069a366004612de1565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156106fb575f80fd5b5061030c61070a366004612f7c565b611bf9565b34801561071a575f80fd5b506103585f81565b34801561072d575f80fd5b5061075261073c366004612e2e565b60046020525f908152604090205462ffffff1681565b60405162ffffff90911681526020016102e4565b348015610771575f80fd5b506102d8610780366004612e2e565b60036020525f908152604090205460ff1681565b34801561079f575f80fd5b506008546104319073ffffffffffffffffffffffffffffffffffffffff1681565b3480156107cb575f80fd5b5061030c6107da366004612fc0565b611d12565b3480156107ea575f80fd5b506009546104319073ffffffffffffffffffffffffffffffffffffffff1681565b348015610816575f80fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b348015610849575f80fd5b50610358610858366004612efe565b8051602081830181018051600b8252928201919093012091525481565b348015610880575f80fd5b5061030c61088f366004612ffd565b611ea7565b34801561089f575f80fd5b5061030c6108ae366004612de1565b612048565b3480156108be575f80fd5b5061030c6108cd366004612dca565b61208b565b3480156108dd575f80fd5b5061030c6108ec366004613030565b612127565b3480156108fc575f80fd5b506103587f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b34801561092f575f80fd5b5061043161093e366004612efe565b8051602081830181018051600c8252928201919093012091525473ffffffffffffffffffffffffffffffffffffffff1681565b34801561097c575f80fd5b5061030c61098b36600461308c565b6123c3565b34801561099b575f80fd5b5061035860065481565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610a3757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b80600b83604051610a4e9190613107565b9081526020016040518091039020819055507f6a59d469e3757d6e139cdf95b12740f585d553afac49b90bdbe278502a4427188282604051610a9192919061316b565b60405180910390a15050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610b04576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f42cc79f957a9535dc49c660eec62747fb540bef0dd29cd7f6c0a810816af4cff9101610a91565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610bc3816125b0565b610bcd83836125bd565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610c22576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c2c82826126e2565b505050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610c98576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca06127be565b565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610d09576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610d56576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388811115610d92576040517fc31c0b6e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526005602052604090819020839055517fe3e43e0700c35d0879972f000dc93907848b11360702f11ebbe14479866f806090610deb9084815260200190565b60405180910390a25050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610e5e576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610eab576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fc2d9f94b2a169da07b0305c4fcdf5e7d988c6e4793af0796516c96727a90b70e906020015b60405180910390a150565b610f2d612855565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610f9c575073ffffffffffffffffffffffffffffffffffffffff811630145b15610fd3576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611020576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f03611059576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152602482018490528416906347e7ef24906044016020604051808303815f875af11580156110cb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bcd919061318c565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461115e576040517f53e5172300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611166612855565b61116e6128b1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806111dd575073ffffffffffffffffffffffffffffffffffffffff841630145b15611214576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616611261576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f0361129a576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff86165f9081526003602052604090205460ff166112f8576040517f4e38f95a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8262ffffff165f036113695773ffffffffffffffffffffffffffffffffffffffff86165f9081526004602052604081205462ffffff169350839003611369576040517f3733548a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f0361138b5760065461137e90603c6131d4565b61138890426131eb565b90505b804211156113c5576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600754600a545f9173ffffffffffffffffffffffffffffffffffffffff90811691631698ee8291908116908a161061141557600a5473ffffffffffffffffffffffffffffffffffffffff16611417565b885b600a5473ffffffffffffffffffffffffffffffffffffffff908116908b1610611440578961145a565b600a5473ffffffffffffffffffffffffffffffffffffffff165b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff87166044820152606401602060405180830381865afa1580156114d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f791906131fe565b905073ffffffffffffffffffffffffffffffffffffffff8116611546576040517f76ecffc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825f0361158557600a545f9061157590899073ffffffffffffffffffffffffffffffffffffffff16878a611afe565b90506115818189612932565b9350505b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081523060048201526024810187905273ffffffffffffffffffffffffffffffffffffffff8816906347e7ef24906044016020604051808303815f875af11580156115f5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611619919061318c565b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018890529088169063095ea7b3906044016020604051808303815f875af1158015611690573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b4919061318c565b50604080516101008101825273ffffffffffffffffffffffffffffffffffffffff808a168252600a548116602083015262ffffff8716828401523060608301526080820185905260a0820189905260c082018690525f60e0830181905260085493517f414bf3890000000000000000000000000000000000000000000000000000000081529293909291169063414bf38990611754908590600401613219565b6020604051808303815f875af1158015611770573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061179491906132d7565b9050848110156117d0576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d906024015f604051808303815f87803b158015611839575f80fd5b505af115801561184b573d5f803e3d5ffd5b505050505f8773ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f81146118a5576040519150601f19603f3d011682016040523d82523d5f602084013e6118aa565b606091505b50509050806118e5576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201525f6024820152908b169063095ea7b3906044016020604051808303815f875af115801561195a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197e919061318c565b50600a546040805173ffffffffffffffffffffffffffffffffffffffff8d81168252602082018d9052928316818301526060810185905262ffffff8a166080820152918a1660a0830152517ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e29181900360c00190a150505050611a2060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050505050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610f25576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16611af6576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca06129c2565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff86811682528581166020830190815282840185815262ffffff878116606086019081525f6080870181815260095498517fc6a5026a0000000000000000000000000000000000000000000000000000000081528851881660048201529551871660248701529351604486015290519091166064840152905183166084830152938492169063c6a5026a9060a4016080604051808303815f875af1158015611bc6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bea91906132ee565b50919998505050505050505050565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08611c23816125b0565b73ffffffffffffffffffffffffffffffffffffffff8216611c70576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600c84604051611c819190613107565b908152604051908190036020018120805473ffffffffffffffffffffffffffffffffffffffff939093167fffffffffffffffffffffffff0000000000000000000000000000000000000000909316929092179091557f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94990611d05908590859061333d565b60405180910390a1505050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16611d79576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83161580611db0575073ffffffffffffffffffffffffffffffffffffffff8216155b80611dcf575073ffffffffffffffffffffffffffffffffffffffff8116155b15611e06576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316811790935560088054868316908416811790915560098054928616929093168217909255604080519384526020840192909252908201527f95d3bff4dd1ae411fd49ebc9fcc62f464b6b60cd9b4eacd860da89045c8d4c8290606001611d05565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16611f0e576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611f5b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8062ffffff166101f414158015611f7957508062ffffff16610bb814155b8015611f8c57508062ffffff1661271014155b15611fc3576040517f3733548a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000001662ffffff861690811790915591519182527f5734dc08ec8c21bd34e0f102d90ea2d1a9dbdcf23e787dc8744d2d0dd227fc739101610deb565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154612081816125b0565b610bcd83836126e2565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff166120f2576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60068190556040518181527f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b90602001610f1a565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08612151816125b0565b73ffffffffffffffffffffffffffffffffffffffff831661219e576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600754600a545f9173ffffffffffffffffffffffffffffffffffffffff90811691631698ee82918781169116106121d557856121ef565b600a5473ffffffffffffffffffffffffffffffffffffffff165b600a5473ffffffffffffffffffffffffffffffffffffffff80891691161061222f57600a5473ffffffffffffffffffffffffffffffffffffffff16612231565b865b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff86166044820152606401602060405180830381865afa1580156122aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122ce91906131fe565b905073ffffffffffffffffffffffffffffffffffffffff811661231d576040517f76ecffc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600d8660405161232e9190613107565b908152604051908190036020018120805473ffffffffffffffffffffffffffffffffffffffff939093167fffffffffffffffffffffffff0000000000000000000000000000000000000000909316929092179091557f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d906123b490879084908790613374565b60405180910390a15050505050565b5f6123cc612a3b565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156123f85750825b90505f8267ffffffffffffffff1660011480156124145750303b155b905081158015612422575080155b15612459576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156124ba5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6124c2612a63565b6124ca612a73565b6124d45f336125bd565b50600a805473ffffffffffffffffffffffffffffffffffffffff808c167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255600780548b8416908316179055600880548a8416908316179055600980549289169290911691909117905583156125a55784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b6125ba8133612a7b565b50565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff166126d2575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561266e3390565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610a37565b5f915050610a37565b5092915050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff16156126d2575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610a37565b6127c6612b29565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610f1a565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615610ca0576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0161292c576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60029055565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260056020526040812054808203612963575061012c5b835f03612973575f915050610a37565b61271061298082826133b7565b61298a90866131d4565b61299491906133ca565b949350505050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6129ca612855565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833612830565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610a37565b612a6b612b84565b610ca0612bc2565b610ca0612b84565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16612b25576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440160405180910390fd5b5050565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16610ca0576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b8c612bca565b610ca0576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61299c612b84565b5f612bd3612a3b565b5468010000000000000000900460ff16919050565b5f60208284031215612bf8575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114612c27575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112612c6a575f80fd5b813567ffffffffffffffff811115612c8457612c84612c2e565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff82111715612cf057612cf0612c2e565b604052818152838201602001851015612d07575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215612d34575f80fd5b823567ffffffffffffffff811115612d4a575f80fd5b612d5685828601612c5b565b95602094909401359450505050565b73ffffffffffffffffffffffffffffffffffffffff811681146125ba575f80fd5b80151581146125ba575f80fd5b5f8060408385031215612da4575f80fd5b8235612daf81612d65565b91506020830135612dbf81612d86565b809150509250929050565b5f60208284031215612dda575f80fd5b5035919050565b5f8060408385031215612df2575f80fd5b823591506020830135612dbf81612d65565b5f8060408385031215612e15575f80fd5b8235612e2081612d65565b946020939093013593505050565b5f60208284031215612e3e575f80fd5b8135612c2781612d65565b5f805f60608486031215612e5b575f80fd5b8335612e6681612d65565b9250602084013591506040840135612e7d81612d65565b809150509250925092565b803562ffffff81168114612e9a575f80fd5b919050565b5f805f805f8060c08789031215612eb4575f80fd5b8635612ebf81612d65565b9550602087013594506040870135612ed681612d65565b9350612ee460608801612e88565b9598949750929560808101359460a0909101359350915050565b5f60208284031215612f0e575f80fd5b813567ffffffffffffffff811115612f24575f80fd5b61299484828501612c5b565b5f805f8060808587031215612f43575f80fd5b8435612f4e81612d65565b93506020850135612f5e81612d65565b9250612f6c60408601612e88565b9396929550929360600135925050565b5f8060408385031215612f8d575f80fd5b823567ffffffffffffffff811115612fa3575f80fd5b612faf85828601612c5b565b9250506020830135612dbf81612d65565b5f805f60608486031215612fd2575f80fd5b8335612fdd81612d65565b92506020840135612fed81612d65565b91506040840135612e7d81612d65565b5f806040838503121561300e575f80fd5b823561301981612d65565b915061302760208401612e88565b90509250929050565b5f805f60608486031215613042575f80fd5b833567ffffffffffffffff811115613058575f80fd5b61306486828701612c5b565b935050602084013561307581612d65565b915061308360408501612e88565b90509250925092565b5f805f806080858703121561309f575f80fd5b84356130aa81612d65565b935060208501356130ba81612d65565b925060408501356130ca81612d65565b915060608501356130da81612d65565b939692955090935050565b5f5b838110156130ff5781810151838201526020016130e7565b50505f910152565b5f82516131188184602087016130e5565b9190910192915050565b5f81518084526131398160208601602086016130e5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081525f61317d6040830185613122565b90508260208301529392505050565b5f6020828403121561319c575f80fd5b8151612c2781612d86565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082028115828204841417610a3757610a376131a7565b80820180821115610a3757610a376131a7565b5f6020828403121561320e575f80fd5b8151612c2781612d65565b5f6101008201905073ffffffffffffffffffffffffffffffffffffffff835116825273ffffffffffffffffffffffffffffffffffffffff602084015116602083015262ffffff60408401511660408301526060830151613291606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080830151608083015260a083015160a083015260c083015160c083015260e08301516126db60e084018273ffffffffffffffffffffffffffffffffffffffff169052565b5f602082840312156132e7575f80fd5b5051919050565b5f805f8060808587031215613301575f80fd5b8451602086015190945061331481612d65565b604086015190935063ffffffff8116811461332d575f80fd5b6060959095015193969295505050565b604081525f61334f6040830185613122565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b606081525f6133866060830186613122565b905073ffffffffffffffffffffffffffffffffffffffff8416602083015262ffffff83166040830152949350505050565b81810381811115610a3757610a376131a7565b5f826133fd577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b50049056fea2646970667358221220be7683826e35c7cef49a08ea8ce84884a78fea00c3f7eced428fd855051f979864736f6c634300081a0033" +const HANDLER_CONTRACT_BYTECODE = "608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c908162bc574b1461393a5750806301ffc9a7146138995780630379eae8146138395780630ac6eb771461378d578063172bfc1c146137115780631a4e49d4146136e85780631a873ce4146136b5578063240028e81461366b578063248a9ca3146136195780632f2ff15d146135bc57806336568abe146135525780633f4ba83a146134495780634b1d2eeb146134095780634d20d0f8146133d65780634d49fbf3146132565780634eb7d1a11461321657806357724c41146131155780635b549182146130e25780635c975abb146130a1578063606b05a4146130345780636435967b1461286757806364f10e501461284c57806368c70c9e146128015780636ca752e3146127b65780636d4008a814612771578063780ad8271461206757806378a8812714611fec57806381fbadad14611fce5780638377e23014611f9a57806383b94a5214611ee45780638456cb5914611db957806391d1485414611d425780639be7fdb214611c57578063a217fddf14611c3b578063a5172ddb14611bf0578063a861469f14611ba6578063ad14d38514611b5c578063af90f35114611a7e578063b49f6b8814611a0f578063b5d8349f146119ae578063b6322a9f14611963578063be0580c0146117bd578063c6f1b7e71461176c578063cd20c6e814611727578063d17c872c14611601578063d547741f1461159a578063db9a0daf146114d7578063dbc1b46414611476578063dcc16b5c14611238578063dd19e7551461104c578063e798646614610f6d578063ec87621c14610f32578063eefbaa3514610e44578063f881446714610646578063f8c8765e14610314578063fb46e99d146102f65763fc6b5de80361000f57346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f35760206102e0816102cd3660048701613a2f565b8160405193828580945193849201613b1f565b8101601281520301902054604051908152f35b80fd5b50346102f357806003193601126102f3576020600654604051908152f35b50346102f35760806003193601126102f35761032e613aa7565b610336613aca565b61033e613aed565b6064359173ffffffffffffffffffffffffffffffffffffffff8316809303610642577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff81168015908161063a575b6001149081610630575b159081610627575b506105ff579173ffffffffffffffffffffffffffffffffffffffff80949392838860017fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000859716177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556105aa575b5061042a6143a1565b6104326143a1565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561045e6143a1565b61046733613ef5565b50167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a55167fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff000000000000000000000000000000000000000060085416176008557fffffffffffffffffffffffff000000000000000000000000000000000000000060095416176009556105165780f35b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f610421565b6004877ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b9050155f6103b2565b303b1591506103aa565b8791506103a0565b8480fd5b5060a06003193601126102f35761065b613aa7565b90610664613bc5565b9160443591606435936084359273ffffffffffffffffffffffffffffffffffffffff8416928385036102f35773ffffffffffffffffffffffffffffffffffffffff601054163303610e1c576106b76141f6565b6106bf614249565b8691839773ffffffffffffffffffffffffffffffffffffffff8216948515610df4578615610df4573415610dcc578815610dcc5762ffffff1615610d8a575b15610d62575b824211610d3a576107bf60208973ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a54169488861090815f14610d335786915b15610d2b57905b604051958694859384937f1698ee820000000000000000000000000000000000000000000000000000000085526004850191604091949373ffffffffffffffffffffffffffffffffffffffff62ffffff9281606087019816865216602085015216910152565b03915afa908115610bcc579073ffffffffffffffffffffffffffffffffffffffff918491610cfc575b501615610cd457803b15610bc85781600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af18015610c3557908291610cbf575b50600a546008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015234602482015292602092849260449284929091165af18015610c3557610ca2575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a541697604051986108cd8a61396a565b89528460208a0152169182604089015230606089015260808801528560a08801523460c08801528060e088015260206109b961010473ffffffffffffffffffffffffffffffffffffffff6008541699846040519b8c9485937fdb3e2198000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1968715610c95578197610c5d575b5080602073ffffffffffffffffffffffffffffffffffffffff600a5416604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015610c3557610c40575b506040517f42966c6800000000000000000000000000000000000000000000000000000000815286600482015260208160248185885af18015610c3557610c08575b5086340394348611610bdb57873403610b03575b505060606040967f01fd625a5ce1109c10761818e2ef64ea92cd4966d78086d37e5a4b50e322687892885191825287602083015288820152a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005582519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff600a5416803b15610bd7578280916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c60048401525af18015610bcc579183918893610bae575b5081809381925af1610b7a613db8565b5015610b865780610a9a565b807f90b8ec180000000000000000000000000000000000000000000000000000000060049252fd5b610bbb91935082906139b4565b610bc8578186915f610b6a565b5080fd5b6040513d85823e3d90fd5b8280fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b610c299060203d602011610c2e575b610c2181836139b4565b810190613cb9565b610a86565b503d610c17565b6040513d84823e3d90fd5b610c589060203d602011610c2e57610c2181836139b4565b610a44565b9096506020813d602011610c8d575b81610c79602093836139b4565b81010312610c895751955f6109c9565b5f80fd5b3d9150610c6c565b50604051903d90823e3d90fd5b610cba9060203d602011610c2e57610c2181836139b4565b6108a1565b81610cc9916139b4565b6102f357805f610836565b6004827f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b610d1e915060203d602011610d24575b610d1681836139b4565b810190613d7f565b5f6107e8565b503d610d0c565b508590610759565b8091610752565b6004827f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9150600654603c810290808204603c1490151715610bdb57610d849042613dab565b91610704565b8483526004602052604083205462ffffff169850886106fe575b6004837f3733548a000000000000000000000000000000000000000000000000000000008152fd5b6004847f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004847fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b807fbce361b00000000000000000000000000000000000000000000000000000000060049252fd5b50346102f35760606003193601126102f35760043567ffffffffffffffff8111610bc857610f1b610e9a7f5e41bf0052b493123a63e4e0d9095ed4324108e489d58c9a0948b2be366ac8c6923690600401613a2f565b602435604435610ef66040518385519160208181890194610ebc818388613b1f565b8101600b81520301902055826040516020818851610edb818388613b1f565b81016011815203019020556040519182918651928391613b1f565b8101906012825260208142930301902055604051938493608085526080850190613b40565b91602084015260408301524260608301520390a180f35b50346102f357806003193601126102f35760206040517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50346102f35760406003193601126102f357610f87613aa7565b73ffffffffffffffffffffffffffffffffffffffff610fa4613b10565b91610fad613de7565b169081156110245760207f16ef4de07b0452a43221c91064fb645963a8e2e60bd8a7514da58d56e315c42291838552600f825261101881604087209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b6004837fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760406003193601126102f357611066613aa7565b73ffffffffffffffffffffffffffffffffffffffff6024359116906040517fa0c50b690000000000000000000000000000000000000000000000000000000081528381600481865afa90811561122d57849161120b575b5060405191815192602081818501956110d7818389613b1f565b81016014815203019020549080155f146111cd57505b73ffffffffffffffffffffffffffffffffffffffff604051602081855161111581838a613b1f565b8101600c81520301902054169283156111a557602061113f91604051809381928751928391613b1f565b8101600b8152030190205490811561117d5761117993949561116360409284613ca6565b9681526013602052205460405195869586613b83565b0390f35b6004867fe661aed0000000000000000000000000000000000000000000000000000000008152fd5b6004867fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b908082106111db57506110ed565b85906044927fff632bea000000000000000000000000000000000000000000000000000000008352600452602452fd5b61122791503d8086833e61121f81836139b4565b810190613c47565b5f6110bd565b6040513d86823e3d90fd5b50346102f35760606003193601126102f35760043567ffffffffffffffff8111610bc85761126a903690600401613a2f565b611272613aca565b60443562ffffff8116918282036106425761128b613de7565b73ffffffffffffffffffffffffffffffffffffffff811680156111a5579160209161135d9373ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541691821091825f1461146f5780925b1561146757506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa801561122d5773ffffffffffffffffffffffffffffffffffffffff918591611448575b5016908115611420579161140f917f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d9360405160208185516113c98183858a01613b1f565b8101600d815203019020827fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051938493606085526060850190613b40565b91602084015260408301520390a180f35b6004847f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b611461915060203d602011610d2457610d1681836139b4565b5f611384565b905090610759565b81926112f1565b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f357602073ffffffffffffffffffffffffffffffffffffffff6114c3826102cd3660048801613a2f565b8101600c8152030190205416604051908152f35b50346102f35760206003193601126102f3576004358180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611572576020817f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b92600655604051908152a180f35b6004827f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760406003193601126102f3576115fd6004356115ba613aca565b906115f86115f3825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613e6f565b6140ee565b5080f35b50346102f35760406003193601126102f35761161b613aa7565b611623613bc5565b908280527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156116ff5773ffffffffffffffffffffffffffffffffffffffff169081156110245762ffffff16906101f4821415806116f3575b806116e7575b610da4578252600460205260408220907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000082541617905580f35b506127108214156116ad565b50610bb88214156116a7565b6004837f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f357604060209173ffffffffffffffffffffffffffffffffffffffff61175b613aa7565b168152601383522054604051908152f35b50346102f357806003193601126102f357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102f35760606003193601126102f3576117d7613aa7565b6117df613aca565b6117e7613aed565b918380527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040842073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f2054161561193b5773ffffffffffffffffffffffffffffffffffffffff168015801561191d575b80156118ff575b610df45773ffffffffffffffffffffffffffffffffffffffff929183917fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff00000000000000000000000000000000000000006008541617600855167fffffffffffffffffffffffff0000000000000000000000000000000000000000600954161760095580f35b5073ffffffffffffffffffffffffffffffffffffffff831615611862565b5073ffffffffffffffffffffffffffffffffffffffff82161561185b565b6004847f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f357602061199b816102cd3660048701613a2f565b8101601581520301902054604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f357602073ffffffffffffffffffffffffffffffffffffffff6119fb826102cd3660048801613a2f565b8101600d8152030190205416604051908152f35b50346102f3577f57ad858a99d9aee6f1fd395e454bb1659eb8500ccb081c729a103dc2247ba3a4611a3f36613a75565b90611a48613de7565b816040516020818451611a5e8183858901613b1f565b8101601581520301902055611a7860405192839283613c2b565b0390a180f35b50346102f35760206003193601126102f357611a98613aa7565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115725773ffffffffffffffffffffffffffffffffffffffff168015611b34577fffffffffffffffffffffffff0000000000000000000000000000000000000000601054161760105580f35b6004827fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f35760ff604060209273ffffffffffffffffffffffffffffffffffffffff611b92613aa7565b168152600384522054166040519015158152f35b50346102f35760206003193601126102f35762ffffff604060209273ffffffffffffffffffffffffffffffffffffffff611bde613aa7565b16815260048452205416604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f3576020611c28816102cd3660048701613a2f565b8101600b81520301902054604051908152f35b50346102f357806003193601126102f357602090604051908152f35b50346102f35760406003193601126102f35760043567ffffffffffffffff8111610bc857611c89903690600401613a2f565b73ffffffffffffffffffffffffffffffffffffffff611ca6613aca565b611cae613de7565b168015611024577f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94991611d36916040516020818451611cf08183858901613b1f565b8101600c815203019020817fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051928392604084526040840190613b40565b9060208301520390a180f35b50346102f35760406003193601126102f35773ffffffffffffffffffffffffffffffffffffffff6040611d73613aca565b9260043581527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020522091165f52602052602060ff60405f2054166040519015158152f35b50346102f357806003193601126102f3578080527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040812073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611ebc57611e266141f6565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b807f49e27cff0000000000000000000000000000000000000000000000000000000060049252fd5b50346102f35760206003193601126102f357611efe613aa7565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115725773ffffffffffffffffffffffffffffffffffffffff168015611b34577fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102f357806003193601126102f357602073ffffffffffffffffffffffffffffffffffffffff60105416604051908152f35b50346102f357806003193601126102f3576020600e54604051908152f35b50346102f357611ffb36613bd7565b9083809394527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156116ff57612064929361205f6141f6565b613cd1565b80f35b50346102f35760c06003193601126102f357612081613aa7565b6024359061208d613aed565b906064359262ffffff8416908185036125485760843560a435936120af6141f6565b6120b7614249565b6120c28684836142c0565b8473ffffffffffffffffffffffffffffffffffffffff821697888a52600360205260ff60408b20541615612749579415612708575b156126b3575b84421161268b576020846121ba928a73ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541690818d10805f146126845781935b501561146757506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156125ed5773ffffffffffffffffffffffffffffffffffffffff918991612665575b50161561263d578015612615576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018390526020816044818b8b5af180156125ed576125f8575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018390526020816044818b8b5af180156125ed576125d0575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a541693604051946122c58661396a565b8886526020808701918252929091166040808701828152306060890190815260808901998a5260a0890188815260c08a0188815260e08b018f815260085495517f414bf3890000000000000000000000000000000000000000000000000000000081529b5173ffffffffffffffffffffffffffffffffffffffff90811660048e01529751881660248d0152935162ffffff1660448c01529151861660648b0152995160848a0152985160a4890152975160c48801529651821660e48701529585916101049183918c91165af192831561256957879361259c575b5082106125745773ffffffffffffffffffffffffffffffffffffffff60085416604051907f095ea7b300000000000000000000000000000000000000000000000000000000825260048201528660248201526020816044818a8a5af180156125695761254c575b508573ffffffffffffffffffffffffffffffffffffffff600a5416803b15610bc8578180916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528960048401525af18015610c3557612533575b5080808085885af161247a613db8565b501561250b57927ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e2949273ffffffffffffffffffffffffffffffffffffffff9260c09584600a54169060405196875260208701526040860152606085015260808401521660a0820152a160017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6004867f90b8ec18000000000000000000000000000000000000000000000000000000008152fd5b8161253d916139b4565b61254857855f61246a565b8580fd5b6125649060203d602011610c2e57610c2181836139b4565b612406565b6040513d89823e3d90fd5b6004867f8199f5f3000000000000000000000000000000000000000000000000000000008152fd5b9092506020813d6020116125c8575b816125b8602093836139b4565b81010312610c895751915f61239f565b3d91506125ab565b6125e89060203d602011610c2e57610c2181836139b4565b612299565b6040513d8a823e3d90fd5b6126109060203d602011610c2e57610c2181836139b4565b612236565b6004877f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004877f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b61267e915060203d602011610d2457610d1681836139b4565b5f6121e1565b829361214d565b6004887f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9350600654603c810290808204603c14901517156126db576126d59042613dab565b936120fd565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8789526004602052604089205462ffffff169450846120f7576004897f3733548a000000000000000000000000000000000000000000000000000000008152fd5b60048a7f4e38f95a000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f357604060209173ffffffffffffffffffffffffffffffffffffffff6127a5613aa7565b168152600583522054604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f35760206127ee816102cd3660048701613a2f565b8101601481520301902054604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f3576020612839816102cd3660048701613a2f565b8101601181520301902054604051908152f35b50346102f35761206461285e36613bd7565b9161205f6141f6565b5034610c895760c0600319360112610c8957612881613aa7565b60243561288c613aed565b6064358015918215809203610c895760843562ffffff811690818103610c895760a4356128b76141f6565b6128bf614249565b6128ca84888a6142c0565b5f95156129e95750506040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101869052919050602082806044810103818a73ffffffffffffffffffffffffffffffffffffffff8b165af1908115612569577ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49460609473ffffffffffffffffffffffffffffffffffffffff9485946129ca575b505b6040519788526020880152604087015216941692a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6129e29060203d602011610c2e57610c2181836139b4565b505f61298c565b8091929395501561300c5773ffffffffffffffffffffffffffffffffffffffff871691825f52600360205260ff60405f20541615612fe4579215612fa2575b600654603c810290808204603c1490151715612f7557612a489042613dab565b804211612f4d57612b0060208573ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a541680881090815f14612f46578d915b15612f3e576040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015612e395773ffffffffffffffffffffffffffffffffffffffff915f91612f1f575b501615612ef7576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018890526020816044815f885af18015612e3957612eda575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018890526020816044815f885af18015612e3957612ebd575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169460405195612c058761396a565b858752602087015216604085015230606085015260808401528560a08401528060c08401525f60e08401526020612cef61010473ffffffffffffffffffffffffffffffffffffffff60085416955f60405197889485937f414bf389000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1928315612e39575f93612e89575b508210612e615760205f91604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015612e3957612e44575b5073ffffffffffffffffffffffffffffffffffffffff600a5416803b15610c89575f80916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528760048401525af18015612e3957612e24575b508580808084875af1612ddc613db8565b501561250b5773ffffffffffffffffffffffffffffffffffffffff7ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49360609382939061298e565b612e319196505f906139b4565b5f945f612dcb565b6040513d5f823e3d90fd5b612e5c9060203d602011610c2e57610c2181836139b4565b612d68565b7f8199f5f3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d602011612eb5575b81612ea5602093836139b4565b81010312610c895751915f612cff565b3d9150612e98565b612ed59060203d602011610c2e57610c2181836139b4565b612bd9565b612ef29060203d602011610c2e57610c2181836139b4565b612b76565b7f76ecffc0000000000000000000000000000000000000000000000000000000005f5260045ffd5b612f38915060203d602011610d2457610d1681836139b4565b5f612b27565b508c90610759565b8091612a95565b7f1ab7da6b000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9150805f52600460205262ffffff60405f2054169182612a28577f3733548a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e38f95a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f22c50cbf000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89577f882f47825d4043cd04a564cad4f524a7fe00a604ae024c23dbc8065b77668b4761306336613a75565b9061306c613de7565b8160405160208184516130828183858901613b1f565b810160148152030190205561309c60405192839283613c2b565b0390a1005b34610c89575f600319360112610c8957602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610c89575f600319360112610c8957602073ffffffffffffffffffffffffffffffffffffffff60075416604051908152f35b34610c89576040600319360112610c895761312e613aa7565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040902054602435919060ff16156131ee5773ffffffffffffffffffffffffffffffffffffffff1680156131c657611388821161319e575f52600560205260405f20555f80f35b7fc31c0b6e000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f49e27cff000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89576020600319360112610c89576004355f526002602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610c89576020600319360112610c895760045f73ffffffffffffffffffffffffffffffffffffffff613287613aa7565b16604051928380927fa0c50b690000000000000000000000000000000000000000000000000000000082525afa908115612e39575f916133bc575b50604051815190602081818501936132db818387613b1f565b81016015815203019020549182156133945773ffffffffffffffffffffffffffffffffffffffff6040516020818451613315818389613b1f565b8101600c81520301902054169182156131c657602061333f91604051809381928651928391613b1f565b8101600b8152030190205490811561336c578161335f8561117994613ca6565b9460405195869586613b83565b7fe661aed0000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f9502a873000000000000000000000000000000000000000000000000000000005f5260045ffd5b6133d091503d805f833e61121f81836139b4565b816132c2565b34610c89575f600319360112610c8957602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b34610c89576020600319360112610c89576004355f526001602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610c89575f600319360112610c8957335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131ee577fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff81161561352a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89576040600319360112610c895761356b613aca565b3373ffffffffffffffffffffffffffffffffffffffff8216036135945761001a906004356140ee565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89576040600319360112610c895761001a6004356135db613aca565b906136146115f3825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613fdc565b34610c89576020600319360112610c895760206136636004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b34610c89576020600319360112610c895773ffffffffffffffffffffffffffffffffffffffff613699613aa7565b165f52600f602052602060ff60405f2054166040519015158152f35b34610c89575f600319360112610c8957602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b34610c89576020600319360112610c89576004355f525f602052602060405f2054604051908152f35b34610c89576040600319360112610c895761372a613aa7565b73ffffffffffffffffffffffffffffffffffffffff6024359161374b613de7565b169081156131c65760207f911a025fb070fa2a29c37a3bf4c00d16acf15583cd050f17bdbacbab7e72320391835f52601382528060405f2055604051908152a2005b34610c89576040600319360112610c89576137a6613aa7565b6137ae613b10565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131ee5773ffffffffffffffffffffffffffffffffffffffff61001a92165f52600360205260405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b34610c89577f6a59d469e3757d6e139cdf95b12740f585d553afac49b90bdbe278502a44271861386836613a75565b9081604051602081845161387f8183858901613b1f565b8101600b8152030190205561309c60405192839283613c2b565b34610c89576020600319360112610c89576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610c8957807f7965db0b0000000000000000000000000000000000000000000000000000000060209214908115613910575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482613905565b34610c89575f600319360112610c895760209073ffffffffffffffffffffffffffffffffffffffff600854168152f35b610100810190811067ffffffffffffffff82111761398757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761398757604052565b67ffffffffffffffff811161398757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f82011215610c8957803590613a46826139f5565b92613a5460405194856139b4565b82845260208383010111610c8957815f926020809301838601378301015290565b6040600319820112610c89576004359067ffffffffffffffff8211610c8957613aa091600401613a2f565b9060243590565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610c8957565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610c8957565b6044359073ffffffffffffffffffffffffffffffffffffffff82168203610c8957565b602435908115158203610c8957565b5f5b838110613b305750505f910152565b8181015183820152602001613b21565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093613b7c81518092818752878088019101613b1f565b0116010190565b919260a09373ffffffffffffffffffffffffffffffffffffffff613bc29796931684526020840152604083015260608201528160808201520190613b40565b90565b6024359062ffffff82168203610c8957565b6003196060910112610c895760043573ffffffffffffffffffffffffffffffffffffffff81168103610c8957906024359060443573ffffffffffffffffffffffffffffffffffffffff81168103610c895790565b929190613c42602091604086526040860190613b40565b930152565b602081830312610c895780519067ffffffffffffffff8211610c89570181601f82011215610c89578051613c7a816139f5565b92613c8860405194856139b4565b81845260208284010111610c8957613bc29160208085019101613b1f565b81810292918115918404141715612f7557565b90816020910312610c8957518015158103610c895790565b90602091613d5293613ce48184846142c0565b5f73ffffffffffffffffffffffffffffffffffffffff6040518097819682957f47e7ef24000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0393165af18015612e3957613d645750565b613d7c9060203d602011610c2e57610c2181836139b4565b50565b90816020910312610c89575173ffffffffffffffffffffffffffffffffffffffff81168103610c895790565b91908201809211612f7557565b3d15613de2573d90613dc9826139f5565b91613dd760405193846139b4565b82523d5f602084013e565b606090565b335f9081527f06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a602052604090205460ff1615613e1f57565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0860245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615613ec65750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613fd75773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f146140e857805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f146140e857805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300541661422157565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146142985760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919073ffffffffffffffffffffffffffffffffffffffff16156131c65773ffffffffffffffffffffffffffffffffffffffff1680156131c65773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168114908115614397575b5061436f571561434757565b7f1f2a2005000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f82d5d76a000000000000000000000000000000000000000000000000000000005f5260045ffd5b905030145f61433b565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c16156143d057565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea2646970667358221220768f174ca9357d5558e1f156d7a974035ebdf7b2ddf7fb9cc7e899aba472f96d64736f6c634300081a0033" const PRC20_CREATION_BYTECODE = "608060405234801561000f575f80fd5b50600436106101a5575f3560e01c806374be2150116100e8578063c701262611610093578063eddeb1231161006e578063eddeb12314610457578063f687d12a1461046a578063f97c007a1461047d578063fc5fecd514610486575f80fd5b8063c7012626146103cb578063d9eeebed146103de578063dd62ed3e14610412575f80fd5b8063b84c8246116100c3578063b84c82461461037e578063c47f002714610391578063c6f1b7e7146103a4575f80fd5b806374be21501461033c57806395d89b4114610363578063a9059cbb1461036b575f80fd5b806323b872dd1161015357806347e7ef241161012e57806347e7ef24146102a1578063609c92b8146102b4578063701cd43b146102e857806370a0823114610307575f80fd5b806323b872dd14610266578063313ce5671461027957806342966c681461028e575f80fd5b8063091d278811610183578063091d278814610224578063095ea7b31461023b57806318160ddd1461025e575f80fd5b8063044d9371146101a957806306fdde03146101fa57806307e2bd8d1461020f575b5f80fd5b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610202610499565b6040516101f1919061143c565b61022261021d366004611479565b610529565b005b61022d60015481565b6040519081526020016101f1565b61024e610249366004611494565b6105ef565b60405190151581526020016101f1565b60065461022d565b61024e6102743660046114be565b6106ae565b60055460405160ff90911681526020016101f1565b61024e61029c3660046114fc565b61079b565b61024e6102af366004611494565b6107ae565b6102db7f000000000000000000000000000000000000000000000000000000000000000081565b6040516101f19190611513565b5f546101d09073ffffffffffffffffffffffffffffffffffffffff1681565b61022d610315366004611479565b73ffffffffffffffffffffffffffffffffffffffff165f9081526007602052604090205490565b61022d7f000000000000000000000000000000000000000000000000000000000000000081565b610202610879565b61024e610379366004611494565b610888565b61022261038c36600461157f565b61089d565b61022261039f36600461157f565b61091c565b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b61024e6103d936600461166f565b610997565b6103e6610af9565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016101f1565b61022d6104203660046116e1565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260086020908152604080832093909416825291909152205490565b6102226104653660046114fc565b610d04565b6102226104783660046114fc565b610da8565b61022d60025481565b6103e66104943660046114fc565b610e4c565b6060600380546104a890611718565b80601f01602080910402602001604051908101604052809291908181526020018280546104d490611718565b801561051f5780601f106104f65761010080835404028352916020019161051f565b820191905f5260205f20905b81548152906001019060200180831161050257829003601f168201915b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610576576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f412d5a95dc32cbb6bd9319bccf1bc1febeda71e734893a440f1f6853252fe99f906020015b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff831661063d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f81815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060015b92915050565b5f6106ba848484611055565b73ffffffffffffffffffffffffffffffffffffffff84165f90815260086020908152604080832033845290915290205482811015610724576040517f10bad14700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85165f81815260086020908152604080832033808552908352928190208786039081905590519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3506001949350505050565b5f6107a6338361119c565b506001919050565b5f6107b983836112ed565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060601b1660208201527f67fc7bdaed5b0ec550d8706b87d60568ab70c6b781263c70101d54cd1564aab390603401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526108689186908690611769565b60405180910390a150600192915050565b6060600480546104a890611718565b5f610894338484611055565b50600192915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461090c576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600461091882826117ef565b5050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461098b576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361091882826117ef565b5f805f6109a2610af9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018390529294509092505f918416906323b872dd906064016020604051808303815f875af1158015610a42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a669190611906565b905080610a9f576040517f0a7cd6d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610aa9338661119c565b7f9ffbffc04a397460ee1dbe8c9503e098090567d6b7f4b3c02a8617d800b6d9553388888886600254604051610ae496959493929190611925565b60405180910390a15060019695505050505050565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610bf8576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610c84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca891906119c0565b9050805f03610ce3576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254600154610cf39083611a04565b610cfd9190611a1b565b9150509091565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d73576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028190556040518181527fef13af88e424b5d15f49c77758542c1938b08b8b95b91ed0751f98ba99000d8f906020016105e4565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e17576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018190556040518181527fff5788270f43bfc1ca41c503606d2594aa3023a1a7547de403a3e2f146a4a80a906020016105e4565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610efc91906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610f4b576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610fd7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffb91906119c0565b9050805f03611036576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546110438583611a04565b61104d9190611a1b565b915050915091565b73ffffffffffffffffffffffffffffffffffffffff8316158061108c575073ffffffffffffffffffffffffffffffffffffffff8216155b156110c3576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526007602052604090205481811015611122576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8085165f8181526007602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061118e9086815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611222576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526007602052604090205481811015611281576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f8181526007602090815260408083208686039055600680548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff821661133a576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611373576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600680548201905573ffffffffffffffffffffffffffffffffffffffff82165f818152600760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b5f81518084525f5b818110156113ff576020818501810151868301820152016113e3565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61144e60208301846113db565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611476575f80fd5b50565b5f60208284031215611489575f80fd5b813561144e81611455565b5f80604083850312156114a5575f80fd5b82356114b081611455565b946020939093013593505050565b5f805f606084860312156114d0575f80fd5b83356114db81611455565b925060208401356114eb81611455565b929592945050506040919091013590565b5f6020828403121561150c575f80fd5b5035919050565b602081016003831061154c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91905290565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f6020828403121561158f575f80fd5b813567ffffffffffffffff8111156115a5575f80fd5b8201601f810184136115b5575f80fd5b803567ffffffffffffffff8111156115cf576115cf611552565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561163b5761163b611552565b604052818152828201602001861015611652575f80fd5b816020840160208301375f91810160200191909152949350505050565b5f805f60408486031215611681575f80fd5b833567ffffffffffffffff811115611697575f80fd5b8401601f810186136116a7575f80fd5b803567ffffffffffffffff8111156116bd575f80fd5b8660208284010111156116ce575f80fd5b6020918201979096509401359392505050565b5f80604083850312156116f2575f80fd5b82356116fd81611455565b9150602083013561170d81611455565b809150509250929050565b600181811c9082168061172c57607f821691505b602082108103611763577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b606081525f61177b60608301866113db565b73ffffffffffffffffffffffffffffffffffffffff9490941660208301525060400152919050565b601f8211156117ea57805f5260205f20601f840160051c810160208510156117c85750805b601f840160051c820191505b818110156117e7575f81556001016117d4565b50505b505050565b815167ffffffffffffffff81111561180957611809611552565b61181d816118178454611718565b846117a3565b6020601f82116001811461186e575f83156118385750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556117e7565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156118bb578785015182556020948501946001909201910161189b565b50848210156118f757868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215611916575f80fd5b8151801515811461144e575f80fd5b73ffffffffffffffffffffffffffffffffffffffff8716815260a060208201528460a0820152848660c08301375f60c086830101525f60c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8801168301019050846040830152836060830152826080830152979650505050505050565b5f602082840312156119b5575f80fd5b815161144e81611455565b5f602082840312156119d0575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176106a8576106a86119d7565b808201808211156106a8576106a86119d756fea26469706673582212206be692aa215f21df823c52c689a11caa03254730bfade7b8b36788d6a72ba61764736f6c634300081a0033" -const UNIVERSAL_GATEWAY_PC_BYTECODE = "6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610f6857508063248a9ca314610ef85780632f2ff15d14610e7d57806336568abe14610df55780633f4ba83a14610d1d5780635c975abb14610cbe5780637f57735014610c6e5780638456cb5914610b935780638e61856014610a6a57806391d14854146109d6578063a217fddf1461099e578063affed0e014610963578063b3ca1fbc1461058e578063c1ee135a1461053d578063d547741f146104bb578063e63ab1e9146104635763f8c8765e146100d7575f80fd5b3461045f5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5761010e611047565b610116611024565b9060443573ffffffffffffffffffffffffffffffffffffffff811680910361045f576064359173ffffffffffffffffffffffffffffffffffffffff831680930361045f577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff811680159081610457575b600114908161044d575b159081610444575b5061041c578560017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008316177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556103c7575b5073ffffffffffffffffffffffffffffffffffffffff82161580156103a9575b80156103a1575b8015610399575b61037157610281610287926102406117ef565b6102486117ef565b6102506117ef565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561027c6117ef565b6112c6565b506113ad565b507fffffffffffffffffffffffff00000000000000000000000000000000000000005f5416175f557fffffffffffffffffffffffff000000000000000000000000000000000000000060015416176001556102de57005b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b50831561022d565b508215610226565b5073ffffffffffffffffffffffffffffffffffffffff81161561021f565b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f6101ff565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050155f6101ac565b303b1591506101a4565b87915061019a565b5f80fd5b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5760206040517f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a8152f35b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5761053b6004356104f8611024565b90610536610531825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b611240565b6115c3565b005b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5760043567ffffffffffffffff811161045f578060040160c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc833603011261045f5761060761171f565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00541461093b5761063981611772565b6040805191610648828461106a565b600f83527f6569703135353a313131353531313100000000000000000000000000000000006020840152600254946001860180871161090e576002556024810193610692856110ab565b9360448301359460848401936106a8858a6110cc565b97909a67ffffffffffffffff89116108e1578451956106ef601f8b017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020018861106a565b8987526020870197368e8c011161045f576107e36107da6107f99f8f9d60a499610807976107c273ffffffffffffffffffffffffffffffffffffffff9f61082f9f908f915f6020886107cb996107d29b8637830101525190209281519373ffffffffffffffffffffffffffffffffffffffff928593602085019733895216908401528d6060840152608083015260c060a083015261079060e083018c61111d565b9060c0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261106a565b5190209f6110ab565b9d806110cc565b93909f6110cc565b979096016110ab565b9c87519e8f93610140855261014085019061111d565b92602081850391015261117a565b938b0152600160608b015261520860808b015261520860a08b015289830360c08b015261117a565b9461520860e08801521661010086015260048110156108b4577fd8352005a8b681f8cf230f28f60cef58ebe9a25d92e88f72cb6cb78799a6ca6d9173ffffffffffffffffffffffffffffffffffffffff9161012087015216938033940390a460017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f576020600254604051908152f35b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5760206040515f8152f35b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610a0d611024565b6004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610aa1611047565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff1615610b635773ffffffffffffffffffffffffffffffffffffffff90610af561171f565b1680156103715773ffffffffffffffffffffffffffffffffffffffff600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167fd0ef78509e8ed82196200827f0d10672cfab667994f990456881f413c1c475eb5f80a3005b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004525f60245260445ffd5b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610bc96111b8565b610bd161171f565b610bd961171f565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610d536111b8565b610d5b6116cb565b610d636116cb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610e2c611024565b3373ffffffffffffffffffffffffffffffffffffffff821603610e555761053b906004356115c3565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5761053b600435610eba611024565b90610ef3610531825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b6114b1565b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f576020610f606004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361045f57817f7965db0b0000000000000000000000000000000000000000000000000000000060209314908115610ffa575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610ff3565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361045f57565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361045f57565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108e157604052565b3573ffffffffffffffffffffffffffffffffffffffff8116810361045f5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561045f570180359067ffffffffffffffff821161045f5760200191813603831361045f57565b91908251928382525f5b8481106111655750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b80602080928401015182828601015201611127565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b335f9081527f75442b0a96088b5456bc4ed01394c96a4feec0f883c9494257d76b96ab1c9b6b602052604090205460ff16156111f057565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a60245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156112975750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff166113a85773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f75442b0a96088b5456bc4ed01394c96a4feec0f883c9494257d76b96ab1c9b6b602052604090205460ff166113a85773ffffffffffffffffffffffffffffffffffffffff165f8181527f75442b0a96088b5456bc4ed01394c96a4feec0f883c9494257d76b96ab1c9b6b6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f146115bd57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f146115bd57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416156116f757565b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300541661174a57565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b61177f60808201826110cc565b15801592604001351591506117e85781806117e0575b6117d957816117d1575b506117cc577fb4fa3fb3000000000000000000000000000000000000000000000000000000005f5260045ffd5b600190565b90505f61179f565b5050600390565b508015611795565b5050600290565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561181e57565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea26469706673582212206796924c3fa73cff81856f96b0134a35adc90b65de0eff7f3363998084206a5064736f6c634300081a0033" +const UNIVERSAL_GATEWAY_PC_BYTECODE = "6080806040526004361015610012575f80fd5b5f3560e01c9081637f577350146102f757508063affed0e0146102da578063b3ca1fbc146100745763c1ee135a14610048575f80fd5b34610070575f366003190112610070576001546040516001600160a01b039091168152602090f35b5f80fd5b60203660031901126100705760043567ffffffffffffffff8111610070578060040160c0600319833603011261007057600254600181018082116102c6576002556100bf8280610319565b91909360248101926100d08461034c565b60448301359060848401976100e58989610319565b67ffffffffffffffff81969296116102b2576040519061010f601f8201601f191660200183610360565b80825260208201933682890111610070577f8882d1d8f7b1750e49d021ea8d62e07c2d163645b8fa31c035905d6572ffc637996101d060a49787610186965f60208861027f9f996101e49a6101ed9e37830101525190206040519687956020870199338b5260e06040890152610100880191610382565b6001600160a01b039092166060860152608085018b905260a0850152838103601f190160c0850152600f81526e6569703135353a313131353531313160881b602082015260400190565b9060e083015203601f198101835282610360565b5190209661034c565b936102556102126102096102018b80610319565b9c909b610319565b9490930161034c565b986040519a6101608c526102476101608d01604090600f81526e6569703135353a313131353531313160881b60208201520190565b8c810360208e015291610382565b9260408a015261111160608a0152606f60808a015261520860a08a015288830360c08a0152610382565b5f60e087018190526001600160a01b039586166101008801526002610120880152610140870152931693339381900390a4005b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b34610070575f366003190112610070576020600254604051908152f35b34610070575f366003190112610070575f546001600160a01b03168152602090f35b903590601e1981360301821215610070570180359067ffffffffffffffff82116100705760200191813603831361007057565b356001600160a01b03811681036100705790565b90601f8019910116810190811067ffffffffffffffff8211176102b257604052565b908060209392818452848401375f828201840152601f01601f191601019056fea264697066735822122079614179005ddf0c314633ad63c96a5c52a1a1b032f71791f9eddc160bd868ed64736f6c634300081a0033" const UEA_MIGRATION_BYTECODE = "608060405234801561000f575f80fd5b506004361061006f575f3560e01c80639538c4b31161004d5780639538c4b3146100e7578063a5df53a01461010b578063f6829c321461012a575f80fd5b806352fa5c221461007357806367f102111461007d5780638c9ec7f5146100c7575b5f80fd5b61007b610132565b005b60025461009d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b60015461009d9073ffffffffffffffffffffffffffffffffffffffff1681565b6100fb6100f5366004610248565b3b151590565b60405190151581526020016100be565b5f5461009d9073ffffffffffffffffffffffffffffffffffffffff1681565b61007b61018a565b610e077f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d81815560405190919081907f310ba5f1d2ed074b51e2eccd052a47ae9ab7c6b800d1fca3db3999d6a592ca03905f90a25050565b5f5473ffffffffffffffffffffffffffffffffffffffff1630036101da576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025473ffffffffffffffffffffffffffffffffffffffff167f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d81815560405190919081907f310ba5f1d2ed074b51e2eccd052a47ae9ab7c6b800d1fca3db3999d6a592ca03905f90a25050565b5f60208284031215610258575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461027b575f80fd5b939250505056fea2646970667358221220b7392b390eabe1d8398ca6a63c585fe969825199b6bfe2a285e4edf564c16b6a64736f6c634300081a0033" diff --git a/test/utils/helpers.go b/test/utils/helpers.go index 5a485e3c..e33ecefb 100644 --- a/test/utils/helpers.go +++ b/test/utils/helpers.go @@ -48,6 +48,7 @@ func ExecVoteOutbound( outbound *uexecutortypes.OutboundTx, success bool, errorMsg string, + gasFeeUsed string, // actual gas fee consumed on destination chain; "" means no refund ) error { t.Helper() @@ -56,6 +57,7 @@ func ExecVoteOutbound( ErrorMsg: errorMsg, TxHash: fmt.Sprintf("0xobserved-%s", outbound.Id), BlockHeight: 1, + GasFeeUsed: gasFeeUsed, } msg := &uexecutortypes.MsgVoteOutbound{ @@ -106,3 +108,33 @@ func ExecVoteGasPrice( _, err := app.AuthzKeeper.Exec(ctx, &execMsg) return err } + +// ExecVoteChainMeta executes a MsgVoteChainMeta on behalf of the core validator +// through the universal validator using authz Exec. +func ExecVoteChainMeta( + t *testing.T, + ctx sdk.Context, + app *app.ChainApp, + universalAddr string, + coreValAddr string, + chainID string, + price uint64, + blockNumber uint64, +) error { + t.Helper() + + msg := &uexecutortypes.MsgVoteChainMeta{ + Signer: coreValAddr, + ObservedChainId: chainID, + Price: price, + ChainHeight: blockNumber, + } + + execMsg := authz.NewMsgExec( + sdk.MustAccAddressFromBech32(universalAddr), + []sdk.Msg{msg}, + ) + + _, err := app.AuthzKeeper.Exec(ctx, &execMsg) + return err +} diff --git a/universalClient/chains/common/chain_store.go b/universalClient/chains/common/chain_store.go index da54b423..34dc1975 100644 --- a/universalClient/chains/common/chain_store.go +++ b/universalClient/chains/common/chain_store.go @@ -157,6 +157,26 @@ func (cs *ChainStore) UpdateStatusAndVoteTxHash(eventID, oldStatus, newStatus, v return res.RowsAffected, nil } +// UpdateStatusAndEventData atomically flips the event status and updates the event data in one DB write. +// The update is conditional on the event currently having oldStatus (compare-and-swap semantics). +// Returns the number of rows affected (0 means the event was already in a different status). +func (cs *ChainStore) UpdateStatusAndEventData(eventID, oldStatus, newStatus string, eventData []byte) (int64, error) { + if cs.database == nil { + return 0, fmt.Errorf("database is nil") + } + + res := cs.database.Client(). + Model(&store.Event{}). + Where("event_id = ? AND status = ?", eventID, oldStatus). + Updates(map[string]any{"status": newStatus, "event_data": eventData}) + + if res.Error != nil { + return 0, fmt.Errorf("failed to update event status and event_data: %w", res.Error) + } + + return res.RowsAffected, nil +} + // UpdateVoteTxHash updates the vote_tx_hash field for an event func (cs *ChainStore) UpdateVoteTxHash(eventID string, voteTxHash string) error { if cs.database == nil { diff --git a/universalClient/chains/common/event_processor.go b/universalClient/chains/common/event_processor.go index 705306ac..2b399436 100644 --- a/universalClient/chains/common/event_processor.go +++ b/universalClient/chains/common/event_processor.go @@ -151,16 +151,19 @@ func (ep *EventProcessor) processConfirmedEvents(ctx context.Context) error { // processOutboundEvent processes an outbound event by voting on it func (ep *EventProcessor) processOutboundEvent(ctx context.Context, event *store.Event) error { - // Extract observation from event data - observation, err := ep.extractOutboundObservation(event) + // Parse outbound event data once + outboundData, err := ep.parseOutboundEventData(event) if err != nil { - return fmt.Errorf("failed to extract outbound observation: %w", err) + return fmt.Errorf("failed to parse outbound event data: %w", err) } - // Extract txID and universalTxID from event data - txID, utxID, err := ep.extractOutboundIDs(event) + txID := outboundData.TxID + utxID := outboundData.UniversalTxID + + // Build observation from parsed data + observation, err := ep.buildOutboundObservation(event, outboundData) if err != nil { - return fmt.Errorf("failed to extract outbound IDs: %w", err) + return fmt.Errorf("failed to build outbound observation: %w", err) } // Vote on outbound @@ -288,6 +291,7 @@ func (ep *EventProcessor) constructInbound(event *store.Event) (*uexecutortypes. AssetAddr: eventData.Token, LogIndex: strconv.FormatUint(uint64(eventData.LogIndex), 10), TxType: txType, + IsCEA: eventData.FromCEA, } if txType == uexecutortypes.TxType_FUNDS_AND_PAYLOAD || txType == uexecutortypes.TxType_GAS_AND_PAYLOAD { @@ -299,6 +303,13 @@ func (ep *EventProcessor) constructInbound(event *store.Event) (*uexecutortypes. inboundMsg.Recipient = eventData.Recipient } + // Set revert instructions if revert fund recipient is present + if eventData.RevertFundRecipient != "" { + inboundMsg.RevertInstructions = &uexecutortypes.RevertInstructions{ + FundRecipient: eventData.RevertFundRecipient, + } + } + // Check if VerificationData is 0x and replace with TxHash if inboundMsg.UniversalPayload != nil && inboundMsg.UniversalPayload.VType == uexecutortypes.VerificationType_universalTxVerification { inboundMsg.VerificationData = txHashHex @@ -330,39 +341,34 @@ func (ep *EventProcessor) base58ToHex(base58Str string) (string, error) { return "0x" + hex.EncodeToString(decoded), nil } -// extractOutboundIDs extracts both txID and universalTxID from an outbound Event's event data -func (ep *EventProcessor) extractOutboundIDs(event *store.Event) (txID string, utxID string, err error) { +// parseOutboundEventData unmarshals event data into an OutboundEvent struct +func (ep *EventProcessor) parseOutboundEventData(event *store.Event) (*OutboundEvent, error) { if event == nil { - return "", "", fmt.Errorf("event is nil") + return nil, fmt.Errorf("event is nil") } if len(event.EventData) == 0 { - return "", "", fmt.Errorf("event data is empty") + return nil, fmt.Errorf("event data is empty") } - // Parse event data JSON to extract tx_id and universal_tx_id var eventData OutboundEvent if err := json.Unmarshal(event.EventData, &eventData); err != nil { - return "", "", fmt.Errorf("failed to unmarshal event data: %w", err) + return nil, fmt.Errorf("failed to unmarshal event data: %w", err) } if eventData.TxID == "" { - return "", "", fmt.Errorf("tx_id not found in event data") + return nil, fmt.Errorf("tx_id not found in event data") } if eventData.UniversalTxID == "" { - return "", "", fmt.Errorf("universal_tx_id not found in event data") + return nil, fmt.Errorf("universal_tx_id not found in event data") } - return eventData.TxID, eventData.UniversalTxID, nil + return &eventData, nil } -// extractOutboundObservation extracts an OutboundObservation from event data -func (ep *EventProcessor) extractOutboundObservation(event *store.Event) (*uexecutortypes.OutboundObservation, error) { - if event == nil { - return nil, fmt.Errorf("event is nil") - } - +// buildOutboundObservation builds an OutboundObservation from event metadata and parsed outbound data +func (ep *EventProcessor) buildOutboundObservation(event *store.Event, outboundData *OutboundEvent) (*uexecutortypes.OutboundObservation, error) { // Extract txHash from EventID (format: "txHash:logIndex" or "signature:logIndex") txHash := "" parts := strings.Split(event.EventID, ":") @@ -380,11 +386,17 @@ func (ep *EventProcessor) extractOutboundObservation(event *store.Event) (*uexec txHashHex = txHash } + gasFeeUsed := "0" + if outboundData.GasFeeUsed != "" { + gasFeeUsed = outboundData.GasFeeUsed + } + observation := &uexecutortypes.OutboundObservation{ - Success: true, // Since event is confirmed, success is always true + Success: true, BlockHeight: event.BlockHeight, TxHash: txHashHex, ErrorMsg: "", + GasFeeUsed: gasFeeUsed, } return observation, nil diff --git a/universalClient/chains/common/event_processor_test.go b/universalClient/chains/common/event_processor_test.go index b723db27..1deff96c 100644 --- a/universalClient/chains/common/event_processor_test.go +++ b/universalClient/chains/common/event_processor_test.go @@ -172,15 +172,14 @@ func TestEventProcessorConstructInbound(t *testing.T) { }) } -func TestEventProcessorExtractOutboundIDs(t *testing.T) { +func TestEventProcessorParseOutboundEventData(t *testing.T) { logger := zerolog.Nop() processor := NewEventProcessor(nil, nil, "eip155:1", true, true, logger) t.Run("nil event returns error", func(t *testing.T) { - txID, utxID, err := processor.extractOutboundIDs(nil) + data, err := processor.parseOutboundEventData(nil) require.Error(t, err) - assert.Empty(t, txID) - assert.Empty(t, utxID) + assert.Nil(t, data) assert.Contains(t, err.Error(), "event is nil") }) @@ -189,17 +188,17 @@ func TestEventProcessorExtractOutboundIDs(t *testing.T) { EventID: "test", EventData: []byte{}, } - txID, utxID, err := processor.extractOutboundIDs(event) + data, err := processor.parseOutboundEventData(event) require.Error(t, err) - assert.Empty(t, txID) - assert.Empty(t, utxID) + assert.Nil(t, data) assert.Contains(t, err.Error(), "event data is empty") }) - t.Run("valid outbound event extracts IDs", func(t *testing.T) { + t.Run("valid outbound event extracts IDs and gas fee", func(t *testing.T) { eventData := OutboundEvent{ TxID: "0x1234", UniversalTxID: "0xabcd", + GasFeeUsed: "42000000000000", } eventDataBytes, _ := json.Marshal(eventData) @@ -208,10 +207,11 @@ func TestEventProcessorExtractOutboundIDs(t *testing.T) { EventData: eventDataBytes, } - txID, utxID, err := processor.extractOutboundIDs(event) + data, err := processor.parseOutboundEventData(event) require.NoError(t, err) - assert.Equal(t, "0x1234", txID) - assert.Equal(t, "0xabcd", utxID) + assert.Equal(t, "0x1234", data.TxID) + assert.Equal(t, "0xabcd", data.UniversalTxID) + assert.Equal(t, "42000000000000", data.GasFeeUsed) }) t.Run("missing tx_id returns error", func(t *testing.T) { @@ -226,10 +226,9 @@ func TestEventProcessorExtractOutboundIDs(t *testing.T) { EventData: eventDataBytes, } - txID, utxID, err := processor.extractOutboundIDs(event) + data, err := processor.parseOutboundEventData(event) require.Error(t, err) - assert.Empty(t, txID) - assert.Empty(t, utxID) + assert.Nil(t, data) assert.Contains(t, err.Error(), "tx_id not found") }) @@ -245,51 +244,69 @@ func TestEventProcessorExtractOutboundIDs(t *testing.T) { EventData: eventDataBytes, } - txID, utxID, err := processor.extractOutboundIDs(event) + data, err := processor.parseOutboundEventData(event) require.Error(t, err) - assert.Empty(t, txID) - assert.Empty(t, utxID) + assert.Nil(t, data) assert.Contains(t, err.Error(), "universal_tx_id not found") }) } -func TestEventProcessorExtractOutboundObservation(t *testing.T) { +func TestEventProcessorBuildOutboundObservation(t *testing.T) { logger := zerolog.Nop() processor := NewEventProcessor(nil, nil, "eip155:1", true, true, logger) - t.Run("nil event returns error", func(t *testing.T) { - obs, err := processor.extractOutboundObservation(nil) - require.Error(t, err) - assert.Nil(t, obs) - assert.Contains(t, err.Error(), "event is nil") - }) + t.Run("builds observation with gas fee from parsed data", func(t *testing.T) { + outboundData := &OutboundEvent{ + TxID: "0x1234", + UniversalTxID: "0xabcd", + GasFeeUsed: "42000000000000", + } - t.Run("valid event extracts observation", func(t *testing.T) { event := &store.Event{ EventID: "0xabc123:5", BlockHeight: 12345, - EventData: []byte("{}"), } - obs, err := processor.extractOutboundObservation(event) + obs, err := processor.buildOutboundObservation(event, outboundData) require.NoError(t, err) require.NotNil(t, obs) assert.True(t, obs.Success) assert.Equal(t, uint64(12345), obs.BlockHeight) assert.Equal(t, "0xabc123", obs.TxHash) + assert.Equal(t, "42000000000000", obs.GasFeeUsed) + }) + + t.Run("missing gas fee defaults to 0", func(t *testing.T) { + outboundData := &OutboundEvent{ + TxID: "0x1234", + UniversalTxID: "0xabcd", + } + + event := &store.Event{ + EventID: "0xabc123:5", + BlockHeight: 12345, + } + + obs, err := processor.buildOutboundObservation(event, outboundData) + require.NoError(t, err) + require.NotNil(t, obs) + assert.Equal(t, "0", obs.GasFeeUsed) }) t.Run("handles base58 tx hash", func(t *testing.T) { + outboundData := &OutboundEvent{ + TxID: "0x1234", + UniversalTxID: "0xabcd", + } + event := &store.Event{ EventID: "2VfUX:0", // Base58 encoded BlockHeight: 100, - EventData: []byte("{}"), } - obs, err := processor.extractOutboundObservation(event) + obs, err := processor.buildOutboundObservation(event, outboundData) require.NoError(t, err) require.NotNil(t, obs) - // Should be converted to hex assert.True(t, len(obs.TxHash) >= 2) }) } @@ -302,6 +319,8 @@ func TestEventProcessorStruct(t *testing.T) { assert.Empty(t, ep.chainID) assert.False(t, ep.running) assert.Nil(t, ep.stopCh) + assert.False(t, ep.inboundEnabled) + assert.False(t, ep.outboundEnabled) }) } diff --git a/universalClient/chains/common/types.go b/universalClient/chains/common/types.go index e78c100b..bf7c231c 100644 --- a/universalClient/chains/common/types.go +++ b/universalClient/chains/common/types.go @@ -2,7 +2,6 @@ package common import ( "context" - "math/big" uetypes "github.com/pushchain/push-chain-node/x/uexecutor/types" ) @@ -25,15 +24,14 @@ type ChainClient interface { // UnSignedOutboundTxReq contains the request for signing an outbound transaction type UnSignedOutboundTxReq struct { - SigningHash []byte // Hash to be signed by TSS - Nonce uint64 // evm - TSS Address nonce | svm - PDA nonce - GasPrice *big.Int // evm - Gas price used | svm - Prioritization fee + SigningHash []byte // Hash to be signed by TSS + Nonce uint64 // evm - TSS Address nonce | svm - PDA nonce } // OutboundTxBuilder builds and broadcasts transactions for outbound transfers type OutboundTxBuilder interface { // GetOutboundSigningRequest creates a signing request from outbound event data - GetOutboundSigningRequest(ctx context.Context, data *uetypes.OutboundCreatedEvent, gasPrice *big.Int, nonce uint64) (*UnSignedOutboundTxReq, error) + GetOutboundSigningRequest(ctx context.Context, data *uetypes.OutboundCreatedEvent, nonce uint64) (*UnSignedOutboundTxReq, error) // GetNextNonce returns the next nonce for the given signer on this chain (for seeding local nonce). // useFinalized: for EVM, if true use finalized block nonce (aggressive/replace stuck); if false use pending. SVM ignores this. @@ -56,6 +54,12 @@ type OutboundTxBuilder interface { // For SVM: checks if the ExecutedTx PDA exists on-chain. // For EVM: returns false (EVM uses nonce-based replay protection). IsAlreadyExecuted(ctx context.Context, txID string) (bool, error) + + // GetGasFeeUsed returns the gas fee used by a transaction on the destination chain. + // EVM: fetches receipt and returns gasUsed * effectiveGasPrice as decimal string. + // SVM: returns "0" (gas accounting is handled via vault gasFee reimbursement). + // Returns "0" if the transaction is not found. + GetGasFeeUsed(ctx context.Context, txHash string) (string, error) } // UniversalTx Payload @@ -69,8 +73,8 @@ type UniversalTx struct { Payload uetypes.UniversalPayload `json:"universalPayload"` VerificationData string `json:"verificationData"` RevertFundRecipient string `json:"revertFundRecipient,omitempty"` - RevertMsg string `json:"revertMsg,omitempty"` // hex-encoded bytes (0x…) TxType uint `json:"txType"` // enum backing uint as decimal string + FromCEA bool `json:"fromCEA"` // true if inbound is initiated by a CEA } // OutboundEvent represents an outbound observation event from the gateway contract @@ -78,8 +82,9 @@ type UniversalTx struct { // - txID at 1st indexed position (bytes32) // - universalTxID at 2nd indexed position (bytes32) type OutboundEvent struct { - TxID string `json:"tx_id"` // bytes32 hex-encoded (0x...) - UniversalTxID string `json:"universal_tx_id"` // bytes32 hex-encoded (0x...) + TxID string `json:"tx_id"` // bytes32 hex-encoded (0x...) + UniversalTxID string `json:"universal_tx_id"` // bytes32 hex-encoded (0x...) + GasFeeUsed string `json:"gas_fee_used,omitempty"` // gas fee used in wei (decimal string) } // Event type enum values for event classification. diff --git a/universalClient/chains/evm/gas_oracle.go b/universalClient/chains/evm/chain_meta_oracle.go similarity index 73% rename from universalClient/chains/evm/gas_oracle.go rename to universalClient/chains/evm/chain_meta_oracle.go index 5824340c..838dbb42 100644 --- a/universalClient/chains/evm/gas_oracle.go +++ b/universalClient/chains/evm/chain_meta_oracle.go @@ -9,8 +9,8 @@ import ( "github.com/rs/zerolog" ) -// GasOracle handles fetching and reporting gas prices -type GasOracle struct { +// ChainMetaOracle handles fetching and reporting gas prices +type ChainMetaOracle struct { rpcClient *RPCClient pushSigner *pushsigner.Signer chainID string @@ -20,15 +20,15 @@ type GasOracle struct { wg sync.WaitGroup } -// NewGasOracle creates a new gas oracle -func NewGasOracle( +// NewChainMetaOracle creates a new gas oracle +func NewChainMetaOracle( rpcClient *RPCClient, pushSigner *pushsigner.Signer, chainID string, gasPriceIntervalSeconds int, logger zerolog.Logger, -) *GasOracle { - return &GasOracle{ +) *ChainMetaOracle { + return &ChainMetaOracle{ rpcClient: rpcClient, pushSigner: pushSigner, chainID: chainID, @@ -39,24 +39,24 @@ func NewGasOracle( } // Start begins fetching and voting on gas prices -func (g *GasOracle) Start(ctx context.Context) error { +func (g *ChainMetaOracle) Start(ctx context.Context) error { g.wg.Add(1) - go g.fetchAndVoteGasPrice(ctx) + go g.fetchAndVoteChainMeta(ctx) return nil } // Stop stops the gas oracle -func (g *GasOracle) Stop() { +func (g *ChainMetaOracle) Stop() { close(g.stopCh) g.wg.Wait() } -// fetchAndVoteGasPrice periodically fetches gas price and votes on it -func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { +// fetchAndVoteChainMeta periodically fetches gas price and votes on it +func (g *ChainMetaOracle) fetchAndVoteChainMeta(ctx context.Context) { defer g.wg.Done() // Get gas oracle fetch interval from config - interval := g.getGasOracleFetchInterval() + interval := g.getChainMetaOracleFetchInterval() if interval <= 0 { interval = 30 * time.Second } @@ -97,15 +97,15 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { continue } - // Vote on gas price + // Vote on chain meta (gas price + block height) priceUint64 := gasPrice.Uint64() - voteTxHash, err := g.pushSigner.VoteGasPrice(ctx, g.chainID, priceUint64, blockNumber) + voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, blockNumber) if err != nil { g.logger.Error(). Err(err). Uint64("price", priceUint64). Uint64("block", blockNumber). - Msg("failed to vote on gas price") + Msg("failed to vote on chain meta") continue } @@ -113,13 +113,13 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { Str("vote_tx_hash", voteTxHash). Uint64("price", priceUint64). Uint64("block", blockNumber). - Msg("successfully voted on gas price") + Msg("successfully voted on chain meta") } } } -// getGasOracleFetchInterval returns the gas oracle fetch interval -func (g *GasOracle) getGasOracleFetchInterval() time.Duration { +// getChainMetaOracleFetchInterval returns the gas oracle fetch interval +func (g *ChainMetaOracle) getChainMetaOracleFetchInterval() time.Duration { if g.gasPriceIntervalSeconds <= 0 { return 30 * time.Second } diff --git a/universalClient/chains/evm/gas_oracle_test.go b/universalClient/chains/evm/chain_meta_oracle_test.go similarity index 68% rename from universalClient/chains/evm/gas_oracle_test.go rename to universalClient/chains/evm/chain_meta_oracle_test.go index 07eb9031..8d15b14e 100644 --- a/universalClient/chains/evm/gas_oracle_test.go +++ b/universalClient/chains/evm/chain_meta_oracle_test.go @@ -9,13 +9,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestNewGasOracle(t *testing.T) { +func TestNewChainMetaOracle(t *testing.T) { t.Run("creates gas oracle with valid params", func(t *testing.T) { logger := zerolog.Nop() chainID := "eip155:1" interval := 30 - oracle := NewGasOracle(nil, nil, chainID, interval, logger) + oracle := NewChainMetaOracle(nil, nil, chainID, interval, logger) require.NotNil(t, oracle) assert.Equal(t, chainID, oracle.chainID) @@ -36,30 +36,30 @@ func TestNewGasOracle(t *testing.T) { } for _, chainID := range testCases { - oracle := NewGasOracle(nil, nil, chainID, 30, logger) + oracle := NewChainMetaOracle(nil, nil, chainID, 30, logger) assert.Equal(t, chainID, oracle.chainID) } }) } -func TestGasOracleGetGasOracleFetchInterval(t *testing.T) { +func TestChainMetaOracleGetChainMetaOracleFetchInterval(t *testing.T) { logger := zerolog.Nop() t.Run("returns configured interval", func(t *testing.T) { - oracle := NewGasOracle(nil, nil, "eip155:1", 60, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "eip155:1", 60, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, 60*time.Second, interval) }) t.Run("returns default for zero interval", func(t *testing.T) { - oracle := NewGasOracle(nil, nil, "eip155:1", 0, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "eip155:1", 0, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, 30*time.Second, interval) }) t.Run("returns default for negative interval", func(t *testing.T) { - oracle := NewGasOracle(nil, nil, "eip155:1", -10, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "eip155:1", -10, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, 30*time.Second, interval) }) @@ -75,26 +75,26 @@ func TestGasOracleGetGasOracleFetchInterval(t *testing.T) { } for _, tc := range testCases { - oracle := NewGasOracle(nil, nil, "eip155:1", tc.input, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "eip155:1", tc.input, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, tc.expected, interval, "interval %d should result in %v", tc.input, tc.expected) } }) } -func TestGasOracleStop(t *testing.T) { +func TestChainMetaOracleStop(t *testing.T) { t.Run("stop waits for goroutine", func(t *testing.T) { logger := zerolog.Nop() - oracle := NewGasOracle(nil, nil, "eip155:1", 30, logger) + oracle := NewChainMetaOracle(nil, nil, "eip155:1", 30, logger) // Should not panic or hang oracle.Stop() }) } -func TestGasOracleStruct(t *testing.T) { +func TestChainMetaOracleStruct(t *testing.T) { t.Run("struct has expected fields", func(t *testing.T) { - oracle := &GasOracle{} + oracle := &ChainMetaOracle{} assert.Nil(t, oracle.rpcClient) assert.Nil(t, oracle.pushSigner) assert.Empty(t, oracle.chainID) diff --git a/universalClient/chains/evm/client.go b/universalClient/chains/evm/client.go index 1bf5dd71..03569e83 100644 --- a/universalClient/chains/evm/client.go +++ b/universalClient/chains/evm/client.go @@ -32,11 +32,11 @@ type Client struct { cancel context.CancelFunc // Components - eventListener *EventListener - eventProcessor *common.EventProcessor - eventConfirmer *EventConfirmer - gasOracle *GasOracle - txBuilder *TxBuilder + eventListener *EventListener + eventProcessor *common.EventProcessor + eventConfirmer *EventConfirmer + chainMetaOracle *ChainMetaOracle + txBuilder *TxBuilder // Dependencies pushSigner *pushsigner.Signer @@ -143,8 +143,8 @@ func (c *Client) Stop() error { } } - if c.gasOracle != nil { - c.gasOracle.Stop() + if c.chainMetaOracle != nil { + c.chainMetaOracle.Stop() } // Close RPC client last @@ -270,7 +270,7 @@ func (c *Client) initializeComponents() error { // Create gas oracle if pushSigner is available if c.pushSigner != nil { - c.gasOracle = NewGasOracle( + c.chainMetaOracle = NewChainMetaOracle( c.rpcClient, c.pushSigner, c.chainIDStr, @@ -302,8 +302,8 @@ func (c *Client) startComponents() error { } } - if c.gasOracle != nil { - if err := c.gasOracle.Start(c.ctx); err != nil { + if c.chainMetaOracle != nil { + if err := c.chainMetaOracle.Start(c.ctx); err != nil { return fmt.Errorf("failed to start gas oracle: %w", err) } } diff --git a/universalClient/chains/evm/event_confirmer.go b/universalClient/chains/evm/event_confirmer.go index bf4b9ad3..b38012df 100644 --- a/universalClient/chains/evm/event_confirmer.go +++ b/universalClient/chains/evm/event_confirmer.go @@ -2,7 +2,9 @@ package evm import ( "context" + "encoding/json" "fmt" + "math/big" "strings" "sync" "time" @@ -147,8 +149,48 @@ func (ec *EventConfirmer) processPendingEvents(ctx context.Context) error { confirmations := latestBlock - receipt.BlockNumber.Uint64() + 1 if confirmations >= requiredConfirmations { - // Update event status to CONFIRMED - rowsAffected, err := ec.chainStore.UpdateEventStatus(event.EventID, "PENDING", "CONFIRMED") + var rowsAffected int64 + + // For outbound events, enrich with gas fee before confirming + if event.Type == chaincommon.EventTypeOutbound { + tx, _, txErr := ec.rpcClient.GetTransactionByHash(ctx, hash) + if txErr != nil { + ec.logger.Warn(). + Err(txErr). + Str("event_id", event.EventID). + Str("tx_hash", txHash). + Msg("failed to fetch transaction for gas fee, skipping confirmation") + continue + } + gasUsed := new(big.Int).SetUint64(receipt.GasUsed) + gasPrice := tx.GasPrice() + gasFeeUsed := new(big.Int).Mul(gasUsed, gasPrice).String() + + // Unmarshal, set GasFeeUsed, re-marshal + var outboundEvent chaincommon.OutboundEvent + if unmarshalErr := json.Unmarshal(event.EventData, &outboundEvent); unmarshalErr != nil { + ec.logger.Error(). + Err(unmarshalErr). + Str("event_id", event.EventID). + Msg("failed to unmarshal outbound event data") + continue + } + outboundEvent.GasFeeUsed = gasFeeUsed + + updatedData, marshalErr := json.Marshal(outboundEvent) + if marshalErr != nil { + ec.logger.Error(). + Err(marshalErr). + Str("event_id", event.EventID). + Msg("failed to marshal enriched outbound event data") + continue + } + + rowsAffected, err = ec.chainStore.UpdateStatusAndEventData(event.EventID, "PENDING", "CONFIRMED", updatedData) + } else { + rowsAffected, err = ec.chainStore.UpdateEventStatus(event.EventID, "PENDING", "CONFIRMED") + } + if err != nil { ec.logger.Error(). Err(err). diff --git a/universalClient/chains/evm/event_parser.go b/universalClient/chains/evm/event_parser.go index 517808cd..b5ae28f5 100644 --- a/universalClient/chains/evm/event_parser.go +++ b/universalClient/chains/evm/event_parser.go @@ -21,9 +21,9 @@ import ( // Event type constants matching gateway method names in chain config. const ( - EventTypeSendFunds = "sendFunds" - EventTypeExecuteUniversalTx = "executeUniversalTx" - EventTypeRevertUniversalTx = "revertUniversalTx" + EventTypeSendFunds = "sendFunds" + EventTypeExecuteUniversalTx = "executeUniversalTx" + EventTypeRevertUniversalTx = "revertUniversalTx" ) // Vault event type constants matching vault method names in chain config. @@ -150,23 +150,12 @@ func parseOutboundObservationEvent(log *types.Log, chainID string, logger zerolo return event } -/* -UniversalTx Event: - 1. sender (address) - 2. recipient (address) - 3. token (address) - 4. amount (uint256) - 5. payload (bytes) - 6. revertInstructions (tuple) - 6.1. revertRecipient (address) - 6.2. revertMsg (bytes) - 7. txType (uint) - 8. signatureData (bytes) -*/ +// parseUniversalTxEvent parses a UniversalTx event from log data. +// Detects V1 (legacy) vs V2 (upgraded) format based on the payload offset: +// V2 has 7 static words (head=224), V1 has 6 (head=192). func parseUniversalTxEvent(event *store.Event, log *types.Log, chainID string, logger zerolog.Logger) { if len(log.Topics) < 3 { - logger.Warn(). - Msg("not enough indexed fields; nothing to do") + logger.Warn().Msg("not enough indexed fields; nothing to do") return } @@ -177,142 +166,87 @@ func parseUniversalTxEvent(event *store.Event, log *types.Log, chainID string, l LogIndex: log.Index, } - // Helper: fetch the i-th 32-byte word from log.Data. - word := func(i int) []byte { - start := i * 32 - end := start + 32 - if start < 0 || end > len(log.Data) { - return nil - } - return log.Data[start:end] - } - - // Need at least 5 words for the static head we rely on. if len(log.Data) < 32*5 { b, _ := json.Marshal(payload) event.EventData = b return } - // bridgeToken (address in the right-most 20 bytes of the first word) - if w := word(0); w != nil { - payload.Token = ethcommon.BytesToAddress(w[12:32]).Hex() - } + // Parse common static fields: token (Word 0), amount (Word 1) + payload.Token = ethcommon.BytesToAddress(log.Data[0*32+12 : 0*32+32]).Hex() + payload.Amount = new(big.Int).SetBytes(log.Data[1*32 : 2*32]).String() - // bridgeAmount (uint256) - if w := word(1); w != nil { - amt := new(big.Int).SetBytes(w) - payload.Amount = amt.String() + // Detect format via payload offset (Word 2): >= 224 means V2 (7-word head) + dataOffset := new(big.Int).SetBytes(log.Data[2*32 : 3*32]).Uint64() + if dataOffset >= uint64(32*7) { + parseUniversalTxV2(event, log, dataOffset, &payload, logger) + } else { + parseUniversalTxV1Legacy(event, log, dataOffset, &payload, logger) } +} - // dynamic offsets (relative to start of log.Data) - var dataOffset, revertOffset uint64 - if w := word(2); w != nil { - dataOffset = new(big.Int).SetBytes(w).Uint64() +// readDynamicBytes decodes ABI-encoded dynamic bytes at the given absolute offset in data. +func readDynamicBytes(data []byte, absOff uint64) (string, bool) { + if absOff+32 > uint64(len(data)) { + return "", false } - if w := word(3); w != nil { - revertOffset = new(big.Int).SetBytes(w).Uint64() + byteLen := new(big.Int).SetBytes(data[absOff : absOff+32]).Uint64() + dataStart := absOff + 32 + dataEnd := dataStart + byteLen + if dataEnd > uint64(len(data)) { + return "", false } + return "0x" + hex.EncodeToString(data[dataStart:dataEnd]), true +} - // txType (enum -> padded uint) - if w := word(4); w != nil { - txType := new(big.Int).SetBytes(w) - payload.TxType = uint(txType.Uint64()) +// readWord returns the i-th 32-byte word from data, or nil if out of bounds. +func readWord(data []byte, i int) []byte { + start := i * 32 + end := start + 32 + if start < 0 || end > len(data) { + return nil } + return data[start:end] +} - // Decode dynamic bytes at absolute offset in log.Data: - readBytesAt := func(absOff uint64) (hexStr string, ok bool) { - if absOff+32 > uint64(len(log.Data)) { - return "", false - } - lstart := int(absOff) - lend := lstart + 32 - byteLen := new(big.Int).SetBytes(log.Data[lstart:lend]).Uint64() - - dataStart := lend - dataEnd := dataStart + int(byteLen) - if dataEnd > len(log.Data) { - return "", false - } - return "0x" + hex.EncodeToString(log.Data[dataStart:dataEnd]), true +// decodePayload decodes the universal payload bytes at the given offset into the payload struct. +func decodePayload(data []byte, dataOffset uint64, payload *common.UniversalTx, logger zerolog.Logger) { + if dataOffset < uint64(32*5) { + return } - - // Decode address at absolute offset in log.Data: - readAddressAt := func(absOff uint64) (string, bool) { - if absOff+32 > uint64(len(log.Data)) { - return "", false - } - w := log.Data[absOff : absOff+32] - return ethcommon.BytesToAddress(w[12:32]).Hex(), true - } - - // --- payload (bytes) --- - // Offsets for dynamic fields in the head will be >= head size (5*32) - if dataOffset >= uint64(32*5) { - if hexStr, ok := readBytesAt(dataOffset); ok { - up, err := decodeUniversalPayload(hexStr) - if err != nil { - logger.Warn(). - Str("hex_str", hexStr). - Err(err). - Msg("failed to decode universal payload") - } else if up != nil { - payload.Payload = *up - } - } + hexStr, ok := readDynamicBytes(data, dataOffset) + if !ok { + return } - - // --- revertCFG (tuple(address fundRecipient, bytes revertMsg)) --- - // Decode the tuple if we have enough room for its head (2 words). - // NOTE: Offsets inside a tuple are RELATIVE TO THE START OF THE TUPLE. - if revertOffset >= uint64(32*5) && revertOffset+64 <= uint64(len(log.Data)) { - tupleBase := revertOffset - - // fundRecipient @ tupleBase + 0 - if addr, ok := readAddressAt(tupleBase); ok { - payload.RevertFundRecipient = addr - } - - // revertMsg offset word @ tupleBase + 32 (relative to tupleBase) - offWordStart := tupleBase + 32 - offWordEnd := offWordStart + 32 - revertMsgRelOff := new(big.Int).SetBytes(log.Data[offWordStart:offWordEnd]).Uint64() - - revertMsgAbsOff := tupleBase + revertMsgRelOff - if hexStr, ok := readBytesAt(revertMsgAbsOff); ok { - payload.RevertMsg = hexStr - } + up, err := decodeUniversalPayload(hexStr) + if err != nil { + logger.Warn().Str("hex_str", hexStr).Err(err).Msg("failed to decode universal payload") + } else if up != nil { + payload.Payload = *up } +} - // --- signatureData (bytes) --- - // Check if we have a 6th word that contains an offset to dynamic bytes - if len(log.Data) >= 32*6 { - if w := word(5); w != nil { - // Check if this is an offset (dynamic bytes) or fixed bytes32 - offset := new(big.Int).SetBytes(w).Uint64() - - // If offset is reasonable (points to data after the static head), treat as dynamic bytes - if offset >= uint64(32*6) && offset < uint64(len(log.Data)) { - if hexStr, ok := readBytesAt(offset); ok { - payload.VerificationData = hexStr - } - } else { - // Fallback: treat as fixed bytes32 (for backward compatibility) - payload.VerificationData = "0x" + hex.EncodeToString(w) - } +// decodeSignatureData decodes the signature/verification data from a word that contains +// either a dynamic offset or fixed bytes32. +func decodeSignatureData(data []byte, w []byte, minOffset uint64) string { + offset := new(big.Int).SetBytes(w).Uint64() + if offset >= minOffset && offset < uint64(len(data)) { + if hexStr, ok := readDynamicBytes(data, offset); ok { + return hexStr } } + // Fallback: treat as fixed bytes32 + return "0x" + hex.EncodeToString(w) +} - // Marshal and store into event.EventData +// finalizeEvent marshals the payload and sets confirmation type on the event. +func finalizeEvent(event *store.Event, payload *common.UniversalTx, logger zerolog.Logger) { if b, err := json.Marshal(payload); err == nil { event.EventData = b } else { - logger.Warn(). - Err(err). - Msg("failed to marshal universal tx payload") + logger.Warn().Err(err).Msg("failed to marshal universal tx payload") } - // if TxType is 0 or 1, use FAST else use STANDARD if payload.TxType == 0 || payload.TxType == 1 { event.ConfirmationType = "FAST" } else { @@ -320,6 +254,85 @@ func parseUniversalTxEvent(event *store.Event, log *types.Log, chainID string, l } } +/* +UniversalTx Event (V2 - upgraded chains): + - sender (address, indexed) + - recipient (address, indexed) + - token (address) — Word 0 + - amount (uint256) — Word 1 + - payload (bytes) — Word 2 (offset) + - revertRecipient (address) — Word 3 + - txType (TX_TYPE) — Word 4 + - signatureData (bytes) — Word 5 (offset) + - fromCEA (bool) — Word 6 +*/ +func parseUniversalTxV2(event *store.Event, log *types.Log, dataOffset uint64, payload *common.UniversalTx, logger zerolog.Logger) { + data := log.Data + + decodePayload(data, dataOffset, payload, logger) + + // revertRecipient (plain address at Word 3) + if w := readWord(data, 3); w != nil { + payload.RevertFundRecipient = ethcommon.BytesToAddress(w[12:32]).Hex() + } + + // txType (Word 4) + if w := readWord(data, 4); w != nil { + payload.TxType = uint(new(big.Int).SetBytes(w).Uint64()) + } + + // signatureData (Word 5 offset) + if w := readWord(data, 5); w != nil { + payload.VerificationData = decodeSignatureData(data, w, uint64(32*7)) + } + + // fromCEA (Word 6) + if w := readWord(data, 6); w != nil { + payload.FromCEA = new(big.Int).SetBytes(w).Uint64() != 0 + } + + finalizeEvent(event, payload, logger) +} + +/* +UniversalTx Event (V1 - legacy, to be removed): + - sender (address, indexed) + - recipient (address, indexed) + - token (address) — Word 0 + - amount (uint256) — Word 1 + - payload (bytes) — Word 2 (offset) + - revertInstructions (tuple) — Word 3 (offset) + - revertRecipient (address) + - revertMsg (bytes) + - txType (uint) — Word 4 + - signatureData (bytes) — Word 5 (offset) +*/ +func parseUniversalTxV1Legacy(event *store.Event, log *types.Log, dataOffset uint64, payload *common.UniversalTx, logger zerolog.Logger) { + data := log.Data + + decodePayload(data, dataOffset, payload, logger) + + // revertInstructions tuple offset (Word 3) + revertOffset := new(big.Int).SetBytes(data[3*32 : 4*32]).Uint64() + + // txType (Word 4) + if w := readWord(data, 4); w != nil { + payload.TxType = uint(new(big.Int).SetBytes(w).Uint64()) + } + + // Decode revert recipient from tuple head + if revertOffset >= uint64(32*5) && revertOffset+64 <= uint64(len(data)) { + payload.RevertFundRecipient = ethcommon.BytesToAddress(data[revertOffset+12 : revertOffset+32]).Hex() + } + + // signatureData (Word 5 offset) + if w := readWord(data, 5); w != nil { + payload.VerificationData = decodeSignatureData(data, w, uint64(32*6)) + } + + finalizeEvent(event, payload, logger) +} + // decodeUniversalPayload takes a hex string and decodes it into UniversalPayload func decodeUniversalPayload(hexStr string) (*uetypes.UniversalPayload, error) { // Handle empty string case diff --git a/universalClient/chains/evm/rpc_client.go b/universalClient/chains/evm/rpc_client.go index 003cedba..b7c45d0a 100644 --- a/universalClient/chains/evm/rpc_client.go +++ b/universalClient/chains/evm/rpc_client.go @@ -190,6 +190,18 @@ func (rc *RPCClient) GetTransactionReceipt(ctx context.Context, txHash ethcommon return receipt, err } +// GetTransactionByHash returns a transaction by its hash. +func (rc *RPCClient) GetTransactionByHash(ctx context.Context, txHash ethcommon.Hash) (*types.Transaction, bool, error) { + var tx *types.Transaction + var isPending bool + err := rc.executeWithFailover(ctx, "get_transaction_by_hash", func(client *ethclient.Client) error { + var innerErr error + tx, isPending, innerErr = client.TransactionByHash(ctx, txHash) + return innerErr + }) + return tx, isPending, err +} + // GetPendingNonce returns the pending nonce (next nonce the chain will accept for this account). func (rc *RPCClient) GetPendingNonce(ctx context.Context, address ethcommon.Address) (uint64, error) { var nonce uint64 diff --git a/universalClient/chains/evm/tx_builder.go b/universalClient/chains/evm/tx_builder.go index 15a985b1..f61cb138 100644 --- a/universalClient/chains/evm/tx_builder.go +++ b/universalClient/chains/evm/tx_builder.go @@ -18,9 +18,6 @@ import ( uetypes "github.com/pushchain/push-chain-node/x/uexecutor/types" ) -// DefaultGasLimit is used when gas limit is not provided in the outbound event data -const DefaultGasLimit = 500000 - // RevertInstructions represents the struct for revert instruction in contracts // Matches: struct RevertInstructions { address revertRecipient; bytes revertMsg; } type RevertInstructions struct { @@ -28,12 +25,7 @@ type RevertInstructions struct { RevertMsg []byte } -// TxBuilder implements OutboundTxBuilder for EVM chains using Vault + Gateway contracts. -// -// Routing: -// - FUNDS, FUNDS_AND_PAYLOAD, PAYLOAD → Vault.finalizeUniversalTx -// - INBOUND_REVERT (native) → Gateway.revertUniversalTx -// - INBOUND_REVERT (ERC20) → Vault.revertUniversalTxToken +// TxBuilder implements OutboundTxBuilder for EVM chains using the Vault contract. type TxBuilder struct { rpcClient *RPCClient chainID string @@ -85,12 +77,10 @@ func NewTxBuilder( return tb, nil } - // GetOutboundSigningRequest creates a signing request from outbound event data func (tb *TxBuilder) GetOutboundSigningRequest( ctx context.Context, data *uetypes.OutboundCreatedEvent, - gasPrice *big.Int, nonce uint64, ) (*common.UnSignedOutboundTxReq, error) { if data == nil { @@ -102,11 +92,21 @@ func (tb *TxBuilder) GetOutboundSigningRequest( if data.DestinationChain == "" { return nil, fmt.Errorf("destinationChain is required") } - if gasPrice == nil { - return nil, fmt.Errorf("gasPrice is required") + + gasPrice := new(big.Int) + if data.GasPrice != "" { + if _, ok := gasPrice.SetString(data.GasPrice, 10); !ok { + return nil, fmt.Errorf("invalid gas price in event data: %s", data.GasPrice) + } + } + if gasPrice.Sign() == 0 { + return nil, fmt.Errorf("gas price is zero or missing in outbound event") } - gasLimit := parseGasLimit(data.GasLimit) + gasLimit, err := parseGasLimit(data.GasLimit) + if err != nil { + return nil, err + } amount := new(big.Int) amount, ok := amount.SetString(data.Amount, 10) @@ -128,14 +128,14 @@ func (tb *TxBuilder) GetOutboundSigningRequest( return nil, fmt.Errorf("failed to encode function call: %w", err) } - txValue, toAddress, err := tb.resolveTxParams(funcName, assetAddr, amount) - if err != nil { - return nil, fmt.Errorf("failed to resolve tx params: %w", err) + txValue := big.NewInt(0) + if assetAddr == (ethcommon.Address{}) { + txValue = amount } tx := types.NewTransaction( nonce, - toAddress, + tb.vaultAddress, txValue, gasLimit.Uint64(), gasPrice, @@ -148,7 +148,6 @@ func (tb *TxBuilder) GetOutboundSigningRequest( return &common.UnSignedOutboundTxReq{ SigningHash: txHash, Nonce: nonce, - GasPrice: gasPrice, }, nil } @@ -201,19 +200,27 @@ func (tb *TxBuilder) BroadcastOutboundSigningRequest( return "", fmt.Errorf("failed to encode function call: %w", err) } - txValue, toAddress, err := tb.resolveTxParams(funcName, assetAddr, amount) + txValue := big.NewInt(0) + if assetAddr == (ethcommon.Address{}) { + txValue = amount + } + + gasLimitForTx, err := parseGasLimit(data.GasLimit) if err != nil { - return "", fmt.Errorf("failed to resolve tx params: %w", err) + return "", fmt.Errorf("invalid gas limit: %w", err) } - gasLimitForTx := parseGasLimit(data.GasLimit) + gasPrice := new(big.Int) + if data.GasPrice != "" { + gasPrice.SetString(data.GasPrice, 10) + } tx := types.NewTransaction( req.Nonce, - toAddress, + tb.vaultAddress, txValue, gasLimitForTx.Uint64(), - req.GasPrice, + gasPrice, txData, ) @@ -256,52 +263,22 @@ func (tb *TxBuilder) VerifyBroadcastedTx(ctx context.Context, txHash string) (fo return true, receiptBlock, confs, uint8(receipt.Status), nil } -// resolveTxParams determines the transaction value and destination address. +// determineFunctionName determines the Vault function name based on TxType. // -// Routing: -// - finalizeUniversalTx → vault (value = amount for native) -// - revertUniversalTxToken → vault (value = 0, ERC20 only) -// - revertUniversalTx → gateway (value = amount, native only) -func (tb *TxBuilder) resolveTxParams(funcName string, assetAddr ethcommon.Address, amount *big.Int) (txValue *big.Int, toAddress ethcommon.Address, err error) { - isNative := assetAddr == (ethcommon.Address{}) - - switch funcName { - case "revertUniversalTx": - // Native revert goes to gateway — no vault needed - return amount, tb.gatewayAddress, nil - - case "finalizeUniversalTx": - if isNative { - return amount, tb.vaultAddress, nil - } - return big.NewInt(0), tb.vaultAddress, nil - - case "revertUniversalTxToken": - return big.NewInt(0), tb.vaultAddress, nil - - default: - return big.NewInt(0), tb.vaultAddress, nil - } -} - -// determineFunctionName determines the function name based on TxType and asset type. -// -// Routing: +// Routing (all on Vault): // - FUNDS, FUNDS_AND_PAYLOAD, PAYLOAD → Vault.finalizeUniversalTx -// - INBOUND_REVERT (native) → Gateway.revertUniversalTx -// - INBOUND_REVERT (ERC20) → Vault.revertUniversalTxToken +// - INBOUND_REVERT → Vault.revertUniversalTx +// - RESCUE_FUNDS → Vault.rescueFunds func (tb *TxBuilder) determineFunctionName(txType uetypes.TxType, assetAddr ethcommon.Address) string { - isNative := assetAddr == (ethcommon.Address{}) - switch txType { case uetypes.TxType_FUNDS, uetypes.TxType_FUNDS_AND_PAYLOAD, uetypes.TxType_PAYLOAD: return "finalizeUniversalTx" case uetypes.TxType_INBOUND_REVERT: - if isNative { - return "revertUniversalTx" - } - return "revertUniversalTxToken" + return "revertUniversalTx" + + case uetypes.TxType_RESCUE_FUNDS: + return "rescueFunds" default: return "finalizeUniversalTx" @@ -357,20 +334,21 @@ func (tb *TxBuilder) encodeFunctionCall( switch funcName { case "finalizeUniversalTx": - // finalizeUniversalTx(bytes32 txId, bytes32 universalTxId, address pushAccount, address token, address target, uint256 amount, bytes data) + // Vault: finalizeUniversalTx(bytes32 subTxId, bytes32 universalTxId, address pushAccount, address recipient, address token, uint256 amount, bytes data) arguments = abi.Arguments{ - {Type: bytes32Type}, // txId + {Type: bytes32Type}, // subTxId {Type: bytes32Type}, // universalTxId {Type: addressType}, // pushAccount + {Type: addressType}, // recipient {Type: addressType}, // token - {Type: addressType}, // target {Type: uint256Type}, // amount {Type: bytesType}, // data } - values = []interface{}{txID32, universalTxID, pushAccount, assetAddr, target, amount, payloadBytes} + values = []interface{}{txID32, universalTxID, pushAccount, target, assetAddr, amount, payloadBytes} - case "revertUniversalTx": - // Gateway: revertUniversalTx(bytes32 txId, bytes32 universalTxId, uint256 amount, RevertInstructions revertInstruction) + case "revertUniversalTx", "rescueFunds": + // Vault: revertUniversalTx(bytes32 subTxId, bytes32 universalTxId, address token, uint256 amount, RevertInstructions revertInstruction) + // Vault: rescueFunds(bytes32 subTxId, bytes32 universalTxId, address token, uint256 amount, RevertInstructions revertInstruction) revertMsgBytes, err := hex.DecodeString(removeHexPrefix(data.RevertMsg)) if err != nil { revertMsgBytes = []byte{} @@ -380,28 +358,7 @@ func (tb *TxBuilder) encodeFunctionCall( {Name: "revertMsg", Type: "bytes"}, }) arguments = abi.Arguments{ - {Type: bytes32Type}, // txId - {Type: bytes32Type}, // universalTxId - {Type: uint256Type}, // amount - {Type: revertInstructionType}, // revertInstruction - } - values = []interface{}{txID32, universalTxID, amount, RevertInstructions{ - RevertRecipient: target, - RevertMsg: revertMsgBytes, - }} - - case "revertUniversalTxToken": - // Vault: revertUniversalTxToken(bytes32 txId, bytes32 universalTxId, address token, uint256 amount, RevertInstructions revertInstruction) - revertMsgBytesToken, err := hex.DecodeString(removeHexPrefix(data.RevertMsg)) - if err != nil { - revertMsgBytesToken = []byte{} - } - revertInstructionType, _ := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ - {Name: "revertRecipient", Type: "address"}, - {Name: "revertMsg", Type: "bytes"}, - }) - arguments = abi.Arguments{ - {Type: bytes32Type}, // txId + {Type: bytes32Type}, // subTxId {Type: bytes32Type}, // universalTxId {Type: addressType}, // token {Type: uint256Type}, // amount @@ -409,7 +366,7 @@ func (tb *TxBuilder) encodeFunctionCall( } values = []interface{}{txID32, universalTxID, assetAddr, amount, RevertInstructions{ RevertRecipient: target, - RevertMsg: revertMsgBytesToken, + RevertMsg: revertMsgBytes, }} default: @@ -434,12 +391,12 @@ func (tb *TxBuilder) getFunctionSignature(funcName string, _ bool) string { return "finalizeUniversalTx(bytes32,bytes32,address,address,address,uint256,bytes)" case "revertUniversalTx": - // Gateway: revertUniversalTx(bytes32,bytes32,uint256,(address,bytes)) - return "revertUniversalTx(bytes32,bytes32,uint256,(address,bytes))" + // Vault: revertUniversalTx(bytes32,bytes32,address,uint256,(address,bytes)) + return "revertUniversalTx(bytes32,bytes32,address,uint256,(address,bytes))" - case "revertUniversalTxToken": - // Vault: revertUniversalTxToken(bytes32,bytes32,address,uint256,(address,bytes)) - return "revertUniversalTxToken(bytes32,bytes32,address,uint256,(address,bytes))" + case "rescueFunds": + // Vault: rescueFunds(bytes32,bytes32,address,uint256,(address,bytes)) + return "rescueFunds(bytes32,bytes32,address,uint256,(address,bytes))" default: return "" @@ -469,17 +426,17 @@ func parseTxType(txTypeStr string) (uetypes.TxType, error) { return uetypes.TxType_UNSPECIFIED_TX, fmt.Errorf("unknown tx type: %s", txTypeStr) } -// parseGasLimit parses gas limit string, returning default if empty or zero -func parseGasLimit(gasLimitStr string) *big.Int { +// parseGasLimit parses gas limit string, returning an error if empty or zero. +func parseGasLimit(gasLimitStr string) (*big.Int, error) { if gasLimitStr == "" || gasLimitStr == "0" { - return big.NewInt(DefaultGasLimit) + return nil, fmt.Errorf("gas limit is required in outbound event") } gasLimit := new(big.Int) gasLimit, ok := gasLimit.SetString(gasLimitStr, 10) if !ok { - return big.NewInt(DefaultGasLimit) + return nil, fmt.Errorf("invalid gas limit: %s", gasLimitStr) } - return gasLimit + return gasLimit, nil } // IsAlreadyExecuted returns false for EVM. EVM uses nonce-based replay protection, @@ -487,3 +444,28 @@ func parseGasLimit(gasLimitStr string) *big.Int { func (tb *TxBuilder) IsAlreadyExecuted(ctx context.Context, txID string) (bool, error) { return false, nil } + +// GetGasFeeUsed returns the gas fee used by a transaction on the EVM chain. +// Fetches the receipt for gasUsed and the transaction for gasPrice, then returns +// gasUsed * gasPrice as a decimal string. Returns "0" if not found. +func (tb *TxBuilder) GetGasFeeUsed(ctx context.Context, txHash string) (string, error) { + hash := ethcommon.HexToHash(txHash) + receipt, err := tb.rpcClient.GetTransactionReceipt(ctx, hash) + if err != nil { + return "0", nil + } + + tx, _, err := tb.rpcClient.GetTransactionByHash(ctx, hash) + if err != nil { + return "0", nil + } + + gasUsed := new(big.Int).SetUint64(receipt.GasUsed) + gasPrice := tx.GasPrice() + if gasPrice == nil || gasPrice.Sign() == 0 { + return "0", nil + } + + gasFeeUsed := new(big.Int).Mul(gasUsed, gasPrice) + return gasFeeUsed.String(), nil +} diff --git a/universalClient/chains/evm/tx_builder_test.go b/universalClient/chains/evm/tx_builder_test.go index b4f8d30b..0aa84069 100644 --- a/universalClient/chains/evm/tx_builder_test.go +++ b/universalClient/chains/evm/tx_builder_test.go @@ -1,9 +1,11 @@ package evm import ( + "context" "encoding/hex" "math/big" "testing" + "time" "github.com/ethereum/go-ethereum/accounts/abi" ethcommon "github.com/ethereum/go-ethereum/common" @@ -31,15 +33,11 @@ func newTestTxBuilder(t *testing.T) *TxBuilder { chainID: "eth_sepolia", chainIDInt: 11155111, gatewayAddress: gwAddr, - vaultAddress: vAddr, - logger: logger.With().Str("component", "evm_tx_builder").Logger(), + vaultAddress: vAddr, + logger: logger.With().Str("component", "evm_tx_builder").Logger(), } } -func TestDefaultGasLimit(t *testing.T) { - assert.Equal(t, int64(500000), int64(DefaultGasLimit)) -} - func TestRevertInstructionsStruct(t *testing.T) { recipient := ethcommon.HexToAddress("0x1234567890123456789012345678901234567890") revertMsg := []byte("test revert message") @@ -93,16 +91,16 @@ func TestGetFunctionSignature(t *testing.T) { expected: "finalizeUniversalTx(bytes32,bytes32,address,address,address,uint256,bytes)", }, { - name: "revertUniversalTx native", + name: "revertUniversalTx", funcName: "revertUniversalTx", isNative: true, - expected: "revertUniversalTx(bytes32,bytes32,uint256,(address,bytes))", + expected: "revertUniversalTx(bytes32,bytes32,address,uint256,(address,bytes))", }, { - name: "revertUniversalTxToken ERC20", - funcName: "revertUniversalTxToken", + name: "rescueFunds", + funcName: "rescueFunds", isNative: false, - expected: "revertUniversalTxToken(bytes32,bytes32,address,uint256,(address,bytes))", + expected: "rescueFunds(bytes32,bytes32,address,uint256,(address,bytes))", }, } @@ -119,8 +117,8 @@ func TestFunctionSelectorGeneration(t *testing.T) { signature string }{ {"finalizeUniversalTx(bytes32,bytes32,address,address,address,uint256,bytes)"}, - {"revertUniversalTx(bytes32,bytes32,uint256,(address,bytes))"}, - {"revertUniversalTxToken(bytes32,bytes32,address,uint256,(address,bytes))"}, + {"revertUniversalTx(bytes32,bytes32,address,uint256,(address,bytes))"}, + {"rescueFunds(bytes32,bytes32,address,uint256,(address,bytes))"}, } for _, tt := range tests { @@ -150,7 +148,7 @@ func TestDetermineFunctionName(t *testing.T) { {"PAYLOAD native", uetypes.TxType_PAYLOAD, nativeAsset, "finalizeUniversalTx"}, {"PAYLOAD ERC20", uetypes.TxType_PAYLOAD, erc20Asset, "finalizeUniversalTx"}, {"INBOUND_REVERT native", uetypes.TxType_INBOUND_REVERT, nativeAsset, "revertUniversalTx"}, - {"INBOUND_REVERT ERC20", uetypes.TxType_INBOUND_REVERT, erc20Asset, "revertUniversalTxToken"}, + {"INBOUND_REVERT ERC20", uetypes.TxType_INBOUND_REVERT, erc20Asset, "revertUniversalTx"}, } for _, tt := range tests { @@ -161,60 +159,6 @@ func TestDetermineFunctionName(t *testing.T) { } } -func TestResolveTxParams(t *testing.T) { - builder := newTestTxBuilder(t) - - nativeAsset := ethcommon.Address{} - erc20Asset := ethcommon.HexToAddress("0x2222222222222222222222222222222222222222") - amount := big.NewInt(1000000000000000000) - - tests := []struct { - name string - funcName string - assetAddr ethcommon.Address - expectedTo ethcommon.Address - expectedValue *big.Int - }{ - { - name: "finalizeUniversalTx native → vault with value", - funcName: "finalizeUniversalTx", - assetAddr: nativeAsset, - expectedTo: ethcommon.HexToAddress(testVaultAddress), - expectedValue: amount, - }, - { - name: "finalizeUniversalTx ERC20 → vault no value", - funcName: "finalizeUniversalTx", - assetAddr: erc20Asset, - expectedTo: ethcommon.HexToAddress(testVaultAddress), - expectedValue: big.NewInt(0), - }, - { - name: "revertUniversalTx native → gateway with value", - funcName: "revertUniversalTx", - assetAddr: nativeAsset, - expectedTo: ethcommon.HexToAddress("0x1234567890123456789012345678901234567890"), - expectedValue: amount, - }, - { - name: "revertUniversalTxToken ERC20 → vault no value", - funcName: "revertUniversalTxToken", - assetAddr: erc20Asset, - expectedTo: ethcommon.HexToAddress(testVaultAddress), - expectedValue: big.NewInt(0), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - txValue, toAddr, err := builder.resolveTxParams(tt.funcName, tt.assetAddr, amount) - require.NoError(t, err) - assert.Equal(t, tt.expectedTo, toAddr) - assert.Equal(t, tt.expectedValue.Int64(), txValue.Int64()) - }) - } -} - func TestEncodeFunctionCallAllFunctions(t *testing.T) { builder := newTestTxBuilder(t) @@ -268,14 +212,28 @@ func TestEncodeFunctionCallAllFunctions(t *testing.T) { funcName: "revertUniversalTx", assetAddr: nativeAsset, txType: uetypes.TxType_INBOUND_REVERT, - expectedSignature: "revertUniversalTx(bytes32,bytes32,uint256,(address,bytes))", + expectedSignature: "revertUniversalTx(bytes32,bytes32,address,uint256,(address,bytes))", + }, + { + name: "revertUniversalTx ERC20", + funcName: "revertUniversalTx", + assetAddr: erc20Asset, + txType: uetypes.TxType_INBOUND_REVERT, + expectedSignature: "revertUniversalTx(bytes32,bytes32,address,uint256,(address,bytes))", + }, + { + name: "rescueFunds native", + funcName: "rescueFunds", + assetAddr: nativeAsset, + txType: uetypes.TxType_INBOUND_REVERT, + expectedSignature: "rescueFunds(bytes32,bytes32,address,uint256,(address,bytes))", }, { - name: "revertUniversalTxToken ERC20", - funcName: "revertUniversalTxToken", + name: "rescueFunds ERC20", + funcName: "rescueFunds", assetAddr: erc20Asset, txType: uetypes.TxType_INBOUND_REVERT, - expectedSignature: "revertUniversalTxToken(bytes32,bytes32,address,uint256,(address,bytes))", + expectedSignature: "rescueFunds(bytes32,bytes32,address,uint256,(address,bytes))", }, { name: "unknown function", @@ -341,7 +299,7 @@ func TestEncodeFunctionCallRevertInstructionsEncoding(t *testing.T) { require.NoError(t, err) assert.NotEmpty(t, encoded) - expectedSignature := "revertUniversalTx(bytes32,bytes32,uint256,(address,bytes))" + expectedSignature := "revertUniversalTx(bytes32,bytes32,address,uint256,(address,bytes))" expectedSelector := crypto.Keccak256([]byte(expectedSignature))[:4] assert.Equal(t, expectedSelector, encoded[:4]) }) @@ -519,24 +477,28 @@ func TestParseTxType(t *testing.T) { } func TestParseGasLimit(t *testing.T) { - tests := []struct { - name string - input string - expected int64 - }{ - {"empty uses default", "", DefaultGasLimit}, - {"zero uses default", "0", DefaultGasLimit}, - {"valid gas limit", "100000", 100000}, - {"large gas limit", "1000000", 1000000}, - {"invalid uses default", "not-a-number", DefaultGasLimit}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := parseGasLimit(tt.input) - assert.Equal(t, tt.expected, result.Int64()) - }) - } + t.Run("empty returns error", func(t *testing.T) { + _, err := parseGasLimit("") + assert.Error(t, err) + }) + t.Run("zero returns error", func(t *testing.T) { + _, err := parseGasLimit("0") + assert.Error(t, err) + }) + t.Run("valid gas limit", func(t *testing.T) { + result, err := parseGasLimit("100000") + assert.NoError(t, err) + assert.Equal(t, int64(100000), result.Int64()) + }) + t.Run("large gas limit", func(t *testing.T) { + result, err := parseGasLimit("1000000") + assert.NoError(t, err) + assert.Equal(t, int64(1000000), result.Int64()) + }) + t.Run("invalid returns error", func(t *testing.T) { + _, err := parseGasLimit("not-a-number") + assert.Error(t, err) + }) } // TestFinalizeUniversalTxUnifiedEncoding verifies that finalizeUniversalTx is used @@ -587,453 +549,260 @@ func TestFinalizeUniversalTxUnifiedEncoding(t *testing.T) { } // ============================================================================= -// Sepolia V2 Simulation Tests +// BSC Testnet Simulation Tests // -// These tests simulate contract calls (eth_call) against the live V2 gateway -// and vault contracts on Sepolia. They verify that the encoded calldata is +// These tests simulate contract calls (eth_call) against the live Vault +// contract on BSC testnet. They verify that the encoded calldata is // accepted by the on-chain contracts. // // Prerequisites: -// 1. sepoliaV2SimulateFrom must have TSS_ROLE on both gateway and vault +// 1. bscSimulateFrom must have TSS_ROLE on the vault // 2. Contracts must not be paused // 3. For ERC20 tests, the vault must have sufficient token balance -// 4. The gateway's VAULT() must return a valid vault address // // These tests are skipped in -short mode and when RPC connection fails. // ============================================================================= -// const ( -// sepoliaV2GatewayAddress = "0x4DCab975cDe839632db6695e2e936A29ce3e325E" -// sepoliaV2SimulateFrom = "0x05d7386fb3d7cb00e0cfac5af3b2eff6bf37c5f1" // TSS Address (has TSS_ROLE) -// sepoliaV2OriginCaller = "0x35B84d6848D16415177c64D64504663b998A6ab4" // Push account / origin caller -// sepoliaV2RPCURL = "https://rpc.sepolia.org" -// sepoliaV2ChainID = int64(11155111) -// sepoliaV2USDT = "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06" // USDT on Sepolia -// sepoliaV2NativeAsset = "0x0000000000000000000000000000000000000000" -// ) - -// // setupSepoliaV2Simulation creates RPCClient and TxBuilder for Sepolia V2 simulation tests. -// // Skips the test if -short is passed or RPC connection fails. -// func setupSepoliaV2Simulation(t *testing.T) (*RPCClient, *TxBuilder) { -// t.Helper() -// if testing.Short() { -// t.Skip("skipping simulation test in short mode") -// } - -// logger := zerolog.Nop() -// rpcClient, err := NewRPCClient([]string{sepoliaV2RPCURL}, sepoliaV2ChainID, logger) -// if err != nil { -// t.Skipf("skipping simulation test: failed to connect to Sepolia RPC: %v", err) -// } - -// builder, err := NewTxBuilder(rpcClient, "eip155:11155111", sepoliaV2ChainID, sepoliaV2GatewayAddress, logger) -// if err != nil { -// t.Skipf("skipping simulation test: failed to create TxBuilder: %v", err) -// } - -// // Log the vault address fetched from gateway -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err, "vault address should be available after init") -// t.Logf("V2 Gateway: %s", sepoliaV2GatewayAddress) -// t.Logf("V2 Vault (from VAULT()): %s", vaultAddr.Hex()) -// t.Logf("V2 TSS: %s", sepoliaV2SimulateFrom) - -// return rpcClient, builder -// } - -// // encodeMulticallPayload ABI-encodes a Multicall[] array for use as the `data` param in finalizeUniversalTx. -// // The CEA contract expects: abi.encode(Multicall[]) where Multicall is (address to, uint256 value, bytes data). -// // Pass nil or empty slice for an empty multicall (no-op / funds-only). -// func encodeMulticallPayload(t *testing.T, calls []struct { -// To ethcommon.Address -// Value *big.Int -// Data []byte -// }) string { -// t.Helper() - -// // ABI type for Multicall[] = tuple(address,uint256,bytes)[] -// multicallArrayType, err := abi.NewType("tuple[]", "", []abi.ArgumentMarshaling{ -// {Name: "to", Type: "address"}, -// {Name: "value", Type: "uint256"}, -// {Name: "data", Type: "bytes"}, -// }) -// require.NoError(t, err) - -// type Multicall struct { -// To ethcommon.Address -// Value *big.Int -// Data []byte -// } - -// var multicalls []Multicall -// for _, c := range calls { -// multicalls = append(multicalls, Multicall{To: c.To, Value: c.Value, Data: c.Data}) -// } -// if multicalls == nil { -// multicalls = []Multicall{} -// } - -// args := abi.Arguments{{Type: multicallArrayType}} -// encoded, err := args.Pack(multicalls) -// require.NoError(t, err) - -// return "0x" + hex.EncodeToString(encoded) -// } - -// // newSepoliaV2SimulationOutbound creates a full OutboundCreatedEvent for V2 simulation tests. -// // Uses unique txID per test to avoid "PayloadExecuted" revert from duplicate txIDs. -// // Sender is used as pushAccount parameter (origin caller), NOT as the from address. -// func newSepoliaV2SimulationOutbound(t *testing.T, amount, assetAddr, payload, revertMsg string) *uetypes.OutboundCreatedEvent { -// t.Helper() -// // Use test name hash for unique txID to avoid isExecuted collision -// txIDBytes := crypto.Keccak256([]byte(t.Name() + time.Now().String())) -// universalTxIDBytes := crypto.Keccak256([]byte("utx-" + t.Name() + time.Now().String())) - -// return &uetypes.OutboundCreatedEvent{ -// TxID: "0x" + hex.EncodeToString(txIDBytes), -// UniversalTxId: "0x" + hex.EncodeToString(universalTxIDBytes), -// Sender: sepoliaV2OriginCaller, -// Recipient: "0x28F1C7B4596D9db14f85c04DcBd867Bf4b14b811", -// Amount: amount, -// AssetAddr: assetAddr, -// Payload: payload, -// RevertMsg: revertMsg, -// } -// } - -// // TestSimulateV2_FetchVaultFromGateway verifies that VAULT() can be read from the gateway -// func TestSimulateV2_FetchVaultFromGateway(t *testing.T) { -// if testing.Short() { -// t.Skip("skipping simulation test in short mode") -// } - -// logger := zerolog.Nop() -// rpcClient, err := NewRPCClient([]string{sepoliaV2RPCURL}, sepoliaV2ChainID, logger) -// if err != nil { -// t.Skipf("skipping: failed to connect to Sepolia RPC: %v", err) -// } -// defer rpcClient.Close() - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// gwAddr := ethcommon.HexToAddress(sepoliaV2GatewayAddress) -// result, err := rpcClient.CallContract(ctx, gwAddr, vaultCallSelector, nil) -// require.NoError(t, err, "VAULT() call should succeed") -// require.True(t, len(result) >= 32, "VAULT() should return at least 32 bytes") - -// vaultAddr := ethcommon.BytesToAddress(result[12:32]) -// assert.NotEqual(t, ethcommon.Address{}, vaultAddr, "VAULT() should not return zero address") -// t.Logf("VAULT() returned: %s", vaultAddr.Hex()) -// } - -// // ---------- 1. Native Revert (Gateway) ---------- - -// // TestSimulateV2_RevertUniversalTx_Native simulates native revertUniversalTx on Sepolia gateway -// func TestSimulateV2_RevertUniversalTx_Native(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// revertMsg := hex.EncodeToString([]byte("test revert")) -// data := newSepoliaV2SimulationOutbound(t, "1000000000000000", sepoliaV2NativeAsset, "0x", revertMsg) // 0.001 ETH -// amount := new(big.Int) -// amount.SetString(data.Amount, 10) -// assetAddr := ethcommon.HexToAddress(data.AssetAddr) - -// calldata, err := builder.encodeFunctionCall("revertUniversalTx", data, amount, assetAddr, uetypes.TxType_INBOUND_REVERT) -// require.NoError(t, err) - -// t.Logf("revertUniversalTx (native) calldata: 0x%s", hex.EncodeToString(calldata)) -// t.Logf("from (TSS): %s, gateway: %s, value: %s", sepoliaV2SimulateFrom, sepoliaV2GatewayAddress, amount.String()) - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// from := ethcommon.HexToAddress(sepoliaV2SimulateFrom) -// gateway := ethcommon.HexToAddress(sepoliaV2GatewayAddress) -// result, err := rpcClient.CallContractWithFrom(ctx, from, gateway, calldata, amount, nil) -// if err != nil { -// t.Logf("Simulation failed: %v", err) -// t.Logf("Verify: 1) TSS has onlyTSS on gateway, 2) gateway not paused, 3) txID not already executed") -// } -// require.NoError(t, err, "simulate revertUniversalTx (native) should pass") -// require.NotNil(t, result) -// } - -// // ---------- 2. Token Revert (Vault) ---------- - -// // TestSimulateV2_RevertUniversalTxToken_ERC20 simulates ERC20 revertUniversalTxToken on Sepolia vault -// func TestSimulateV2_RevertUniversalTxToken_ERC20(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// revertMsg := hex.EncodeToString([]byte("test revert token")) -// data := newSepoliaV2SimulationOutbound(t, "1000000", sepoliaV2USDT, "0x", revertMsg) // 1 USDT (6 decimals) -// amount := new(big.Int) -// amount.SetString(data.Amount, 10) -// assetAddr := ethcommon.HexToAddress(data.AssetAddr) - -// calldata, err := builder.encodeFunctionCall("revertUniversalTxToken", data, amount, assetAddr, uetypes.TxType_INBOUND_REVERT) -// require.NoError(t, err) - -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err) - -// t.Logf("revertUniversalTxToken (ERC20) calldata: 0x%s", hex.EncodeToString(calldata)) -// t.Logf("from (TSS): %s, vault: %s, token: %s", sepoliaV2SimulateFrom, vaultAddr.Hex(), sepoliaV2USDT) - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// from := ethcommon.HexToAddress(sepoliaV2SimulateFrom) -// result, err := rpcClient.CallContractWithFrom(ctx, from, vaultAddr, calldata, big.NewInt(0), nil) -// if err != nil { -// t.Logf("Simulation failed: %v", err) -// t.Logf("Verify: 1) TSS has TSS_ROLE on vault, 2) vault has token balance, 3) token is supported") -// } -// require.NoError(t, err, "simulate revertUniversalTxToken (ERC20) should pass") -// require.NotNil(t, result) -// } - -// // ---------- 3. Native FinalizeUniversalTx — no payload (Vault) ---------- - -// // TestSimulateV2_FinalizeUniversalTx_Native simulates native finalizeUniversalTx (funds only, no payload) -// func TestSimulateV2_FinalizeUniversalTx_Native(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// emptyMulticall := encodeMulticallPayload(t, nil) -// data := newSepoliaV2SimulationOutbound(t, "10000000000", sepoliaV2NativeAsset, emptyMulticall, "") // ~10 gwei worth of ETH, no payload -// amount := new(big.Int) -// amount.SetString(data.Amount, 10) -// assetAddr := ethcommon.HexToAddress(data.AssetAddr) - -// calldata, err := builder.encodeFunctionCall("finalizeUniversalTx", data, amount, assetAddr, uetypes.TxType_FUNDS) -// require.NoError(t, err) - -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err) - -// t.Logf("finalizeUniversalTx (native, no payload) calldata: 0x%s", hex.EncodeToString(calldata)) -// t.Logf("from (TSS): %s, vault: %s, value: %s", sepoliaV2SimulateFrom, vaultAddr.Hex(), amount.String()) - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// from := ethcommon.HexToAddress(sepoliaV2SimulateFrom) -// result, err := rpcClient.CallContractWithFrom(ctx, from, vaultAddr, calldata, amount, nil) -// if err != nil { -// t.Logf("Simulation failed: %v", err) -// t.Logf("Verify: 1) TSS has TSS_ROLE on vault, 2) vault not paused, 3) txID not already executed") -// } -// require.NoError(t, err, "simulate finalizeUniversalTx (native, no payload) should pass") -// require.NotNil(t, result) -// } - -// // ---------- 4. ERC20 FinalizeUniversalTx — no payload (Vault) ---------- - -// // TestSimulateV2_FinalizeUniversalTx_ERC20 simulates ERC20 finalizeUniversalTx (funds only, no payload) -// func TestSimulateV2_FinalizeUniversalTx_ERC20(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// emptyMulticall := encodeMulticallPayload(t, nil) -// data := newSepoliaV2SimulationOutbound(t, "1000000", sepoliaV2USDT, emptyMulticall, "") // 1 USDT (6 decimals), no payload -// amount := new(big.Int) -// amount.SetString(data.Amount, 10) -// assetAddr := ethcommon.HexToAddress(data.AssetAddr) - -// calldata, err := builder.encodeFunctionCall("finalizeUniversalTx", data, amount, assetAddr, uetypes.TxType_FUNDS) -// require.NoError(t, err) - -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err) - -// t.Logf("finalizeUniversalTx (ERC20, no payload) calldata: 0x%s", hex.EncodeToString(calldata)) -// t.Logf("from (TSS): %s, vault: %s, token: %s", sepoliaV2SimulateFrom, vaultAddr.Hex(), sepoliaV2USDT) - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// from := ethcommon.HexToAddress(sepoliaV2SimulateFrom) -// result, err := rpcClient.CallContractWithFrom(ctx, from, vaultAddr, calldata, big.NewInt(0), nil) -// if err != nil { -// t.Logf("Simulation failed: %v", err) -// t.Logf("Verify: 1) TSS has TSS_ROLE on vault, 2) vault has token balance, 3) token is supported") -// } -// require.NoError(t, err, "simulate finalizeUniversalTx (ERC20, no payload) should pass") -// require.NotNil(t, result) -// } - -// // ---------- 5. Native FinalizeUniversalTx — with payload (Vault) ---------- - -// // TestSimulateV2_FinalizeUniversalTx_NativeWithPayload simulates native finalizeUniversalTx with funds + payload -// func TestSimulateV2_FinalizeUniversalTx_NativeWithPayload(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// // Multicall: send 0.001 ETH to recipient -// recipient := ethcommon.HexToAddress("0x28F1C7B4596D9db14f85c04DcBd867Bf4b14b811") -// nativeMulticall := encodeMulticallPayload(t, []struct { -// To ethcommon.Address -// Value *big.Int -// Data []byte -// }{{To: recipient, Value: big.NewInt(1000000000000000), Data: nil}}) -// data := newSepoliaV2SimulationOutbound(t, "1000000000000000", sepoliaV2NativeAsset, nativeMulticall, "") // 0.001 ETH + payload -// amount := new(big.Int) -// amount.SetString(data.Amount, 10) -// assetAddr := ethcommon.HexToAddress(data.AssetAddr) - -// calldata, err := builder.encodeFunctionCall("finalizeUniversalTx", data, amount, assetAddr, uetypes.TxType_FUNDS_AND_PAYLOAD) -// require.NoError(t, err) - -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err) - -// t.Logf("finalizeUniversalTx (native+payload) calldata: 0x%s", hex.EncodeToString(calldata)) -// t.Logf("from (TSS): %s, vault: %s, value: %s", sepoliaV2SimulateFrom, vaultAddr.Hex(), amount.String()) - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// from := ethcommon.HexToAddress(sepoliaV2SimulateFrom) -// result, err := rpcClient.CallContractWithFrom(ctx, from, vaultAddr, calldata, amount, nil) -// if err != nil { -// t.Logf("Simulation failed: %v", err) -// } -// require.NoError(t, err, "simulate finalizeUniversalTx (native+payload) should pass") -// require.NotNil(t, result) -// } - -// // ---------- 6. ERC20 FinalizeUniversalTx — with payload (Vault) ---------- - -// // TestSimulateV2_FinalizeUniversalTx_ERC20WithPayload simulates ERC20 finalizeUniversalTx with funds + payload -// func TestSimulateV2_FinalizeUniversalTx_ERC20WithPayload(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// // Multicall: transfer 1 USDT to recipient via ERC20.transfer -// erc20Recipient := ethcommon.HexToAddress("0x28F1C7B4596D9db14f85c04DcBd867Bf4b14b811") -// transferSel := crypto.Keccak256([]byte("transfer(address,uint256)"))[:4] -// transferArgs := abi.Arguments{ -// {Type: func() abi.Type { t, _ := abi.NewType("address", "", nil); return t }()}, -// {Type: func() abi.Type { t, _ := abi.NewType("uint256", "", nil); return t }()}, -// } -// transferData, err := transferArgs.Pack(erc20Recipient, big.NewInt(1000000)) // 1 USDT (6 decimals) -// require.NoError(t, err) -// erc20TransferCalldata := append(transferSel, transferData...) -// usdtAddr := ethcommon.HexToAddress(sepoliaV2USDT) -// erc20Multicall := encodeMulticallPayload(t, []struct { -// To ethcommon.Address -// Value *big.Int -// Data []byte -// }{{To: usdtAddr, Value: big.NewInt(0), Data: erc20TransferCalldata}}) -// data := newSepoliaV2SimulationOutbound(t, "1000000", sepoliaV2USDT, erc20Multicall, "") // 1 USDT (6 decimals) + payload -// amount := new(big.Int) -// amount.SetString(data.Amount, 10) -// assetAddr := ethcommon.HexToAddress(data.AssetAddr) - -// calldata, err := builder.encodeFunctionCall("finalizeUniversalTx", data, amount, assetAddr, uetypes.TxType_FUNDS_AND_PAYLOAD) -// require.NoError(t, err) - -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err) - -// t.Logf("finalizeUniversalTx (ERC20+payload) calldata: 0x%s", hex.EncodeToString(calldata)) -// t.Logf("from (TSS): %s, vault: %s, token: %s", sepoliaV2SimulateFrom, vaultAddr.Hex(), sepoliaV2USDT) - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// from := ethcommon.HexToAddress(sepoliaV2SimulateFrom) -// result, err := rpcClient.CallContractWithFrom(ctx, from, vaultAddr, calldata, big.NewInt(0), nil) -// if err != nil { -// t.Logf("Simulation failed: %v", err) -// } -// require.NoError(t, err, "simulate finalizeUniversalTx (ERC20+payload) should pass") -// require.NotNil(t, result) -// } - -// // ---------- 7. FinalizeUniversalTx — payload only, no funds (Vault) ---------- - -// // TestSimulateV2_FinalizeUniversalTx_PayloadOnly simulates finalizeUniversalTx with only payload (no funds) -// // Uses native asset (zero address) with zero amount — pure contract execution via CEA -// func TestSimulateV2_FinalizeUniversalTx_PayloadOnly(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// // amount=0, native asset, non-empty payload → PAYLOAD tx type -// // Multicall: simple call to recipient with no value (pure execution) -// payloadRecipient := ethcommon.HexToAddress("0x28F1C7B4596D9db14f85c04DcBd867Bf4b14b811") -// payloadOnlyMulticall := encodeMulticallPayload(t, []struct { -// To ethcommon.Address -// Value *big.Int -// Data []byte -// }{{To: payloadRecipient, Value: big.NewInt(0), Data: []byte{0xde, 0xad, 0xbe, 0xef}}}) -// data := newSepoliaV2SimulationOutbound(t, "0", sepoliaV2NativeAsset, payloadOnlyMulticall, "") -// amount := big.NewInt(0) -// assetAddr := ethcommon.HexToAddress(data.AssetAddr) - -// calldata, err := builder.encodeFunctionCall("finalizeUniversalTx", data, amount, assetAddr, uetypes.TxType_PAYLOAD) -// require.NoError(t, err) - -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err) - -// t.Logf("finalizeUniversalTx (payload only) calldata: 0x%s", hex.EncodeToString(calldata)) -// t.Logf("from (TSS): %s, vault: %s, value: 0", sepoliaV2SimulateFrom, vaultAddr.Hex()) - -// ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) -// defer cancel() - -// from := ethcommon.HexToAddress(sepoliaV2SimulateFrom) -// result, err := rpcClient.CallContractWithFrom(ctx, from, vaultAddr, calldata, big.NewInt(0), nil) -// if err != nil { -// t.Logf("Simulation failed: %v", err) -// } -// require.NoError(t, err, "simulate finalizeUniversalTx (payload only) should pass") -// require.NotNil(t, result) -// } - -// // ---------- Routing verification ---------- - -// // TestSimulateV2_FullFlow_ResolveTxParams verifies that resolveTxParams routes to the correct contract -// func TestSimulateV2_FullFlow_ResolveTxParams(t *testing.T) { -// rpcClient, builder := setupSepoliaV2Simulation(t) -// defer rpcClient.Close() - -// vaultAddr, err := builder.getVaultAddress() -// require.NoError(t, err) -// gatewayAddr := ethcommon.HexToAddress(sepoliaV2GatewayAddress) - -// amount := big.NewInt(1000000000000000) // 0.001 ETH -// nativeAsset := ethcommon.Address{} -// erc20Asset := ethcommon.HexToAddress(sepoliaV2USDT) - -// tests := []struct { -// name string -// funcName string -// assetAddr ethcommon.Address -// expectedTo ethcommon.Address -// expectVal bool // true if txValue should equal amount -// }{ -// {"finalizeUniversalTx native → vault", "finalizeUniversalTx", nativeAsset, vaultAddr, true}, -// {"finalizeUniversalTx ERC20 → vault", "finalizeUniversalTx", erc20Asset, vaultAddr, false}, -// {"revertUniversalTx native → gateway", "revertUniversalTx", nativeAsset, gatewayAddr, true}, -// {"revertUniversalTxToken ERC20 → vault", "revertUniversalTxToken", erc20Asset, vaultAddr, false}, -// } - -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// txValue, toAddr, err := builder.resolveTxParams(tt.funcName, tt.assetAddr, amount) -// require.NoError(t, err) -// assert.Equal(t, tt.expectedTo, toAddr, "should route to correct contract") -// if tt.expectVal { -// assert.Equal(t, amount.Int64(), txValue.Int64(), "native calls should have value=amount") -// } else { -// assert.Equal(t, int64(0), txValue.Int64(), "ERC20 calls should have value=0") -// } -// t.Logf("%s → to=%s value=%s", tt.funcName, toAddr.Hex(), txValue.String()) -// }) -// } -// } +const ( + bscGatewayAddress = "0x44aFFC61983F4348DdddB886349eb992C061EaC0" + bscVaultAddress = "0xE52AC4f8DD3e0263bDF748F3390cdFA1f02be881" + bscSimulateFrom = "0x05D7386FB3D7cB00e0CFAc5Af3B2EFF6BF37c5f1" // TSS Address (has TSS_ROLE) + bscPushAccount = "0x35B84d6848D16415177c64D64504663b998A6ab4" // Push account / origin caller + bscRPCURL = "https://bsc-testnet-rpc.publicnode.com" + bscChainID = int64(97) + bscUSDT = "0xBC14F348BC9667be46b35Edc9B68653d86013DC5" + bscNativeAsset = "0x0000000000000000000000000000000000000000" +) + +// setupBSCSimulation creates RPCClient and TxBuilder for BSC testnet simulation tests. +func setupBSCSimulation(t *testing.T) (*RPCClient, *TxBuilder) { + t.Helper() + t.Skip("skipping simulation tests") // DELIBERATELY SKIPPING SIMULATION TESTS + logger := zerolog.Nop() + rpcClient, err := NewRPCClient([]string{bscRPCURL}, bscChainID, logger) + if err != nil { + t.Skipf("skipping simulation test: failed to connect to BSC RPC: %v", err) + } + + vaultAddr := ethcommon.HexToAddress(bscVaultAddress) + builder, err := NewTxBuilder(rpcClient, "eip155:97", bscChainID, bscGatewayAddress, vaultAddr, logger) + if err != nil { + t.Skipf("skipping simulation test: failed to create TxBuilder: %v", err) + } + + t.Logf("BSC Gateway: %s", bscGatewayAddress) + t.Logf("BSC Vault: %s", bscVaultAddress) + t.Logf("BSC TSS: %s", bscSimulateFrom) + + return rpcClient, builder +} + +// encodeMulticallPayload ABI-encodes a Multicall[] array for use as the `data` param in finalizeUniversalTx. +func encodeMulticallPayload(t *testing.T, calls []struct { + To ethcommon.Address + Value *big.Int + Data []byte +}) string { + t.Helper() + + multicallArrayType, err := abi.NewType("tuple[]", "", []abi.ArgumentMarshaling{ + {Name: "to", Type: "address"}, + {Name: "value", Type: "uint256"}, + {Name: "data", Type: "bytes"}, + }) + require.NoError(t, err) + + type Multicall struct { + To ethcommon.Address + Value *big.Int + Data []byte + } + + var multicalls []Multicall + for _, c := range calls { + multicalls = append(multicalls, Multicall{To: c.To, Value: c.Value, Data: c.Data}) + } + if multicalls == nil { + multicalls = []Multicall{} + } + + args := abi.Arguments{{Type: multicallArrayType}} + encoded, err := args.Pack(multicalls) + require.NoError(t, err) + + return "0x" + hex.EncodeToString(encoded) +} + +// newBSCSimulationOutbound creates a full OutboundCreatedEvent for BSC simulation tests. +func newBSCSimulationOutbound(t *testing.T, amount, assetAddr, payload, revertMsg string) *uetypes.OutboundCreatedEvent { + t.Helper() + txIDBytes := crypto.Keccak256([]byte(t.Name() + time.Now().String())) + universalTxIDBytes := crypto.Keccak256([]byte("utx-" + t.Name() + time.Now().String())) + + return &uetypes.OutboundCreatedEvent{ + TxID: "0x" + hex.EncodeToString(txIDBytes), + UniversalTxId: "0x" + hex.EncodeToString(universalTxIDBytes), + Sender: bscPushAccount, + Recipient: "0x28F1C7B4596D9db14f85c04DcBd867Bf4b14b811", + Amount: amount, + AssetAddr: assetAddr, + Payload: payload, + RevertMsg: revertMsg, + } +} + +// simulateOnVault is a helper that encodes a function call and simulates it via eth_call on the vault. +func simulateOnVault(t *testing.T, rpcClient *RPCClient, builder *TxBuilder, funcName string, data *uetypes.OutboundCreatedEvent, txType uetypes.TxType) { + t.Helper() + + amount := new(big.Int) + amount.SetString(data.Amount, 10) + assetAddr := ethcommon.HexToAddress(data.AssetAddr) + + calldata, err := builder.encodeFunctionCall(funcName, data, amount, assetAddr, txType) + require.NoError(t, err) + + txValue := big.NewInt(0) + if assetAddr == (ethcommon.Address{}) { + txValue = amount + } + + t.Logf("%s calldata: 0x%s", funcName, hex.EncodeToString(calldata)) + t.Logf("from (TSS): %s, vault: %s, value: %s", bscSimulateFrom, bscVaultAddress, txValue.String()) + + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + from := ethcommon.HexToAddress(bscSimulateFrom) + vault := ethcommon.HexToAddress(bscVaultAddress) + result, err := rpcClient.CallContractWithFrom(ctx, from, vault, calldata, txValue, nil) + require.NoError(t, err, "simulate %s should pass", funcName) + require.NotNil(t, result) +} + +// ---------- 1. Fetch Vault from Gateway ---------- + +func TestSimulateBSC_FetchVaultFromGateway(t *testing.T) { + if testing.Short() { + t.Skip("skipping simulation test in short mode") + } + + logger := zerolog.Nop() + rpcClient, err := NewRPCClient([]string{bscRPCURL}, bscChainID, logger) + if err != nil { + t.Skipf("skipping: failed to connect to BSC RPC: %v", err) + } + defer rpcClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + gwAddr := ethcommon.HexToAddress(bscGatewayAddress) + vaultCallSelector := crypto.Keccak256([]byte("VAULT()"))[:4] + result, err := rpcClient.CallContract(ctx, gwAddr, vaultCallSelector, nil) + require.NoError(t, err, "VAULT() call should succeed") + require.True(t, len(result) >= 32, "VAULT() should return at least 32 bytes") + + vaultAddr := ethcommon.BytesToAddress(result[12:32]) + assert.NotEqual(t, ethcommon.Address{}, vaultAddr, "VAULT() should not return zero address") + assert.Equal(t, ethcommon.HexToAddress(bscVaultAddress), vaultAddr, "VAULT() should match expected vault address") + t.Logf("VAULT() returned: %s", vaultAddr.Hex()) +} + +// ---------- 2. Native Revert (Vault) ---------- + +func TestSimulateBSC_RevertUniversalTx_Native(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + revertMsg := hex.EncodeToString([]byte("test revert")) + data := newBSCSimulationOutbound(t, "1000000000000000", bscNativeAsset, "0x", revertMsg) // 0.001 BNB + simulateOnVault(t, rpcClient, builder, "revertUniversalTx", data, uetypes.TxType_INBOUND_REVERT) +} + +// ---------- 3. ERC20 Revert (Vault) ---------- + +func TestSimulateBSC_RevertUniversalTx_ERC20(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + revertMsg := hex.EncodeToString([]byte("test revert token")) + data := newBSCSimulationOutbound(t, "1000000", bscUSDT, "0x", revertMsg) // 1 USDT + simulateOnVault(t, rpcClient, builder, "revertUniversalTx", data, uetypes.TxType_INBOUND_REVERT) +} + +// ---------- 4. Native FinalizeUniversalTx — no payload ---------- + +func TestSimulateBSC_FinalizeUniversalTx_Native(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + emptyMulticall := encodeMulticallPayload(t, nil) + data := newBSCSimulationOutbound(t, "10000000000", bscNativeAsset, emptyMulticall, "") // ~10 gwei BNB + simulateOnVault(t, rpcClient, builder, "finalizeUniversalTx", data, uetypes.TxType_FUNDS) +} + +// ---------- 5. ERC20 FinalizeUniversalTx — no payload ---------- + +func TestSimulateBSC_FinalizeUniversalTx_ERC20(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + emptyMulticall := encodeMulticallPayload(t, nil) + data := newBSCSimulationOutbound(t, "1000000", bscUSDT, emptyMulticall, "") // 1 USDT + simulateOnVault(t, rpcClient, builder, "finalizeUniversalTx", data, uetypes.TxType_FUNDS) +} + +// ---------- 6. Native FinalizeUniversalTx — with payload ---------- + +func TestSimulateBSC_FinalizeUniversalTx_NativeWithPayload(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + recipient := ethcommon.HexToAddress("0x28F1C7B4596D9db14f85c04DcBd867Bf4b14b811") + nativeMulticall := encodeMulticallPayload(t, []struct { + To ethcommon.Address + Value *big.Int + Data []byte + }{{To: recipient, Value: big.NewInt(1000000000000000), Data: nil}}) + data := newBSCSimulationOutbound(t, "1000000000000000", bscNativeAsset, nativeMulticall, "") // 0.001 BNB + payload + simulateOnVault(t, rpcClient, builder, "finalizeUniversalTx", data, uetypes.TxType_FUNDS_AND_PAYLOAD) +} + +// ---------- 7. Payload only — no funds ---------- + +func TestSimulateBSC_FinalizeUniversalTx_PayloadOnly(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + payloadRecipient := ethcommon.HexToAddress("0x28F1C7B4596D9db14f85c04DcBd867Bf4b14b811") + payloadOnlyMulticall := encodeMulticallPayload(t, []struct { + To ethcommon.Address + Value *big.Int + Data []byte + }{{To: payloadRecipient, Value: big.NewInt(0), Data: []byte{0xde, 0xad, 0xbe, 0xef}}}) + data := newBSCSimulationOutbound(t, "0", bscNativeAsset, payloadOnlyMulticall, "") + simulateOnVault(t, rpcClient, builder, "finalizeUniversalTx", data, uetypes.TxType_PAYLOAD) +} + +// ---------- 8. Native RescueFunds ---------- + +func TestSimulateBSC_RescueFunds_Native(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + revertMsg := hex.EncodeToString([]byte("rescue native")) + data := newBSCSimulationOutbound(t, "1000000000000000", bscNativeAsset, "0x", revertMsg) // 0.001 BNB + simulateOnVault(t, rpcClient, builder, "rescueFunds", data, uetypes.TxType_INBOUND_REVERT) +} + +// ---------- 9. ERC20 RescueFunds ---------- + +func TestSimulateBSC_RescueFunds_ERC20(t *testing.T) { + rpcClient, builder := setupBSCSimulation(t) + defer rpcClient.Close() + + revertMsg := hex.EncodeToString([]byte("rescue token")) + data := newBSCSimulationOutbound(t, "1000000", bscUSDT, "0x", revertMsg) // 1 USDT + simulateOnVault(t, rpcClient, builder, "rescueFunds", data, uetypes.TxType_INBOUND_REVERT) +} diff --git a/universalClient/chains/push/event_parser.go b/universalClient/chains/push/event_parser.go index 8f67ae93..12bcb264 100644 --- a/universalClient/chains/push/event_parser.go +++ b/universalClient/chains/push/event_parser.go @@ -45,7 +45,10 @@ const ( AttrKeyAssetAddr = "asset_addr" AttrKeySender = "sender" AttrKeyPayload = "payload" + AttrKeyGasFee = "gas_fee" AttrKeyGasLimit = "gas_limit" + AttrKeyGasPrice = "gas_price" + AttrKeyGasToken = "gas_token" AttrKeyTxType = "tx_type" AttrKeyPcTxHash = "pc_tx_hash" AttrKeyLogIndex = "log_index" @@ -177,7 +180,10 @@ func parseOutboundEvent(event abci.Event) (*store.Event, error) { AssetAddr: attrs[AttrKeyAssetAddr], Sender: attrs[AttrKeySender], Payload: attrs[AttrKeyPayload], + GasFee: attrs[AttrKeyGasFee], GasLimit: attrs[AttrKeyGasLimit], + GasPrice: attrs[AttrKeyGasPrice], + GasToken: attrs[AttrKeyGasToken], TxType: attrs[AttrKeyTxType], PcTxHash: attrs[AttrKeyPcTxHash], LogIndex: attrs[AttrKeyLogIndex], diff --git a/universalClient/chains/svm/gas_oracle.go b/universalClient/chains/svm/chain_meta_oracle.go similarity index 72% rename from universalClient/chains/svm/gas_oracle.go rename to universalClient/chains/svm/chain_meta_oracle.go index bb1aaca7..aec40985 100644 --- a/universalClient/chains/svm/gas_oracle.go +++ b/universalClient/chains/svm/chain_meta_oracle.go @@ -9,8 +9,8 @@ import ( "github.com/rs/zerolog" ) -// GasOracle handles fetching and reporting gas prices (prioritization fees) -type GasOracle struct { +// ChainMetaOracle handles fetching and reporting gas prices (prioritization fees) +type ChainMetaOracle struct { rpcClient *RPCClient pushSigner *pushsigner.Signer chainID string @@ -20,15 +20,15 @@ type GasOracle struct { wg sync.WaitGroup } -// NewGasOracle creates a new gas oracle -func NewGasOracle( +// NewChainMetaOracle creates a new gas oracle +func NewChainMetaOracle( rpcClient *RPCClient, pushSigner *pushsigner.Signer, chainID string, gasPriceIntervalSeconds int, logger zerolog.Logger, -) *GasOracle { - return &GasOracle{ +) *ChainMetaOracle { + return &ChainMetaOracle{ rpcClient: rpcClient, pushSigner: pushSigner, chainID: chainID, @@ -39,24 +39,24 @@ func NewGasOracle( } // Start begins fetching and voting on gas prices -func (g *GasOracle) Start(ctx context.Context) error { +func (g *ChainMetaOracle) Start(ctx context.Context) error { g.wg.Add(1) - go g.fetchAndVoteGasPrice(ctx) + go g.fetchAndVoteChainMeta(ctx) return nil } // Stop stops the gas oracle -func (g *GasOracle) Stop() { +func (g *ChainMetaOracle) Stop() { close(g.stopCh) g.wg.Wait() } -// fetchAndVoteGasPrice periodically fetches gas price and votes on it -func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { +// fetchAndVoteChainMeta periodically fetches gas price and votes on it +func (g *ChainMetaOracle) fetchAndVoteChainMeta(ctx context.Context) { defer g.wg.Done() // Get gas oracle fetch interval from config - interval := g.getGasOracleFetchInterval() + interval := g.getChainMetaOracleFetchInterval() if interval <= 0 { interval = 30 * time.Second } @@ -97,15 +97,15 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { continue } - // Vote on gas price + // Vote on chain meta (gas price + slot height) priceUint64 := gasPrice.Uint64() - voteTxHash, err := g.pushSigner.VoteGasPrice(ctx, g.chainID, priceUint64, slotNumber) + voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, slotNumber) if err != nil { g.logger.Error(). Err(err). Uint64("price", priceUint64). Uint64("slot", slotNumber). - Msg("failed to vote on gas price") + Msg("failed to vote on chain meta") continue } @@ -113,13 +113,13 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { Str("vote_tx_hash", voteTxHash). Uint64("price", priceUint64). Uint64("slot", slotNumber). - Msg("successfully voted on gas price") + Msg("successfully voted on chain meta") } } } -// getGasOracleFetchInterval returns the gas oracle fetch interval -func (g *GasOracle) getGasOracleFetchInterval() time.Duration { +// getChainMetaOracleFetchInterval returns the gas oracle fetch interval +func (g *ChainMetaOracle) getChainMetaOracleFetchInterval() time.Duration { if g.gasPriceIntervalSeconds <= 0 { return 30 * time.Second } diff --git a/universalClient/chains/svm/gas_oracle_test.go b/universalClient/chains/svm/chain_meta_oracle_test.go similarity index 67% rename from universalClient/chains/svm/gas_oracle_test.go rename to universalClient/chains/svm/chain_meta_oracle_test.go index 4f7905df..5bccb055 100644 --- a/universalClient/chains/svm/gas_oracle_test.go +++ b/universalClient/chains/svm/chain_meta_oracle_test.go @@ -9,13 +9,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestNewGasOracle(t *testing.T) { +func TestNewChainMetaOracle(t *testing.T) { t.Run("creates gas oracle with valid params", func(t *testing.T) { logger := zerolog.Nop() chainID := "solana:mainnet" interval := 30 - oracle := NewGasOracle(nil, nil, chainID, interval, logger) + oracle := NewChainMetaOracle(nil, nil, chainID, interval, logger) require.NotNil(t, oracle) assert.Equal(t, chainID, oracle.chainID) @@ -35,30 +35,30 @@ func TestNewGasOracle(t *testing.T) { } for _, chainID := range testCases { - oracle := NewGasOracle(nil, nil, chainID, 30, logger) + oracle := NewChainMetaOracle(nil, nil, chainID, 30, logger) assert.Equal(t, chainID, oracle.chainID) } }) } -func TestGasOracleGetGasOracleFetchInterval(t *testing.T) { +func TestChainMetaOracleGetChainMetaOracleFetchInterval(t *testing.T) { logger := zerolog.Nop() t.Run("returns configured interval", func(t *testing.T) { - oracle := NewGasOracle(nil, nil, "solana:mainnet", 60, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "solana:mainnet", 60, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, 60*time.Second, interval) }) t.Run("returns default for zero interval", func(t *testing.T) { - oracle := NewGasOracle(nil, nil, "solana:mainnet", 0, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "solana:mainnet", 0, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, 30*time.Second, interval) }) t.Run("returns default for negative interval", func(t *testing.T) { - oracle := NewGasOracle(nil, nil, "solana:mainnet", -10, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "solana:mainnet", -10, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, 30*time.Second, interval) }) @@ -74,26 +74,26 @@ func TestGasOracleGetGasOracleFetchInterval(t *testing.T) { } for _, tc := range testCases { - oracle := NewGasOracle(nil, nil, "solana:mainnet", tc.input, logger) - interval := oracle.getGasOracleFetchInterval() + oracle := NewChainMetaOracle(nil, nil, "solana:mainnet", tc.input, logger) + interval := oracle.getChainMetaOracleFetchInterval() assert.Equal(t, tc.expected, interval, "interval %d should result in %v", tc.input, tc.expected) } }) } -func TestGasOracleStop(t *testing.T) { +func TestChainMetaOracleStop(t *testing.T) { t.Run("stop waits for goroutine", func(t *testing.T) { logger := zerolog.Nop() - oracle := NewGasOracle(nil, nil, "solana:mainnet", 30, logger) + oracle := NewChainMetaOracle(nil, nil, "solana:mainnet", 30, logger) // Should not panic or hang oracle.Stop() }) } -func TestGasOracleStruct(t *testing.T) { +func TestChainMetaOracleStruct(t *testing.T) { t.Run("struct has expected fields", func(t *testing.T) { - oracle := &GasOracle{} + oracle := &ChainMetaOracle{} assert.Nil(t, oracle.rpcClient) assert.Nil(t, oracle.pushSigner) assert.Empty(t, oracle.chainID) diff --git a/universalClient/chains/svm/client.go b/universalClient/chains/svm/client.go index 30071b7e..21778dd0 100644 --- a/universalClient/chains/svm/client.go +++ b/universalClient/chains/svm/client.go @@ -31,11 +31,11 @@ type Client struct { cancel context.CancelFunc // Components - eventListener *EventListener - eventProcessor *common.EventProcessor - eventConfirmer *EventConfirmer - gasOracle *GasOracle - txBuilder *TxBuilder + eventListener *EventListener + eventProcessor *common.EventProcessor + eventConfirmer *EventConfirmer + chainMetaOracle *ChainMetaOracle + txBuilder *TxBuilder // Dependencies pushSigner *pushsigner.Signer @@ -152,8 +152,8 @@ func (c *Client) Stop() error { } } - if c.gasOracle != nil { - c.gasOracle.Stop() + if c.chainMetaOracle != nil { + c.chainMetaOracle.Stop() } // Close RPC client last @@ -242,7 +242,7 @@ func (c *Client) initializeComponents() error { // Create gas oracle if pushSigner is available if c.pushSigner != nil { - c.gasOracle = NewGasOracle( + c.chainMetaOracle = NewChainMetaOracle( c.rpcClient, c.pushSigner, c.chainIDStr, @@ -289,8 +289,8 @@ func (c *Client) startComponents() error { } } - if c.gasOracle != nil { - if err := c.gasOracle.Start(c.ctx); err != nil { + if c.chainMetaOracle != nil { + if err := c.chainMetaOracle.Start(c.ctx); err != nil { return fmt.Errorf("failed to start gas oracle: %w", err) } } diff --git a/universalClient/chains/svm/event_confirmer.go b/universalClient/chains/svm/event_confirmer.go index fdfa8b0b..3f37fe8b 100644 --- a/universalClient/chains/svm/event_confirmer.go +++ b/universalClient/chains/svm/event_confirmer.go @@ -169,7 +169,7 @@ func (ec *EventConfirmer) processPendingEvents(ctx context.Context) error { confirmations := latestSlot - txSlot + 1 if confirmations >= requiredConfirmations { - // Update event status to CONFIRMED + // GasFeeUsed for outbound events is already set by the event parser from the on-chain event data rowsAffected, err := ec.chainStore.UpdateEventStatus(event.EventID, "PENDING", "CONFIRMED") if err != nil { ec.logger.Error(). diff --git a/universalClient/chains/svm/event_parser.go b/universalClient/chains/svm/event_parser.go index 8d7072d8..c809607d 100644 --- a/universalClient/chains/svm/event_parser.go +++ b/universalClient/chains/svm/event_parser.go @@ -101,11 +101,17 @@ func parseSendFundsEvent(log string, signature string, slot uint64, logIndex uin return event } -// parseOutboundObservationEvent parses an outboundObservation event +// parseOutboundObservationEvent parses an outboundObservation event (UniversalTxFinalized) // Event structure (Borsh serialized): // - discriminator (8 bytes) -// - sub_tx_id (32 bytes - bytes32) -// - universal_tx_id (32 bytes - bytes32) +// - sub_tx_id (32 bytes) +// - universal_tx_id (32 bytes) +// - gas_fee (8 bytes, u64 lamports) +// - push_account (20 bytes) +// - target (32 bytes, Pubkey) +// - token (32 bytes, Pubkey) +// - amount (8 bytes, u64) +// - payload (4 bytes length + data, Vec) func parseOutboundObservationEvent(log string, signature string, slot uint64, logIndex uint, chainID string, logger zerolog.Logger) *store.Event { if !strings.HasPrefix(log, "Program data: ") { return nil @@ -117,11 +123,11 @@ func parseOutboundObservationEvent(log string, signature string, slot uint64, lo return nil } - // Need at least: 8 bytes discriminator + 32 bytes txID + 32 bytes universalTxID = 72 bytes - if len(decoded) < 72 { + // Minimum: 8 disc + 32 sub_tx_id + 32 universal_tx_id + 8 gas_fee = 80 bytes + if len(decoded) < 80 { logger.Warn(). Int("data_len", len(decoded)). - Msg("data too short for outboundObservation event; need at least 72 bytes") + Msg("data too short for outboundObservation event; need at least 80 bytes") return nil } @@ -144,11 +150,16 @@ func parseOutboundObservationEvent(log string, signature string, slot uint64, lo // Extract universalTxID (32 bytes) universalTxID := "0x" + hex.EncodeToString(decoded[offset:offset+32]) + offset += 32 + + // Extract gas_fee (8 bytes, u64 little-endian lamports) + gasFee := binary.LittleEndian.Uint64(decoded[offset : offset+8]) // Create OutboundEvent payload payload := common.OutboundEvent{ TxID: txID, UniversalTxID: universalTxID, + GasFeeUsed: fmt.Sprintf("%d", gasFee), } // Marshal payload to JSON @@ -176,6 +187,7 @@ func parseOutboundObservationEvent(log string, signature string, slot uint64, lo Str("event_id", eventID). Str("tx_id", txID). Str("universal_tx_id", universalTxID). + Str("gas_fee", fmt.Sprintf("%d", gasFee)). Msg("parsed outboundObservation event") return event @@ -301,10 +313,7 @@ func decodeUniversalTxEvent(data []byte, logger zerolog.Logger) (*common.Univers offset += int(dataLen) } - // Parse revert_cfg (RevertConfig struct) - // RevertConfig: { recipient: Pubkey, message: Vec } - - // Parse revert recipient (Pubkey) + // Parse revert_recipient (Pubkey) if len(data) < offset+32 { logger.Warn().Msg("not enough data for revert recipient") return payload, nil @@ -313,36 +322,6 @@ func decodeUniversalTxEvent(data []byte, logger zerolog.Logger) (*common.Univers payload.RevertFundRecipient = revertRecipient.String() offset += 32 - // Parse revert message (Vec) - if len(data) < offset+4 { - logger.Warn().Msg("not enough data for revert message length") - return payload, nil - } - revertMsgLen := binary.LittleEndian.Uint32(data[offset : offset+4]) - offset += 4 - - remainingForRevert := len(data) - offset - revertLenValid := int(revertMsgLen) <= remainingForRevert - if !revertLenValid { - logger.Warn(). - Uint32("revert_msg_len", revertMsgLen). - Int("available", remainingForRevert). - Msg("revert message length invalid, skipping revert message parsing") - } - - if revertLenValid && revertMsgLen > 0 { - if len(data) < offset+int(revertMsgLen) { - logger.Warn(). - Uint32("expected_len", revertMsgLen). - Int("available", len(data)-offset). - Msg("not enough data for revert message") - return payload, nil - } - revertMsg := data[offset : offset+int(revertMsgLen)] - payload.RevertMsg = "0x" + hex.EncodeToString(revertMsg) - offset += int(revertMsgLen) - } - // Parse tx_type (TxType enum) if len(data) <= offset { logger.Warn().Msg("not enough data for tx_type, defaulting to Funds") @@ -376,6 +355,12 @@ func decodeUniversalTxEvent(data []byte, logger zerolog.Logger) (*common.Univers offset += int(sigLen) } + // Parse fromCEA (bool, 1 byte) - if not present, defaults to false + if len(data) > offset { + payload.FromCEA = data[offset] != 0 + offset++ + } + logger.Debug(). Str("sender", payload.Sender). Str("recipient", payload.Recipient). @@ -384,8 +369,8 @@ func decodeUniversalTxEvent(data []byte, logger zerolog.Logger) (*common.Univers Str("universal_payload", fmt.Sprintf("%+v", payload.Payload)). Str("verification_data", payload.VerificationData). Str("revert_recipient", payload.RevertFundRecipient). - Str("revert_message", payload.RevertMsg). Uint("tx_type", payload.TxType). + Bool("from_cea", payload.FromCEA). Int("total_bytes_parsed", offset). Msg("decoded UniversalTx event") diff --git a/universalClient/chains/svm/event_parser_test.go b/universalClient/chains/svm/event_parser_test.go index 9770631f..7a84656e 100644 --- a/universalClient/chains/svm/event_parser_test.go +++ b/universalClient/chains/svm/event_parser_test.go @@ -2,6 +2,7 @@ package svm import ( "encoding/base64" + "encoding/binary" "encoding/hex" "encoding/json" "testing" @@ -19,12 +20,15 @@ func TestParseOutboundObservationEvent(t *testing.T) { chainID := "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" signature := "5wHu1qwD7q5xMkZxq6z2S3r4y5N7m8P9kL0jH1gF2dE3cB4aA5b6C7d8E9f0G1h2" - // Helper to create base64-encoded log data - createLogData := func(discriminator []byte, txID []byte, universalTxID []byte) string { - data := make([]byte, 0, 72) + // Helper to create base64-encoded log data with gas_fee + createLogData := func(discriminator []byte, txID []byte, universalTxID []byte, gasFee uint64) string { + data := make([]byte, 0, 80) data = append(data, discriminator...) data = append(data, txID...) data = append(data, universalTxID...) + gasFeeBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(gasFeeBytes, gasFee) + data = append(data, gasFeeBytes...) return "Program data: " + base64.StdEncoding.EncodeToString(data) } @@ -54,7 +58,7 @@ func TestParseOutboundObservationEvent(t *testing.T) { }{ { name: "parses valid outbound observation event", - log: createLogData(discriminator, txID, universalTxID), + log: createLogData(discriminator, txID, universalTxID, 5000), wantEvent: true, validate: func(t *testing.T, event *store.Event) { assert.Contains(t, event.EventID, signature) @@ -63,7 +67,7 @@ func TestParseOutboundObservationEvent(t *testing.T) { assert.Equal(t, "PENDING", event.Status) assert.Equal(t, "STANDARD", event.ConfirmationType) - // Verify event data contains tx_id and universal_tx_id + // Verify event data contains tx_id, universal_tx_id, and gas_fee_used assert.NotNil(t, event.EventData) var outboundData map[string]any err := json.Unmarshal(event.EventData, &outboundData) @@ -74,6 +78,7 @@ func TestParseOutboundObservationEvent(t *testing.T) { assert.Equal(t, expectedTxID, outboundData["tx_id"]) assert.Equal(t, expectedUniversalTxID, outboundData["universal_tx_id"]) + assert.Equal(t, "5000", outboundData["gas_fee_used"]) }, }, { @@ -92,20 +97,21 @@ func TestParseOutboundObservationEvent(t *testing.T) { wantEvent: false, }, { - name: "returns nil for data too short (less than 72 bytes)", + name: "returns nil for data too short (less than 80 bytes)", log: func() string { - // Only 64 bytes (8 discriminator + 32 txID, missing universalTxID) - shortData := make([]byte, 64) + // Only 72 bytes (8 discriminator + 32 txID + 32 universalTxID, missing gas_fee) + shortData := make([]byte, 72) copy(shortData[:8], discriminator) copy(shortData[8:40], txID) + copy(shortData[40:72], universalTxID) return "Program data: " + base64.StdEncoding.EncodeToString(shortData) }(), wantEvent: false, }, { - name: "correctly parses minimum valid data (exactly 72 bytes)", + name: "correctly parses minimum valid data (exactly 80 bytes)", log: func() string { - exactData := make([]byte, 72) + exactData := make([]byte, 80) copy(exactData[:8], discriminator) for i := 8; i < 40; i++ { exactData[i] = 0x11 // txID @@ -113,6 +119,7 @@ func TestParseOutboundObservationEvent(t *testing.T) { for i := 40; i < 72; i++ { exactData[i] = 0x22 // universalTxID } + binary.LittleEndian.PutUint64(exactData[72:80], 12345) // gas_fee return "Program data: " + base64.StdEncoding.EncodeToString(exactData) }(), wantEvent: true, @@ -121,21 +128,22 @@ func TestParseOutboundObservationEvent(t *testing.T) { err := json.Unmarshal(event.EventData, &outboundData) require.NoError(t, err) - // Verify the values are correctly parsed assert.Contains(t, outboundData["tx_id"], "0x1111") assert.Contains(t, outboundData["universal_tx_id"], "0x2222") + assert.Equal(t, "12345", outboundData["gas_fee_used"]) }, }, { - name: "handles data longer than 72 bytes", + name: "handles data longer than 80 bytes", log: func() string { - // 100 bytes - extra data after the required fields should be ignored - longData := make([]byte, 100) + // 120 bytes - extra data after the required fields should be ignored + longData := make([]byte, 120) copy(longData[:8], discriminator) copy(longData[8:40], txID) copy(longData[40:72], universalTxID) + binary.LittleEndian.PutUint64(longData[72:80], 9999) // gas_fee // Extra bytes at the end - for i := 72; i < 100; i++ { + for i := 80; i < 120; i++ { longData[i] = 0xFF } return "Program data: " + base64.StdEncoding.EncodeToString(longData) @@ -151,6 +159,7 @@ func TestParseOutboundObservationEvent(t *testing.T) { assert.Equal(t, expectedTxID, outboundData["tx_id"]) assert.Equal(t, expectedUniversalTxID, outboundData["universal_tx_id"]) + assert.Equal(t, "9999", outboundData["gas_fee_used"]) }, }, } @@ -193,14 +202,15 @@ func TestParseOutboundObservationEvent_EventIDFormat(t *testing.T) { logger := zerolog.New(nil).Level(zerolog.Disabled) chainID := "solana:devnet" - // Create valid outbound data - data := make([]byte, 72) + // Create valid outbound data (80 bytes minimum: 8 disc + 32 txID + 32 utxID + 8 gas_fee) + data := make([]byte, 80) for i := 0; i < 8; i++ { data[i] = byte(i) // discriminator } for i := 8; i < 72; i++ { data[i] = byte(i % 256) // txID and universalTxID } + binary.LittleEndian.PutUint64(data[72:80], 0) // gas_fee log := "Program data: " + base64.StdEncoding.EncodeToString(data) tests := []struct { diff --git a/universalClient/chains/svm/tx_builder.go b/universalClient/chains/svm/tx_builder.go index db45c651..25a2ec13 100644 --- a/universalClient/chains/svm/tx_builder.go +++ b/universalClient/chains/svm/tx_builder.go @@ -79,11 +79,6 @@ import ( uetypes "github.com/pushchain/push-chain-node/x/uexecutor/types" ) -// DefaultComputeUnitLimit is the fallback compute budget when the event doesn't specify a gas limit. -// Solana charges based on "compute units" (similar to EVM gas). 200k is a safe default for most -// gateway operations. The actual cost depends on how many accounts are touched, CPI depth, etc. -const DefaultComputeUnitLimit = 200000 - // GatewayAccountMeta represents a single account that a target program needs when executing // an arbitrary cross-chain call (instruction_id=2). The payload from Push Chain includes a list // of these — each with the account's public key and whether it needs write access. @@ -162,7 +157,6 @@ func NewTxBuilder( func (tb *TxBuilder) GetOutboundSigningRequest( ctx context.Context, data *uetypes.OutboundCreatedEvent, - gasPrice *big.Int, nonce uint64, ) (*common.UnSignedOutboundTxReq, error) { if data == nil { @@ -174,9 +168,6 @@ func (tb *TxBuilder) GetOutboundSigningRequest( if data.DestinationChain == "" { return nil, fmt.Errorf("destinationChain is required") } - if gasPrice == nil { - return nil, fmt.Errorf("gasPrice is required") - } // --- Parse all fields from the outbound event --- @@ -267,9 +258,11 @@ func (tb *TxBuilder) GetOutboundSigningRequest( } // For native SOL, token stays all-zeros (Pubkey::default() in Rust) - // Gas fee from event. TODO: OutboundCreatedEvent doesn't include GasFee field yet. - // When the event pipeline threads gas_fee through, parse it here. + // Parse gas fee from event data var gasFee uint64 + if data.GasFee != "" { + gasFee, _ = strconv.ParseUint(data.GasFee, 10, 64) + } // recipient/target: Solana pubkey of the destination. Used differently depending on instruction: // - Withdraw (id=1): the wallet that receives the funds (target = recipient) @@ -287,34 +280,29 @@ func (tb *TxBuilder) GetOutboundSigningRequest( // --- Determine instruction ID and decode payload --- // For non-revert flows: decode payload to get instruction_id (1=withdraw, 2=execute), - // accounts, ixData, and rentFee. The instruction_id in the payload is authoritative. - // For revert flows: instruction_id is determined from TxType + asset type. + // accounts, and ixData. The instruction_id in the payload is authoritative. + // For revert flows: instruction_id is always 3 (unified for SOL and SPL). + // For rescue flows: instruction_id is 4 (when proto is ready). var instructionID uint8 var targetProgram [32]byte var accounts []GatewayAccountMeta var ixData []byte - var rentFee uint64 var revertRecipient [32]byte var revertMint [32]byte - if txType == uetypes.TxType_INBOUND_REVERT { - // Revert flows: instruction_id from TxType (no payload-based instruction_id) - if isNative { - instructionID = 3 - } else { - instructionID = 4 + if txType == uetypes.TxType_INBOUND_REVERT || txType == uetypes.TxType_RESCUE_FUNDS { + // Revert (id=3) and rescue (id=4): instruction_id determined by TxType, no payload decode + instructionID, err = tb.determineInstructionID(txType, isNative) + if err != nil { + return nil, fmt.Errorf("failed to determine instruction ID: %w", err) } - - switch instructionID { - case 3: // Revert SOL: recipient gets their SOL back - copy(revertRecipient[:], recipientPubkey.Bytes()) - case 4: // Revert SPL: recipient gets their SPL tokens back - copy(revertRecipient[:], recipientPubkey.Bytes()) + copy(revertRecipient[:], recipientPubkey.Bytes()) + if !isNative { copy(revertMint[:], token[:]) } } else { // Non-revert flows: decode payload to get instruction_id. - // Payload format: [accounts][ixData][rentFee][instruction_id] + // Payload format: [accounts][ixData][instruction_id][target_program] // For simple withdraw, payload may be empty — fall back to TxType. payloadHex := removeHexPrefix(data.Payload) if payloadHex != "" { @@ -325,11 +313,15 @@ func (tb *TxBuilder) GetOutboundSigningRequest( if len(payloadBytes) > 0 { var payloadInstructionID uint8 - accounts, ixData, rentFee, payloadInstructionID, err = decodePayload(payloadBytes) + var payloadTargetProgram [32]byte + accounts, ixData, payloadInstructionID, payloadTargetProgram, err = decodePayload(payloadBytes) if err != nil { return nil, fmt.Errorf("failed to decode payload: %w", err) } instructionID = payloadInstructionID + if payloadTargetProgram != ([32]byte{}) { + targetProgram = payloadTargetProgram + } } } @@ -347,24 +339,23 @@ func (tb *TxBuilder) GetOutboundSigningRequest( return nil, fmt.Errorf("invalid instruction_id: %d (expected 1=withdraw or 2=execute)", instructionID) } - // Validate rent_fee <= gas_fee (contract requires this) - if rentFee > gasFee { - return nil, fmt.Errorf("rent_fee (%d) exceeds gas_fee (%d)", rentFee, gasFee) - } - // Validate mode-specific constraints per integration guide switch instructionID { case 1: // Withdraw mode - if len(accounts) > 0 || len(ixData) > 0 || rentFee > 0 { - return nil, fmt.Errorf("withdraw mode: accounts, ixData, and rentFee must be empty/zero") + if len(accounts) > 0 || len(ixData) > 0 { + return nil, fmt.Errorf("withdraw mode: accounts and ixData must be empty") } if amount.Uint64() == 0 { return nil, fmt.Errorf("withdraw mode: amount must be > 0") } - copy(targetProgram[:], recipientPubkey.Bytes()) + if targetProgram == ([32]byte{}) { + copy(targetProgram[:], recipientPubkey.Bytes()) + } case 2: // Execute mode - copy(targetProgram[:], recipientPubkey.Bytes()) + if targetProgram == ([32]byte{}) { + copy(targetProgram[:], recipientPubkey.Bytes()) + } } } @@ -374,19 +365,16 @@ func (tb *TxBuilder) GetOutboundSigningRequest( messageHash, err := tb.constructTSSMessage( instructionID, chainID, amount.Uint64(), txID, universalTxID, sender, token, gasFee, - targetProgram, accounts, ixData, rentFee, + targetProgram, accounts, ixData, revertRecipient, revertMint, ) if err != nil { return nil, fmt.Errorf("failed to construct TSS message: %w", err) } - prioritizationFee := gasPrice.Uint64() - return &common.UnSignedOutboundTxReq{ SigningHash: messageHash, // This is the keccak256 hash to be signed by TSS Nonce: nonce, - GasPrice: big.NewInt(int64(prioritizationFee)), }, nil } @@ -425,6 +413,13 @@ func (tb *TxBuilder) IsAlreadyExecuted(ctx context.Context, txID string) (bool, return len(data) > 0, nil } +// GetGasFeeUsed returns "0" for SVM. SVM gas accounting is handled via vault +// gasFee reimbursement — the actual gas cost is the base fee + PDA rent paid +// by the relayer, which is reimbursed from the gasFee baked into the signed message. +func (tb *TxBuilder) GetGasFeeUsed(ctx context.Context, txHash string) (string, error) { + return "0", nil +} + // ============================================================================= // STEP 2: BroadcastOutboundSigningRequest // @@ -567,8 +562,11 @@ func (tb *TxBuilder) BuildOutboundTransaction( copy(token[:], mintPubkey.Bytes()) } - // Gas fee from event. TODO: OutboundCreatedEvent doesn't include GasFee field yet. + // Parse gas fee from event data var gasFee uint64 + if data.GasFee != "" { + gasFee, _ = strconv.ParseUint(data.GasFee, 10, 64) + } recipientPubkey, err := solana.PublicKeyFromBase58(data.Recipient) if err != nil { @@ -588,13 +586,13 @@ func (tb *TxBuilder) BuildOutboundTransaction( var instructionID uint8 var execAccounts []GatewayAccountMeta var ixData []byte - var rentFee uint64 - if txType == uetypes.TxType_INBOUND_REVERT { - if isNative { - instructionID = 3 - } else { - instructionID = 4 + if txType == uetypes.TxType_INBOUND_REVERT || txType == uetypes.TxType_RESCUE_FUNDS { + // Revert (id=3) and rescue (id=4): instruction_id determined by TxType, no payload decode + var idErr error + instructionID, idErr = tb.determineInstructionID(txType, isNative) + if idErr != nil { + return nil, 0, fmt.Errorf("failed to determine instruction ID: %w", idErr) } } else { // Non-revert: decode payload to get instruction_id @@ -605,7 +603,7 @@ func (tb *TxBuilder) BuildOutboundTransaction( return nil, 0, fmt.Errorf("failed to decode payload hex: %w", decErr) } if len(payloadBytes) > 0 { - execAccounts, ixData, rentFee, instructionID, err = decodePayload(payloadBytes) + execAccounts, ixData, instructionID, _, err = decodePayload(payloadBytes) if err != nil { return nil, 0, fmt.Errorf("failed to decode payload: %w", err) } @@ -624,9 +622,6 @@ func (tb *TxBuilder) BuildOutboundTransaction( if instructionID != 1 && instructionID != 2 { return nil, 0, fmt.Errorf("invalid instruction_id: %d", instructionID) } - if rentFee > gasFee { - return nil, 0, fmt.Errorf("rent_fee (%d) exceeds gas_fee (%d)", rentFee, gasFee) - } } // --- Derive PDAs --- @@ -650,6 +645,12 @@ func (tb *TxBuilder) BuildOutboundTransaction( return nil, 0, fmt.Errorf("failed to derive executed_tx PDA: %w", err) } + // --- Derive fee_vault PDA (needed for revert and rescue) --- + feeVaultPDA, _, err := solana.FindProgramAddress([][]byte{[]byte("fee_vault")}, tb.gatewayAddress) + if err != nil { + return nil, 0, fmt.Errorf("failed to derive fee_vault PDA: %w", err) + } + // --- Build instruction data and accounts list --- var instructionData []byte var accounts []*solana.AccountMeta @@ -678,7 +679,7 @@ func (tb *TxBuilder) BuildOutboundTransaction( instructionData = tb.buildWithdrawAndExecuteData( instructionID, txID, universalTxID, amount.Uint64(), sender, - writableFlags, ixData, gasFee, rentFee, + writableFlags, ixData, gasFee, signature, recoveryID, req.SigningHash, ) @@ -692,46 +693,28 @@ func (tb *TxBuilder) BuildOutboundTransaction( ) case instructionID == 3: - // ---- revert_universal_tx (native SOL refund) ---- + // ---- revert_universal_tx (unified for SOL and SPL) ---- instructionData = tb.buildRevertData( - instructionID, txID, universalTxID, amount.Uint64(), + txID, universalTxID, amount.Uint64(), recipientPubkey, revertMsgBytes, gasFee, signature, recoveryID, req.SigningHash, ) - accounts = tb.buildRevertSOLAccounts( - configPDA, vaultPDA, tssPDA, recipientPubkey, + accounts = tb.buildRevertAccounts( + configPDA, vaultPDA, feeVaultPDA, tssPDA, recipientPubkey, executedTxPDA, relayerKeypair.PublicKey(), + isNative, mintPubkey, ) case instructionID == 4: - // ---- revert_universal_tx_token (SPL token refund) ---- - ataProgramID := solana.MustPublicKeyFromBase58("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL") - - tokenVaultATA, _, ataErr := solana.FindProgramAddress( - [][]byte{vaultPDA.Bytes(), solana.TokenProgramID.Bytes(), mintPubkey.Bytes()}, - ataProgramID, - ) - if ataErr != nil { - return nil, 0, fmt.Errorf("failed to derive token vault ATA: %w", ataErr) - } - - recipientATA, _, ataErr := solana.FindProgramAddress( - [][]byte{recipientPubkey.Bytes(), solana.TokenProgramID.Bytes(), mintPubkey.Bytes()}, - ataProgramID, - ) - if ataErr != nil { - return nil, 0, fmt.Errorf("failed to derive recipient ATA: %w", ataErr) - } - - instructionData = tb.buildRevertData( - instructionID, txID, universalTxID, amount.Uint64(), - recipientPubkey, revertMsgBytes, gasFee, + // ---- rescue_funds ---- + instructionData = tb.buildRescueData( + txID, universalTxID, amount.Uint64(), gasFee, signature, recoveryID, req.SigningHash, ) - accounts = tb.buildRevertSPLAccounts( - configPDA, vaultPDA, tokenVaultATA, tssPDA, - recipientATA, mintPubkey, + accounts = tb.buildRescueAccounts( + configPDA, vaultPDA, feeVaultPDA, tssPDA, recipientPubkey, executedTxPDA, relayerKeypair.PublicKey(), + isNative, mintPubkey, ) } @@ -747,25 +730,21 @@ func (tb *TxBuilder) BuildOutboundTransaction( instructionData, ) - var computeUnitLimit uint32 if data.GasLimit == "" || data.GasLimit == "0" { - computeUnitLimit = DefaultComputeUnitLimit - } else { - parsedLimit, parseErr := strconv.ParseUint(data.GasLimit, 10, 32) - if parseErr != nil { - computeUnitLimit = DefaultComputeUnitLimit - } else { - computeUnitLimit = uint32(parsedLimit) - } + return nil, 0, fmt.Errorf("gas limit is required in outbound event") + } + parsedLimit, parseErr := strconv.ParseUint(data.GasLimit, 10, 32) + if parseErr != nil { + return nil, 0, fmt.Errorf("invalid gas limit: %s", data.GasLimit) } + computeUnitLimit := uint32(parsedLimit) - computeBudgetInstruction := tb.buildSetComputeUnitLimitInstruction(computeUnitLimit) + computeLimitIx := tb.buildSetComputeUnitLimitInstruction(computeUnitLimit) - // Build the instruction list. For SPL flows that need a recipient ATA - // (withdraw SPL or revert SPL), prepend a CreateIdempotent ATA instruction. - instructions := []solana.Instruction{computeBudgetInstruction} + // Build the instruction list. + instructions := []solana.Instruction{computeLimitIx} - needsRecipientATA := (instructionID == 1 && !isNative) || instructionID == 4 + needsRecipientATA := (instructionID == 1 && !isNative) || ((instructionID == 3 || instructionID == 4) && !isNative) if needsRecipientATA { createATAInstruction := tb.buildCreateATAIdempotentInstruction( relayerKeypair.PublicKey(), @@ -884,8 +863,8 @@ func (tb *TxBuilder) fetchTSSChainID(ctx context.Context, tssPDA solana.PublicKe // ID Function When // 1 finalize_universal_tx FUNDS (withdraw mode): send SOL or SPL tokens to a recipient // 2 finalize_universal_tx FUNDS_AND_PAYLOAD or GAS_AND_PAYLOAD (execute mode): call a program -// 3 revert_universal_tx INBOUND_REVERT + native SOL: refund SOL for a failed cross-chain tx -// 4 revert_universal_tx_token INBOUND_REVERT + SPL token: refund SPL tokens for a failed tx +// 3 revert_universal_tx INBOUND_REVERT: unified revert for both SOL and SPL +// 4 rescue_funds RESCUE_FUNDS: emergency rescue of locked funds func (tb *TxBuilder) determineInstructionID(txType uetypes.TxType, isNative bool) (uint8, error) { switch txType { case uetypes.TxType_FUNDS: @@ -895,9 +874,9 @@ func (tb *TxBuilder) determineInstructionID(txType uetypes.TxType, isNative bool return 2, nil case uetypes.TxType_INBOUND_REVERT: - if isNative { - return 3, nil - } + return 3, nil + + case uetypes.TxType_RESCUE_FUNDS: return 4, nil default: @@ -917,7 +896,7 @@ func (tb *TxBuilder) determineInstructionID(txType uetypes.TxType, isNative bool // Message format: // // "PUSH_CHAIN_SVM" — 14-byte ASCII prefix (prevents cross-protocol replay) -// instruction_id — 1 byte (1=withdraw, 2=execute, 3=revert SOL, 4=revert SPL) +// instruction_id — 1 byte (1=withdraw, 2=execute, 3=revert, 4=rescue) // chain_id — N bytes UTF-8 (prevents cross-chain replay, e.g., "devnet") // NOTE: raw UTF-8 bytes, NOT Borsh-encoded (no length prefix) // amount — 8 bytes big-endian @@ -928,9 +907,11 @@ func (tb *TxBuilder) determineInstructionID(txType uetypes.TxType, isNative bool // 1 (withdraw): [tx_id(32), utx_id(32), sender(20), token(32), gas_fee(8 BE), target(32)] // 2 (execute): [tx_id(32), utx_id(32), sender(20), token(32), gas_fee(8 BE), target(32), // accounts_buf(4 BE count + [pubkey(32) + writable(1)] per account), -// ix_data_buf(4 BE len + data), rent_fee(8 BE)] -// 3 (revert SOL): [tx_id(32), utx_id(32), recipient(32), gas_fee(8 BE)] -// 4 (revert SPL): [tx_id(32), utx_id(32), mint(32), recipient(32), gas_fee(8 BE)] +// ix_data_buf(4 BE len + data)] +// 3 (revert): SOL: [tx_id(32), utx_id(32), recipient(32), gas_fee(8 BE)] +// SPL: [tx_id(32), utx_id(32), mint(32), recipient(32), gas_fee(8 BE)] +// 4 (rescue): SOL: [tx_id(32), utx_id(32), recipient(32), gas_fee(8 BE)] +// SPL: [tx_id(32), utx_id(32), mint(32), recipient(32), gas_fee(8 BE)] // // The final message is hashed with keccak256 (Solana's keccak::hash = Ethereum's keccak256). func (tb *TxBuilder) constructTSSMessage( @@ -945,7 +926,6 @@ func (tb *TxBuilder) constructTSSMessage( targetProgram [32]byte, execAccounts []GatewayAccountMeta, ixData []byte, - rentFee uint64, revertRecipient [32]byte, revertMint [32]byte, ) ([]byte, error) { @@ -996,20 +976,13 @@ func (tb *TxBuilder) constructTSSMessage( message = append(message, ixDataLen...) message = append(message, ixData...) - rentFeeBytes := make([]byte, 8) - binary.BigEndian.PutUint64(rentFeeBytes, rentFee) - message = append(message, rentFeeBytes...) - - case 3: // revert SOL — tx_id before utx_id (same order as finalize) - message = append(message, txID[:]...) - message = append(message, universalTxID[:]...) - message = append(message, revertRecipient[:]...) - message = append(message, gasFeeBytes...) - - case 4: // revert SPL — tx_id before utx_id, includes mint for token identification + case 3, 4: // revert (id=3) or rescue (id=4) — same message format message = append(message, txID[:]...) message = append(message, universalTxID[:]...) - message = append(message, revertMint[:]...) + if revertMint != ([32]byte{}) { + // SPL: include mint before recipient + message = append(message, revertMint[:]...) + } message = append(message, revertRecipient[:]...) message = append(message, gasFeeBytes...) @@ -1100,15 +1073,17 @@ func (tb *TxBuilder) loadRelayerKeypair() (solana.PrivateKey, error) { // [33 bytes] × N accounts — each is [pubkey(32) + is_writable(1)] // [u32 BE] ix_data_len — length of the instruction data for the target program // [N bytes] ix_data — the raw instruction data to pass to the target program -// [u64 BE] rent_fee — SOL to cover rent for any new accounts created // [u8] instruction_id — 1=withdraw, 2=execute +// [32 bytes] target_program — the Solana program to invoke // -// For withdraw (instruction_id=1): accounts_count=0, ix_data_len=0, rent_fee=0 +// For withdraw (instruction_id=1): accounts_count=0, ix_data_len=0 // For execute (instruction_id=2): accounts and ix_data contain CPI data -func decodePayload(payload []byte) ([]GatewayAccountMeta, []byte, uint64, uint8, error) { - // Minimum payload: accounts_count(4) + ix_data_len(4) + rent_fee(8) + instruction_id(1) = 17 - if len(payload) < 17 { - return nil, nil, 0, 0, fmt.Errorf("payload too short: %d bytes (minimum 17)", len(payload)) +func decodePayload(payload []byte) ([]GatewayAccountMeta, []byte, uint8, [32]byte, error) { + var targetProgram [32]byte + + // Minimum payload: accounts_count(4) + ix_data_len(4) + instruction_id(1) + target_program(32) = 41 + if len(payload) < 41 { + return nil, nil, 0, targetProgram, fmt.Errorf("payload too short: %d bytes (minimum 41)", len(payload)) } offset := 0 @@ -1119,7 +1094,7 @@ func decodePayload(payload []byte) ([]GatewayAccountMeta, []byte, uint64, uint8, accounts := make([]GatewayAccountMeta, accountsCount) for i := uint32(0); i < accountsCount; i++ { if offset+33 > len(payload) { - return nil, nil, 0, 0, fmt.Errorf("payload too short for account %d", i) + return nil, nil, 0, targetProgram, fmt.Errorf("payload too short for account %d", i) } var pubkey [32]byte copy(pubkey[:], payload[offset:offset+32]) @@ -1129,30 +1104,30 @@ func decodePayload(payload []byte) ([]GatewayAccountMeta, []byte, uint64, uint8, } if offset+4 > len(payload) { - return nil, nil, 0, 0, fmt.Errorf("payload too short for ix_data length") + return nil, nil, 0, targetProgram, fmt.Errorf("payload too short for ix_data length") } ixDataLen := binary.BigEndian.Uint32(payload[offset : offset+4]) offset += 4 if offset+int(ixDataLen) > len(payload) { - return nil, nil, 0, 0, fmt.Errorf("payload too short for ix_data") + return nil, nil, 0, targetProgram, fmt.Errorf("payload too short for ix_data") } ixData := make([]byte, ixDataLen) copy(ixData, payload[offset:offset+int(ixDataLen)]) offset += int(ixDataLen) - if offset+8 > len(payload) { - return nil, nil, 0, 0, fmt.Errorf("payload too short for rent_fee") - } - rentFee := binary.BigEndian.Uint64(payload[offset : offset+8]) - offset += 8 - if offset >= len(payload) { - return nil, nil, 0, 0, fmt.Errorf("payload too short for instruction_id") + return nil, nil, 0, targetProgram, fmt.Errorf("payload too short for instruction_id") } instructionID := payload[offset] + offset++ + + if offset+32 > len(payload) { + return nil, nil, 0, targetProgram, fmt.Errorf("payload too short for target_program") + } + copy(targetProgram[:], payload[offset:offset+32]) - return accounts, ixData, rentFee, instructionID, nil + return accounts, ixData, instructionID, targetProgram, nil } // accountsToWritableFlags bitpacks the writable flags for execute accounts into a compact byte array. @@ -1206,7 +1181,7 @@ func anchorDiscriminator(methodName string) []byte { // the finalize_universal_tx gateway function. // // This is the exact byte layout that the Anchor deserializer expects on-chain. -// The field order MUST match the Rust function signature in withdraw_execute.rs: +// The field order MUST match the Rust function signature: // // Offset Size Field Borsh Type // 0 8 discriminator sha256("global:finalize_universal_tx")[:8] @@ -1218,7 +1193,6 @@ func anchorDiscriminator(methodName string) []byte { // 101 4+N writable_flags Vec (4-byte LE length + data) // ... 4+M ix_data Vec (4-byte LE length + data) // ... 8 gas_fee u64 (little-endian) -// ... 8 rent_fee u64 (little-endian) // ... 64 signature [u8; 64] (TSS secp256k1 r||s) // ... 1 recovery_id u8 (ECDSA v value, 0-3) // ... 32 message_hash [u8; 32] (keccak256 of TSS message) @@ -1231,7 +1205,6 @@ func (tb *TxBuilder) buildWithdrawAndExecuteData( writableFlags []byte, ixData []byte, gasFee uint64, - rentFee uint64, signature []byte, recoveryID byte, messageHash []byte, @@ -1265,10 +1238,6 @@ func (tb *TxBuilder) buildWithdrawAndExecuteData( binary.LittleEndian.PutUint64(gasFeeBytes, gasFee) data = append(data, gasFeeBytes...) - rentFeeBytes := make([]byte, 8) - binary.LittleEndian.PutUint64(rentFeeBytes, rentFee) - data = append(data, rentFeeBytes...) - data = append(data, signature...) data = append(data, recoveryID) data = append(data, messageHash...) @@ -1277,39 +1246,31 @@ func (tb *TxBuilder) buildWithdrawAndExecuteData( } // buildRevertData constructs the Borsh-serialized instruction data for -// revert_universal_tx (id=3, native SOL) or revert_universal_tx_token (id=4, SPL). -// -// Both revert functions share the same parameter layout — only the discriminator differs. +// revert_universal_tx (unified for both SOL and SPL). // // Offset Size Field -// 0 8 discriminator (different for SOL vs SPL) -// 8 32 tx_id [u8; 32] +// 0 8 discriminator sha256("global:revert_universal_tx")[:8] +// 8 32 sub_tx_id [u8; 32] // 40 32 universal_tx_id [u8; 32] // 72 8 amount u64 (LE) -// 80 32 fund_recipient Pubkey — who gets the refund +// 80 32 revert_recipient Pubkey — who gets the refund // 112 4+N revert_msg Vec — human-readable revert reason // ... 8 gas_fee u64 (LE) // ... 64 signature [u8; 64] // ... 1 recovery_id u8 // ... 32 message_hash [u8; 32] func (tb *TxBuilder) buildRevertData( - instructionID uint8, txID [32]byte, universalTxID [32]byte, amount uint64, - fundRecipient solana.PublicKey, + revertRecipient solana.PublicKey, revertMsg []byte, gasFee uint64, signature []byte, recoveryID byte, messageHash []byte, ) []byte { - var discriminator []byte - if instructionID == 3 { - discriminator = anchorDiscriminator("revert_universal_tx") - } else { - discriminator = anchorDiscriminator("revert_universal_tx_token") - } + discriminator := anchorDiscriminator("revert_universal_tx") data := make([]byte, 0, 256) data = append(data, discriminator...) @@ -1320,8 +1281,8 @@ func (tb *TxBuilder) buildRevertData( binary.LittleEndian.PutUint64(amountBytes, amount) data = append(data, amountBytes...) - // RevertInstructions struct: { fund_recipient: Pubkey, revert_msg: Vec } - data = append(data, fundRecipient.Bytes()...) + // RevertInstructions struct: { revert_recipient: Pubkey, revert_msg: Vec } + data = append(data, revertRecipient.Bytes()...) revertMsgLen := make([]byte, 4) binary.LittleEndian.PutUint32(revertMsgLen, uint32(len(revertMsg))) data = append(data, revertMsgLen...) @@ -1338,6 +1299,49 @@ func (tb *TxBuilder) buildRevertData( return data } +// buildRescueData constructs the Borsh-serialized instruction data for rescue_funds. +// Unlike revert, rescue does NOT include RevertInstructions — the recipient comes from accounts. +// +// Offset Size Field +// 0 8 discriminator sha256("global:rescue_funds")[:8] +// 8 32 sub_tx_id [u8; 32] +// 40 32 universal_tx_id [u8; 32] +// 72 8 amount u64 (LE) +// 80 8 gas_fee u64 (LE) +// 88 64 signature [u8; 64] +// 152 1 recovery_id u8 +// 153 32 message_hash [u8; 32] +func (tb *TxBuilder) buildRescueData( + txID [32]byte, + universalTxID [32]byte, + amount uint64, + gasFee uint64, + signature []byte, + recoveryID byte, + messageHash []byte, +) []byte { + discriminator := anchorDiscriminator("rescue_funds") + + data := make([]byte, 0, 192) + data = append(data, discriminator...) + data = append(data, txID[:]...) + data = append(data, universalTxID[:]...) + + amountBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(amountBytes, amount) + data = append(data, amountBytes...) + + gasFeeBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(gasFeeBytes, gasFee) + data = append(data, gasFeeBytes...) + + data = append(data, signature...) + data = append(data, recoveryID) + data = append(data, messageHash...) + + return data +} + // ============================================================================= // Accounts List Builders // @@ -1534,76 +1538,92 @@ func (tb *TxBuilder) VerifyBroadcastedTx(ctx context.Context, txHash string) (fo // buildSetComputeUnitLimitInstruction creates a SetComputeUnitLimit instruction for the Compute Budget program // Instruction format: [1-byte instruction type (2 = SetComputeUnitLimit)] + [4-byte u32 units] -// buildRevertSOLAccounts builds the accounts list for revert_universal_tx (native SOL refund). +// buildRevertAccounts builds the unified accounts list for revert_universal_tx +// (handles both SOL and SPL). // -// Must match the RevertUniversalTx struct in revert.rs: +// Must match the RevertUniversalTx struct in the gateway IDL: // -// # Account Flags -// 1 config read-only -// 2 vault mut SOL vault (source of refund) -// 3 tss_pda mut TSS state -// 4 recipient mut Gets the SOL refund -// 5 executed_tx mut Replay protection (gets created) -// 6 caller signer,mut Relayer -// 7 system_program read-only -func (tb *TxBuilder) buildRevertSOLAccounts( +// # Account Flags Notes +// 1 config read-only Gateway config PDA +// 2 vault mut SOL vault PDA +// 3 fee_vault mut Fee vault PDA (relayer reimbursement) +// 4 tss_pda mut TSS state +// 5 recipient mut Gets the refund +// 6 executed_sub_tx mut Replay protection (gets created) +// 7 caller signer,mut Relayer +// 8 system_program read-only +// --- Optional SPL accounts (9-12) --- +// 9 token_vault mut/None Vault's ATA for the token +// 10 recipient_token_account mut/None Recipient's ATA +// 11 token_mint read/None The SPL token mint +// 12 token_program read/None SPL Token program +func (tb *TxBuilder) buildRevertAccounts( configPDA solana.PublicKey, vaultPDA solana.PublicKey, + feeVaultPDA solana.PublicKey, tssPDA solana.PublicKey, recipient solana.PublicKey, executedTxPDA solana.PublicKey, caller solana.PublicKey, + isNative bool, + mintPubkey solana.PublicKey, ) []*solana.AccountMeta { - return []*solana.AccountMeta{ + accounts := []*solana.AccountMeta{ {PublicKey: configPDA, IsWritable: false, IsSigner: false}, {PublicKey: vaultPDA, IsWritable: true, IsSigner: false}, + {PublicKey: feeVaultPDA, IsWritable: true, IsSigner: false}, {PublicKey: tssPDA, IsWritable: true, IsSigner: false}, {PublicKey: recipient, IsWritable: true, IsSigner: false}, {PublicKey: executedTxPDA, IsWritable: true, IsSigner: false}, {PublicKey: caller, IsWritable: true, IsSigner: true}, {PublicKey: solana.SystemProgramID, IsWritable: false, IsSigner: false}, } + + if isNative { + // SOL: optional SPL accounts are None (gateway program ID sentinel) + for i := 0; i < 4; i++ { + accounts = append(accounts, &solana.AccountMeta{PublicKey: tb.gatewayAddress, IsWritable: false, IsSigner: false}) + } + } else { + // SPL: derive and pass real ATAs + ataProgramID := solana.MustPublicKeyFromBase58("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL") + tokenVaultATA, _, _ := solana.FindProgramAddress( + [][]byte{vaultPDA.Bytes(), solana.TokenProgramID.Bytes(), mintPubkey.Bytes()}, + ataProgramID, + ) + recipientATA, _, _ := solana.FindProgramAddress( + [][]byte{recipient.Bytes(), solana.TokenProgramID.Bytes(), mintPubkey.Bytes()}, + ataProgramID, + ) + accounts = append(accounts, + &solana.AccountMeta{PublicKey: tokenVaultATA, IsWritable: true, IsSigner: false}, + &solana.AccountMeta{PublicKey: recipientATA, IsWritable: true, IsSigner: false}, + &solana.AccountMeta{PublicKey: mintPubkey, IsWritable: false, IsSigner: false}, + &solana.AccountMeta{PublicKey: solana.TokenProgramID, IsWritable: false, IsSigner: false}, + ) + } + + return accounts } -// buildRevertSPLAccounts builds the accounts list for revert_universal_tx_token (SPL token refund). -// -// Must match the RevertUniversalTxToken struct in revert.rs: -// -// # Account Flags -// 1 config read-only -// 2 vault mut SOL vault PDA (authority for token transfers) -// 3 token_vault mut Vault's ATA for the token (source of refund) -// 4 tss_pda mut TSS state -// 5 recipient_token_account mut Recipient's ATA (destination of refund) -// 6 token_mint read-only The SPL token mint -// 7 executed_tx mut Replay protection -// 8 caller signer,mut Relayer -// 9 vault_sol mut Same as vault, needed for gas_fee transfer -// 10 token_program read-only SPL Token program -// 11 system_program read-only -func (tb *TxBuilder) buildRevertSPLAccounts( +// buildRescueAccounts builds the accounts list for rescue_funds. +// Same layout as revert_universal_tx accounts. +func (tb *TxBuilder) buildRescueAccounts( configPDA solana.PublicKey, vaultPDA solana.PublicKey, - tokenVaultATA solana.PublicKey, + feeVaultPDA solana.PublicKey, tssPDA solana.PublicKey, - recipientATA solana.PublicKey, - tokenMint solana.PublicKey, + recipient solana.PublicKey, executedTxPDA solana.PublicKey, caller solana.PublicKey, + isNative bool, + mintPubkey solana.PublicKey, ) []*solana.AccountMeta { - return []*solana.AccountMeta{ - {PublicKey: configPDA, IsWritable: false, IsSigner: false}, - {PublicKey: vaultPDA, IsWritable: true, IsSigner: false}, - {PublicKey: tokenVaultATA, IsWritable: true, IsSigner: false}, - {PublicKey: tssPDA, IsWritable: true, IsSigner: false}, - {PublicKey: recipientATA, IsWritable: true, IsSigner: false}, - {PublicKey: tokenMint, IsWritable: false, IsSigner: false}, - {PublicKey: executedTxPDA, IsWritable: true, IsSigner: false}, - {PublicKey: caller, IsWritable: true, IsSigner: true}, - {PublicKey: vaultPDA, IsWritable: true, IsSigner: false}, // vault_sol = same PDA, needed for gas_fee - {PublicKey: solana.TokenProgramID, IsWritable: false, IsSigner: false}, - {PublicKey: solana.SystemProgramID, IsWritable: false, IsSigner: false}, - } + // Rescue uses the same account layout as revert + return tb.buildRevertAccounts( + configPDA, vaultPDA, feeVaultPDA, tssPDA, recipient, + executedTxPDA, caller, isNative, mintPubkey, + ) } // ============================================================================= diff --git a/universalClient/chains/svm/tx_builder_test.go b/universalClient/chains/svm/tx_builder_test.go index bfc62894..59884c52 100644 --- a/universalClient/chains/svm/tx_builder_test.go +++ b/universalClient/chains/svm/tx_builder_test.go @@ -8,7 +8,6 @@ import ( "encoding/binary" "encoding/hex" "fmt" - "math/big" "os" "path/filepath" "testing" @@ -58,15 +57,6 @@ func makeSender(fill byte) [20]byte { return s } -// makeToken returns a 32-byte token (Pubkey). Zero for native SOL. -func makeToken(fill byte) [32]byte { - var t [32]byte - for i := range t { - t[i] = fill - } - return t -} - // buildMockTSSPDAData builds a raw byte slice simulating a TssPda account. // Layout: discriminator(8) + tss_eth_address(20) + chain_id(Borsh String: 4 LE len + bytes) + authority(32) + bump(1) func buildMockTSSPDAData(tssAddr [20]byte, chainID string, authority [32]byte, bump byte) []byte { @@ -111,9 +101,9 @@ func signMessageHash(t *testing.T, key *ecdsa.PrivateKey, hash []byte) ([]byte, return sig[:64], sig[64] // signature (r||s), recovery_id (v) } -// buildMockExecutePayload builds a pre-encoded execute payload. -// Format: [u32 BE accounts_count][33 bytes per account (32 pubkey + 1 writable)][u32 BE ix_data_len][ix_data][u64 BE rent_fee] -func buildMockPayload(accounts []GatewayAccountMeta, ixData []byte, rentFee uint64, instructionID uint8) []byte { +// buildMockPayload builds a pre-encoded payload. +// Format: [u32 BE accounts_count][33 bytes per account (32 pubkey + 1 writable)][u32 BE ix_data_len][ix_data][instruction_id (u8)][target_program (32 bytes)] +func buildMockPayload(accounts []GatewayAccountMeta, ixData []byte, instructionID uint8, targetProgram [32]byte) []byte { payload := make([]byte, 0, 256) // accounts count (u32 BE) countBytes := make([]byte, 4) @@ -134,23 +124,21 @@ func buildMockPayload(accounts []GatewayAccountMeta, ixData []byte, rentFee uint payload = append(payload, ixLenBytes...) // ix_data payload = append(payload, ixData...) - // rent_fee (u64 BE) - rentFeeBytes := make([]byte, 8) - binary.BigEndian.PutUint64(rentFeeBytes, rentFee) - payload = append(payload, rentFeeBytes...) // instruction_id (u8) payload = append(payload, instructionID) + // target_program (32 bytes) + payload = append(payload, targetProgram[:]...) return payload } // buildMockExecutePayload is a convenience wrapper for execute payloads (instruction_id=2) -func buildMockExecutePayload(accounts []GatewayAccountMeta, ixData []byte, rentFee uint64) []byte { - return buildMockPayload(accounts, ixData, rentFee, 2) +func buildMockExecutePayload(accounts []GatewayAccountMeta, ixData []byte) []byte { + return buildMockPayload(accounts, ixData, 2, [32]byte{}) } // buildMockWithdrawPayload builds a withdraw payload (instruction_id=1, no accounts/ixData) func buildMockWithdrawPayload() []byte { - return buildMockPayload(nil, nil, 0, 1) + return buildMockPayload(nil, nil, 1, [32]byte{}) } // ============================================================ @@ -231,10 +219,6 @@ func TestNewTxBuilder(t *testing.T) { // TestDefaultComputeUnitLimit // ============================================================ -func TestDefaultComputeUnitLimit(t *testing.T) { - assert.Equal(t, uint32(200000), uint32(DefaultComputeUnitLimit)) -} - // ============================================================ // TestDeriveTSSPDA — seed must be "tsspda_v2" // ============================================================ @@ -340,7 +324,9 @@ func TestDetermineInstructionID(t *testing.T) { {"FUNDS_AND_PAYLOAD → 2 (execute)", uetypes.TxType_FUNDS_AND_PAYLOAD, true, 2, false}, {"GAS_AND_PAYLOAD → 2 (execute)", uetypes.TxType_GAS_AND_PAYLOAD, false, 2, false}, {"INBOUND_REVERT native → 3", uetypes.TxType_INBOUND_REVERT, true, 3, false}, - {"INBOUND_REVERT SPL → 4", uetypes.TxType_INBOUND_REVERT, false, 4, false}, + {"INBOUND_REVERT SPL → 3", uetypes.TxType_INBOUND_REVERT, false, 3, false}, + {"RESCUE_FUNDS native → 4", uetypes.TxType_RESCUE_FUNDS, true, 4, false}, + {"RESCUE_FUNDS SPL → 4", uetypes.TxType_RESCUE_FUNDS, false, 4, false}, {"UNSPECIFIED → error", uetypes.TxType_UNSPECIFIED_TX, true, 0, true}, {"GAS → error", uetypes.TxType_GAS, true, 0, true}, {"PAYLOAD → error", uetypes.TxType_PAYLOAD, true, 0, true}, @@ -369,7 +355,7 @@ func TestAnchorDiscriminator(t *testing.T) { }{ {"finalize_universal_tx"}, {"revert_universal_tx"}, - {"revert_universal_tx_token"}, + {"rescue_funds"}, } for _, tt := range tests { @@ -398,7 +384,7 @@ func TestConstructTSSMessage(t *testing.T) { txID := makeTxID(0xAA) utxID := makeTxID(0xBB) sender := makeSender(0xCC) - token := makeToken(0x00) // native SOL = zero + token := [32]byte{} // native SOL = zero target := makeTxID(0xDD) t.Run("withdraw (id=1) message format", func(t *testing.T) { @@ -406,7 +392,7 @@ func TestConstructTSSMessage(t *testing.T) { 1, "devnet", 1000000, txID, utxID, sender, token, 0, // gasFee - target, nil, nil, 0, + target, nil, nil, [32]byte{}, [32]byte{}, ) require.NoError(t, err) @@ -442,8 +428,8 @@ func TestConstructTSSMessage(t *testing.T) { hash, err := builder.constructTSSMessage( 2, "devnet", 2000000, txID, utxID, sender, token, - 100, // gasFee - target, accs, ixData, 500, // rentFee + 100, // gasFee + target, accs, ixData, [32]byte{}, [32]byte{}, ) require.NoError(t, err) @@ -479,10 +465,6 @@ func TestConstructTSSMessage(t *testing.T) { binary.BigEndian.PutUint32(ixLenBE, 4) msg = append(msg, ixLenBE...) msg = append(msg, 0xDE, 0xAD, 0xBE, 0xEF) - // rent_fee - rentBE := make([]byte, 8) - binary.BigEndian.PutUint64(rentBE, 500) - msg = append(msg, rentBE...) expected := crypto.Keccak256(msg) assert.Equal(t, expected, hash, "execute message hash mismatch") @@ -493,7 +475,7 @@ func TestConstructTSSMessage(t *testing.T) { hash, err := builder.constructTSSMessage( 3, "devnet", 500000, txID, utxID, sender, token, - 0, [32]byte{}, nil, nil, 0, + 0, [32]byte{}, nil, nil, revertRecipient, [32]byte{}, ) require.NoError(t, err) @@ -515,19 +497,19 @@ func TestConstructTSSMessage(t *testing.T) { assert.Equal(t, expected, hash, "revert SOL message hash mismatch") }) - t.Run("revert SPL (id=4) message format", func(t *testing.T) { + t.Run("revert SPL (id=3 with mint) message format", func(t *testing.T) { revertRecipient := makeTxID(0xEE) revertMint := makeTxID(0xFF) hash, err := builder.constructTSSMessage( - 4, "devnet", 750000, + 3, "devnet", 750000, txID, utxID, sender, token, - 0, [32]byte{}, nil, nil, 0, + 0, [32]byte{}, nil, nil, revertRecipient, revertMint, ) require.NoError(t, err) msg := []byte("PUSH_CHAIN_SVM") - msg = append(msg, 4) + msg = append(msg, 3) msg = append(msg, []byte("devnet")...) amountBE := make([]byte, 8) binary.BigEndian.PutUint64(amountBE, 750000) @@ -544,13 +526,69 @@ func TestConstructTSSMessage(t *testing.T) { assert.Equal(t, expected, hash, "revert SPL message hash mismatch") }) + t.Run("rescue SOL (id=4) message format", func(t *testing.T) { + rescueRecipient := makeTxID(0xEE) + hash, err := builder.constructTSSMessage( + 4, "devnet", 300000, + txID, utxID, sender, token, + 50, [32]byte{}, nil, nil, + rescueRecipient, [32]byte{}, + ) + require.NoError(t, err) + + msg := []byte("PUSH_CHAIN_SVM") + msg = append(msg, 4) + msg = append(msg, []byte("devnet")...) + amountBE := make([]byte, 8) + binary.BigEndian.PutUint64(amountBE, 300000) + msg = append(msg, amountBE...) + msg = append(msg, txID[:]...) + msg = append(msg, utxID[:]...) + msg = append(msg, rescueRecipient[:]...) + gasBE := make([]byte, 8) + binary.BigEndian.PutUint64(gasBE, 50) + msg = append(msg, gasBE...) + + expected := crypto.Keccak256(msg) + assert.Equal(t, expected, hash, "rescue SOL message hash mismatch") + }) + + t.Run("rescue SPL (id=4 with mint) message format", func(t *testing.T) { + rescueRecipient := makeTxID(0xEE) + rescueMint := makeTxID(0xFF) + hash, err := builder.constructTSSMessage( + 4, "devnet", 400000, + txID, utxID, sender, token, + 75, [32]byte{}, nil, nil, + rescueRecipient, rescueMint, + ) + require.NoError(t, err) + + msg := []byte("PUSH_CHAIN_SVM") + msg = append(msg, 4) + msg = append(msg, []byte("devnet")...) + amountBE := make([]byte, 8) + binary.BigEndian.PutUint64(amountBE, 400000) + msg = append(msg, amountBE...) + msg = append(msg, txID[:]...) + msg = append(msg, utxID[:]...) + msg = append(msg, rescueMint[:]...) + msg = append(msg, rescueRecipient[:]...) + gasBE := make([]byte, 8) + binary.BigEndian.PutUint64(gasBE, 75) + msg = append(msg, gasBE...) + + expected := crypto.Keccak256(msg) + assert.Equal(t, expected, hash, "rescue SPL message hash mismatch") + }) + t.Run("chain_id bytes go directly into message (no length prefix)", func(t *testing.T) { // Verify that the chain_id in the message is raw UTF-8, not Borsh-encoded chainID := "test_chain" hash1, err := builder.constructTSSMessage( 1, chainID, 0, [32]byte{}, [32]byte{}, [20]byte{}, [32]byte{}, - 0, [32]byte{}, nil, nil, 0, + 0, [32]byte{}, nil, nil, [32]byte{}, [32]byte{}, ) require.NoError(t, err) @@ -575,7 +613,7 @@ func TestConstructTSSMessage(t *testing.T) { _, err := builder.constructTSSMessage( 99, "devnet", 0, [32]byte{}, [32]byte{}, [20]byte{}, [32]byte{}, - 0, [32]byte{}, nil, nil, 0, + 0, [32]byte{}, nil, nil, [32]byte{}, [32]byte{}, ) assert.Error(t, err) @@ -594,7 +632,7 @@ func TestConstructTSSMessage_HashIsKeccak256(t *testing.T) { hash, err := builder.constructTSSMessage( 1, "x", 0, [32]byte{}, [32]byte{}, [20]byte{}, [32]byte{}, - 0, [32]byte{}, nil, nil, 0, + 0, [32]byte{}, nil, nil, [32]byte{}, [32]byte{}, ) require.NoError(t, err) @@ -623,10 +661,10 @@ func TestDecodePayload(t *testing.T) { {Pubkey: makeTxID(0x22), IsWritable: false}, } expectedIxData := []byte{0xAA, 0xBB, 0xCC} - expectedRentFee := uint64(12345) + expectedTarget := makeTxID(0xDD) - payload := buildMockPayload(expectedAccounts, expectedIxData, expectedRentFee, 2) - accounts, ixData, rentFee, instructionID, err := decodePayload(payload) + payload := buildMockPayload(expectedAccounts, expectedIxData, 2, expectedTarget) + accounts, ixData, instructionID, targetProgram, err := decodePayload(payload) require.NoError(t, err) assert.Equal(t, uint8(2), instructionID) @@ -636,28 +674,28 @@ func TestDecodePayload(t *testing.T) { assert.Equal(t, expectedAccounts[1].Pubkey, accounts[1].Pubkey) assert.False(t, accounts[1].IsWritable) assert.Equal(t, expectedIxData, ixData) - assert.Equal(t, expectedRentFee, rentFee) + assert.Equal(t, expectedTarget, targetProgram) }) t.Run("decodes withdraw payload (0 accounts)", func(t *testing.T) { payload := buildMockWithdrawPayload() - accounts, ixData, rentFee, instructionID, err := decodePayload(payload) + accounts, ixData, instructionID, _, err := decodePayload(payload) require.NoError(t, err) assert.Equal(t, uint8(1), instructionID) assert.Len(t, accounts, 0) assert.Len(t, ixData, 0) - assert.Equal(t, uint64(0), rentFee) }) t.Run("decodes payload with empty ix_data", func(t *testing.T) { accs := []GatewayAccountMeta{{Pubkey: makeTxID(0x33), IsWritable: true}} - payload := buildMockPayload(accs, nil, 999, 2) - accounts, ixData, rentFee, instructionID, err := decodePayload(payload) + expectedTarget := makeTxID(0xEE) + payload := buildMockPayload(accs, nil, 2, expectedTarget) + accounts, ixData, instructionID, targetProgram, err := decodePayload(payload) require.NoError(t, err) assert.Equal(t, uint8(2), instructionID) assert.Len(t, accounts, 1) assert.Len(t, ixData, 0) - assert.Equal(t, uint64(999), rentFee) + assert.Equal(t, expectedTarget, targetProgram) }) t.Run("rejects too-short payload", func(t *testing.T) { @@ -756,7 +794,7 @@ func TestBuildWithdrawAndExecuteData(t *testing.T) { data := builder.buildWithdrawAndExecuteData( 1, txID, utxID, 1000000, sender, []byte{}, []byte{}, // empty writable_flags and ix_data for withdraw - 0, 0, // gasFee, rentFee + 0, // gasFee sig, 2, msgHash, ) @@ -788,20 +826,18 @@ func TestBuildWithdrawAndExecuteData(t *testing.T) { // Check gas_fee (u64 LE) assert.Equal(t, uint64(0), binary.LittleEndian.Uint64(data[109:117]), "gas_fee") - // Check rent_fee (u64 LE) - assert.Equal(t, uint64(0), binary.LittleEndian.Uint64(data[117:125]), "rent_fee") - - // Check signature - assert.Equal(t, sig, data[125:189], "signature") + // Check signature (no more rent_fee — directly after gas_fee) + assert.Equal(t, sig, data[117:181], "signature") // Check recovery_id - assert.Equal(t, byte(2), data[189], "recovery_id") + assert.Equal(t, byte(2), data[181], "recovery_id") // Check message_hash - assert.Equal(t, msgHash, data[190:222], "message_hash") + assert.Equal(t, msgHash, data[182:214], "message_hash") - // Total length (no nonce at end) - assert.Len(t, data, 222) + // Total length: 8(disc) + 1(id) + 32(txid) + 32(utxid) + 8(amt) + 20(sender) + // + 4(wf_len) + 0(wf) + 4(ix_len) + 0(ix) + 8(gas) + 64(sig) + 1(recov) + 32(hash) = 214 + assert.Len(t, data, 214) }) t.Run("execute (id=2) with accounts and ix_data", func(t *testing.T) { @@ -811,7 +847,7 @@ func TestBuildWithdrawAndExecuteData(t *testing.T) { data := builder.buildWithdrawAndExecuteData( 2, txID, utxID, 500, sender, wf, ixData, - 100, 50, // gasFee, rentFee + 100, // gasFee sig, 0, msgHash, ) @@ -837,11 +873,7 @@ func TestBuildWithdrawAndExecuteData(t *testing.T) { assert.Equal(t, uint64(100), binary.LittleEndian.Uint64(data[offset:offset+8])) offset += 8 - // rent_fee - assert.Equal(t, uint64(50), binary.LittleEndian.Uint64(data[offset:offset+8])) - offset += 8 - - // signature + recovery_id + message_hash + // signature + recovery_id + message_hash (no more rent_fee) assert.Equal(t, sig, data[offset:offset+64]) offset += 64 assert.Equal(t, byte(0), data[offset]) @@ -863,31 +895,68 @@ func TestBuildRevertData(t *testing.T) { sig := make([]byte, 64) msgHash := make([]byte, 32) - t.Run("revert SOL (id=3) uses correct discriminator", func(t *testing.T) { - data := builder.buildRevertData(3, txID, utxID, 1000, recipient, revertMsg, 0, sig, 1, msgHash) + t.Run("revert uses correct discriminator (revert_universal_tx)", func(t *testing.T) { + data := builder.buildRevertData(txID, utxID, 1000, recipient, revertMsg, 0, sig, 1, msgHash) expectedDisc := anchorDiscriminator("revert_universal_tx") assert.Equal(t, expectedDisc, data[:8]) assert.Equal(t, txID[:], data[8:40]) assert.Equal(t, utxID[:], data[40:72]) assert.Equal(t, uint64(1000), binary.LittleEndian.Uint64(data[72:80])) - // revert_instruction: fund_recipient(32) + revert_msg Vec(4+N) + // revert_instruction: revert_recipient(32) + revert_msg Vec(4+N) assert.Equal(t, recipient.Bytes(), data[80:112]) assert.Equal(t, uint32(len(revertMsg)), binary.LittleEndian.Uint32(data[112:116])) assert.Equal(t, revertMsg, data[116:116+len(revertMsg)]) }) - t.Run("revert SPL (id=4) uses correct discriminator", func(t *testing.T) { - data := builder.buildRevertData(4, txID, utxID, 2000, recipient, nil, 0, sig, 0, msgHash) + t.Run("revert with empty revert_msg", func(t *testing.T) { + data := builder.buildRevertData(txID, utxID, 2000, recipient, nil, 0, sig, 0, msgHash) - expectedDisc := anchorDiscriminator("revert_universal_tx_token") + expectedDisc := anchorDiscriminator("revert_universal_tx") assert.Equal(t, expectedDisc, data[:8]) // revert_msg should be empty Vec (len=0) - offset := 112 // after tx_id(32) + utx_id(32) + amount(8) + fund_recipient(32) + offset := 112 // after tx_id(32) + utx_id(32) + amount(8) + revert_recipient(32) assert.Equal(t, uint32(0), binary.LittleEndian.Uint32(data[offset:offset+4])) }) } +// ============================================================ +// TestBuildRescueData +// ============================================================ + +func TestBuildRescueData(t *testing.T) { + builder := newTestBuilder(t) + txID := makeTxID(0x01) + utxID := makeTxID(0x02) + sig := make([]byte, 64) + msgHash := make([]byte, 32) + + t.Run("rescue uses correct discriminator", func(t *testing.T) { + data := builder.buildRescueData(txID, utxID, 5000, 100, sig, 1, msgHash) + + expectedDisc := anchorDiscriminator("rescue_funds") + assert.Equal(t, expectedDisc, data[:8], "discriminator") + assert.Equal(t, txID[:], data[8:40], "tx_id") + assert.Equal(t, utxID[:], data[40:72], "universal_tx_id") + assert.Equal(t, uint64(5000), binary.LittleEndian.Uint64(data[72:80]), "amount") + assert.Equal(t, uint64(100), binary.LittleEndian.Uint64(data[80:88]), "gas_fee") + assert.Equal(t, sig, data[88:152], "signature") + assert.Equal(t, byte(1), data[152], "recovery_id") + assert.Equal(t, msgHash, data[153:185], "message_hash") + // Total: 8(disc) + 32(txid) + 32(utxid) + 8(amount) + 8(gasFee) + 64(sig) + 1(recov) + 32(hash) = 185 + assert.Len(t, data, 185) + }) + + t.Run("rescue has no revert instructions (unlike revert)", func(t *testing.T) { + rescueData := builder.buildRescueData(txID, utxID, 1000, 50, sig, 0, msgHash) + revertRecipient := solana.MustPublicKeyFromBase58(testGatewayAddress) + revertData := builder.buildRevertData(txID, utxID, 1000, revertRecipient, nil, 50, sig, 0, msgHash) + + // Rescue should be shorter than revert (no recipient + revert_msg fields) + assert.Less(t, len(rescueData), len(revertData), "rescue data should be shorter than revert data") + }) +} + // ============================================================ // TestBuildWithdrawAndExecuteAccounts — accounts list // ============================================================ @@ -994,61 +1063,101 @@ func TestBuildWithdrawAndExecuteAccounts(t *testing.T) { // TestBuildRevertAccounts // ============================================================ -func TestBuildRevertSOLAccounts(t *testing.T) { +func TestBuildRevertAccounts(t *testing.T) { builder := newTestBuilder(t) config := solana.NewWallet().PublicKey() vault := solana.NewWallet().PublicKey() + feeVault := solana.NewWallet().PublicKey() tss := solana.NewWallet().PublicKey() recipient := solana.NewWallet().PublicKey() executed := solana.NewWallet().PublicKey() caller := solana.NewWallet().PublicKey() + tokenMint := solana.NewWallet().PublicKey() + + t.Run("SOL revert has 12 accounts (8 required + 4 None sentinels)", func(t *testing.T) { + accounts := builder.buildRevertAccounts(config, vault, feeVault, tss, recipient, executed, caller, true, solana.PublicKey{}) + + assert.Len(t, accounts, 12) + assert.Equal(t, config, accounts[0].PublicKey, "config") + assert.False(t, accounts[0].IsWritable) + assert.Equal(t, vault, accounts[1].PublicKey, "vault") + assert.True(t, accounts[1].IsWritable) + assert.Equal(t, feeVault, accounts[2].PublicKey, "fee_vault") + assert.True(t, accounts[2].IsWritable) + assert.Equal(t, tss, accounts[3].PublicKey, "tss_pda") + assert.True(t, accounts[3].IsWritable) + assert.Equal(t, recipient, accounts[4].PublicKey, "recipient") + assert.True(t, accounts[4].IsWritable) + assert.Equal(t, executed, accounts[5].PublicKey, "executed_tx") + assert.True(t, accounts[5].IsWritable) + assert.Equal(t, caller, accounts[6].PublicKey, "caller") + assert.True(t, accounts[6].IsSigner) + assert.Equal(t, solana.SystemProgramID, accounts[7].PublicKey, "system_program") + // SOL: 4 optional SPL accounts are gateway sentinel (None) + for i := 8; i < 12; i++ { + assert.Equal(t, builder.gatewayAddress, accounts[i].PublicKey, "SOL sentinel account %d", i) + } + }) - accounts := builder.buildRevertSOLAccounts(config, vault, tss, recipient, executed, caller) - - assert.Len(t, accounts, 7) - assert.Equal(t, config, accounts[0].PublicKey, "config") - assert.Equal(t, vault, accounts[1].PublicKey, "vault") - assert.True(t, accounts[1].IsWritable) - assert.Equal(t, tss, accounts[2].PublicKey, "tss_pda") - assert.True(t, accounts[2].IsWritable) - assert.Equal(t, recipient, accounts[3].PublicKey, "recipient") - assert.True(t, accounts[3].IsWritable) - assert.Equal(t, executed, accounts[4].PublicKey, "executed_tx") - assert.True(t, accounts[4].IsWritable) - assert.Equal(t, caller, accounts[5].PublicKey, "caller") - assert.True(t, accounts[5].IsSigner) - assert.Equal(t, solana.SystemProgramID, accounts[6].PublicKey, "system_program") + t.Run("SPL revert has 12 accounts (8 required + 4 SPL accounts)", func(t *testing.T) { + accounts := builder.buildRevertAccounts(config, vault, feeVault, tss, recipient, executed, caller, false, tokenMint) + + assert.Len(t, accounts, 12) + // First 8 same as SOL + assert.Equal(t, config, accounts[0].PublicKey, "config") + assert.Equal(t, vault, accounts[1].PublicKey, "vault") + assert.Equal(t, feeVault, accounts[2].PublicKey, "fee_vault") + assert.Equal(t, tss, accounts[3].PublicKey, "tss_pda") + assert.Equal(t, recipient, accounts[4].PublicKey, "recipient") + assert.Equal(t, executed, accounts[5].PublicKey, "executed_tx") + assert.Equal(t, caller, accounts[6].PublicKey, "caller") + assert.Equal(t, solana.SystemProgramID, accounts[7].PublicKey, "system_program") + // SPL: token_vault, recipient_token_account, token_mint, token_program + assert.True(t, accounts[8].IsWritable, "token_vault should be writable") + assert.True(t, accounts[9].IsWritable, "recipient_token_account should be writable") + assert.Equal(t, tokenMint, accounts[10].PublicKey, "token_mint") + assert.Equal(t, solana.TokenProgramID, accounts[11].PublicKey, "token_program") + }) } -func TestBuildRevertSPLAccounts(t *testing.T) { +// ============================================================ +// TestBuildRescueAccounts +// ============================================================ + +func TestBuildRescueAccounts(t *testing.T) { builder := newTestBuilder(t) config := solana.NewWallet().PublicKey() vault := solana.NewWallet().PublicKey() - tokenVault := solana.NewWallet().PublicKey() + feeVault := solana.NewWallet().PublicKey() tss := solana.NewWallet().PublicKey() - recipientATA := solana.NewWallet().PublicKey() - tokenMint := solana.NewWallet().PublicKey() + recipient := solana.NewWallet().PublicKey() executed := solana.NewWallet().PublicKey() caller := solana.NewWallet().PublicKey() + tokenMint := solana.NewWallet().PublicKey() + + t.Run("rescue delegates to buildRevertAccounts (same layout)", func(t *testing.T) { + rescueAccounts := builder.buildRescueAccounts(config, vault, feeVault, tss, recipient, executed, caller, true, solana.PublicKey{}) + revertAccounts := builder.buildRevertAccounts(config, vault, feeVault, tss, recipient, executed, caller, true, solana.PublicKey{}) + + assert.Len(t, rescueAccounts, len(revertAccounts)) + for i := range rescueAccounts { + assert.Equal(t, revertAccounts[i].PublicKey, rescueAccounts[i].PublicKey, "account %d pubkey", i) + assert.Equal(t, revertAccounts[i].IsWritable, rescueAccounts[i].IsWritable, "account %d writable", i) + assert.Equal(t, revertAccounts[i].IsSigner, rescueAccounts[i].IsSigner, "account %d signer", i) + } + }) - accounts := builder.buildRevertSPLAccounts(config, vault, tokenVault, tss, recipientATA, tokenMint, executed, caller) - - assert.Len(t, accounts, 11) - assert.Equal(t, config, accounts[0].PublicKey, "config") - assert.Equal(t, vault, accounts[1].PublicKey, "vault") - assert.Equal(t, tokenVault, accounts[2].PublicKey, "token_vault") - assert.True(t, accounts[2].IsWritable) - assert.Equal(t, tss, accounts[3].PublicKey, "tss_pda") - assert.Equal(t, recipientATA, accounts[4].PublicKey, "recipient_token_account") - assert.Equal(t, tokenMint, accounts[5].PublicKey, "token_mint") - assert.Equal(t, executed, accounts[6].PublicKey, "executed_tx") - assert.Equal(t, caller, accounts[7].PublicKey, "caller") - assert.True(t, accounts[7].IsSigner) - assert.Equal(t, vault, accounts[8].PublicKey, "vault_sol (same as vault)") - assert.Equal(t, solana.TokenProgramID, accounts[9].PublicKey, "token_program") - assert.Equal(t, solana.SystemProgramID, accounts[10].PublicKey, "system_program") + t.Run("rescue SPL matches revert SPL layout", func(t *testing.T) { + rescueAccounts := builder.buildRescueAccounts(config, vault, feeVault, tss, recipient, executed, caller, false, tokenMint) + revertAccounts := builder.buildRevertAccounts(config, vault, feeVault, tss, recipient, executed, caller, false, tokenMint) + + assert.Len(t, rescueAccounts, len(revertAccounts)) + for i := range rescueAccounts { + assert.Equal(t, revertAccounts[i].PublicKey, rescueAccounts[i].PublicKey, "account %d pubkey", i) + } + }) } // ============================================================ @@ -1087,6 +1196,7 @@ func TestParseTxType(t *testing.T) { {"FUNDS_AND_PAYLOAD", uetypes.TxType_FUNDS_AND_PAYLOAD, false}, {"GAS_AND_PAYLOAD", uetypes.TxType_GAS_AND_PAYLOAD, false}, {"INBOUND_REVERT", uetypes.TxType_INBOUND_REVERT, false}, + {"RESCUE_FUNDS", uetypes.TxType_RESCUE_FUNDS, false}, {"1", uetypes.TxType(1), false}, {"3", uetypes.TxType(3), false}, {"invalid", uetypes.TxType_UNSPECIFIED_TX, true}, @@ -1138,53 +1248,6 @@ func TestGatewayAccountMetaStruct(t *testing.T) { assert.True(t, meta.IsWritable) } -// ============================================================ -// TestGasLimitParsing -// ============================================================ - -func TestGasLimitParsing(t *testing.T) { - tests := []struct { - name string - gasLimit string - expected uint32 - }{ - {"empty → default", "", DefaultComputeUnitLimit}, - {"zero → default", "0", DefaultComputeUnitLimit}, - {"valid", "300000", 300000}, - {"invalid number → default", "abc", DefaultComputeUnitLimit}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var result uint32 - if tt.gasLimit == "" || tt.gasLimit == "0" { - result = DefaultComputeUnitLimit - } else { - parsed, err := parseUint32(tt.gasLimit) - if err != nil { - result = DefaultComputeUnitLimit - } else { - result = parsed - } - } - assert.Equal(t, tt.expected, result) - }) - } -} - -func parseUint32(s string) (uint32, error) { - val, err := parseUint64(s) - if err != nil { - return 0, err - } - return uint32(val), nil -} - -func parseUint64(s string) (uint64, error) { - var val uint64 - _, err := fmt.Sscanf(s, "%d", &val) - return val, err -} - // ============================================================ // TestEndToEndMessageAndDataConsistency // ============================================================ @@ -1203,7 +1266,7 @@ func TestEndToEndWithdrawMessageAndData(t *testing.T) { msgHash, err := builder.constructTSSMessage( 1, "devnet", 1000000, txID, utxID, sender, token, - 0, target, nil, nil, 0, + 0, target, nil, nil, [32]byte{}, [32]byte{}, ) require.NoError(t, err) @@ -1211,15 +1274,15 @@ func TestEndToEndWithdrawMessageAndData(t *testing.T) { sig := make([]byte, 64) instrData := builder.buildWithdrawAndExecuteData( 1, txID, utxID, 1000000, sender, - []byte{}, []byte{}, 0, 0, + []byte{}, []byte{}, 0, sig, 0, msgHash, ) // Extract message_hash from instruction data // Offset: 8(disc) + 1(id) + 32(txid) + 32(utxid) + 8(amount) + 20(sender) - // + 4(wf_len) + 0(wf) + 4(ix_len) + 0(ix) + 8(gas) + 8(rent) + 64(sig) + 1(recov) - // = 190 - msgHashFromData := instrData[190:222] + // + 4(wf_len) + 0(wf) + 4(ix_len) + 0(ix) + 8(gas) + 64(sig) + 1(recov) + // = 182 + msgHashFromData := instrData[182:214] assert.Equal(t, msgHash, msgHashFromData, "message_hash in instruction data must match TSS message hash") } @@ -1229,7 +1292,7 @@ func TestEndToEndWithdrawMessageAndData(t *testing.T) { func TestAnchorDiscriminatorKnownValues(t *testing.T) { // Verify discriminator values are deterministic and can be independently computed - for _, method := range []string{"finalize_universal_tx", "revert_universal_tx", "revert_universal_tx_token"} { + for _, method := range []string{"finalize_universal_tx", "revert_universal_tx", "rescue_funds"} { disc := anchorDiscriminator(method) h := sha256.Sum256([]byte("global:" + method)) assert.Equal(t, h[:8], disc, "discriminator for %s", method) @@ -1263,7 +1326,7 @@ func TestEndToEndWithRealSignature(t *testing.T) { msgHash, err := builder.constructTSSMessage( 1, "devnet", amount, txID, utxID, sender, token, - 0, target, nil, nil, 0, + 0, target, nil, nil, [32]byte{}, [32]byte{}, ) require.NoError(t, err) @@ -1274,14 +1337,16 @@ func TestEndToEndWithRealSignature(t *testing.T) { // 3. Build instruction data with real signature instrData := builder.buildWithdrawAndExecuteData( 1, txID, utxID, amount, sender, - []byte{}, []byte{}, 0, 0, + []byte{}, []byte{}, 0, sig, recoveryID, msgHash, ) // 4. Verify the instruction data contains the real signature - assert.Equal(t, sig, instrData[125:189], "real signature in instruction data") - assert.Equal(t, recoveryID, instrData[189], "recovery ID in instruction data") - assert.Equal(t, msgHash, instrData[190:222], "message hash in instruction data") + // Offset: 8(disc) + 1(id) + 32(txid) + 32(utxid) + 8(amt) + 20(sender) + // + 4(wf_len) + 0(wf) + 4(ix_len) + 0(ix) + 8(gas) = 117 + assert.Equal(t, sig, instrData[117:181], "real signature in instruction data") + assert.Equal(t, recoveryID, instrData[181], "recovery ID in instruction data") + assert.Equal(t, msgHash, instrData[182:214], "message hash in instruction data") }) t.Run("execute flow with real signature", func(t *testing.T) { @@ -1290,12 +1355,11 @@ func TestEndToEndWithRealSignature(t *testing.T) { {Pubkey: makeTxID(0x11), IsWritable: true}, } ixData := []byte{0xDE, 0xAD} - rentFee := uint64(5000) msgHash, err := builder.constructTSSMessage( 2, "devnet", amount, txID, utxID, sender, token, - 0, target, accs, ixData, rentFee, + 0, target, accs, ixData, [32]byte{}, [32]byte{}, ) require.NoError(t, err) @@ -1306,14 +1370,14 @@ func TestEndToEndWithRealSignature(t *testing.T) { instrData := builder.buildWithdrawAndExecuteData( 2, txID, utxID, amount, sender, wf, ixData, - 0, rentFee, + 0, sig, recoveryID, msgHash, ) // Verify instruction data length includes variable-length fields // 8(disc) + 1(id) + 32(txid) + 32(utxid) + 8(amt) + 20(sender) - // + 4+1(wf) + 4+2(ix) + 8(gas) + 8(rent) + 64(sig) + 1(recov) + 32(hash) - expectedLen := 8 + 1 + 32 + 32 + 8 + 20 + 5 + 6 + 8 + 8 + 64 + 1 + 32 + // + 4+1(wf) + 4+2(ix) + 8(gas) + 64(sig) + 1(recov) + 32(hash) + expectedLen := 8 + 1 + 32 + 32 + 8 + 20 + 5 + 6 + 8 + 64 + 1 + 32 assert.Len(t, instrData, expectedLen) }) @@ -1324,7 +1388,7 @@ func TestEndToEndWithRealSignature(t *testing.T) { msgHash, err := builder.constructTSSMessage( 3, "devnet", amount, txID, utxID, sender, token, - 0, [32]byte{}, nil, nil, 0, + 0, [32]byte{}, nil, nil, revertRecipient, [32]byte{}, ) require.NoError(t, err) @@ -1333,7 +1397,7 @@ func TestEndToEndWithRealSignature(t *testing.T) { recipient := solana.PublicKeyFromBytes(revertRecipient[:]) instrData := builder.buildRevertData( - 3, txID, utxID, amount, recipient, + txID, utxID, amount, recipient, []byte("revert msg"), 0, sig, recoveryID, msgHash, ) @@ -1342,6 +1406,33 @@ func TestEndToEndWithRealSignature(t *testing.T) { expectedDisc := anchorDiscriminator("revert_universal_tx") assert.Equal(t, expectedDisc, instrData[:8]) }) + + t.Run("rescue SOL flow with real signature", func(t *testing.T) { + amount := uint64(200000) + rescueRecipient := makeTxID(0xEE) + + msgHash, err := builder.constructTSSMessage( + 4, "devnet", amount, + txID, utxID, sender, token, + 50, [32]byte{}, nil, nil, + rescueRecipient, [32]byte{}, + ) + require.NoError(t, err) + + sig, recoveryID := signMessageHash(t, evmKey, msgHash) + + instrData := builder.buildRescueData( + txID, utxID, amount, 50, + sig, recoveryID, msgHash, + ) + + // Verify discriminator is for rescue_funds + expectedDisc := anchorDiscriminator("rescue_funds") + assert.Equal(t, expectedDisc, instrData[:8]) + + // Verify total length: 8(disc) + 32(txid) + 32(utxid) + 8(amt) + 8(gas) + 64(sig) + 1(recov) + 32(hash) = 185 + assert.Len(t, instrData, 185) + }) } // ============================================================ @@ -1461,7 +1552,7 @@ func buildAndSimulate(t *testing.T, rpcClient *RPCClient, builder *TxBuilder, da defer cancel() // Step 1: Build signing request (fetches chain ID from on-chain TSS PDA) - req, err := builder.GetOutboundSigningRequest(ctx, data, big.NewInt(1000), 0) + req, err := builder.GetOutboundSigningRequest(ctx, data, 0) if err != nil { return nil, fmt.Errorf("GetOutboundSigningRequest: %w", err) } @@ -1539,7 +1630,7 @@ func TestSimulate_Execute_NativeSOL(t *testing.T) { // It accepts any UTF-8 data with no required accounts, making it ideal for // CPI testing without needing initialized state on devnet. ixData := []byte("hello from push chain") - payload := buildMockExecutePayload(nil, ixData, 0) + payload := buildMockExecutePayload(nil, ixData) payloadHex := "0x" + hex.EncodeToString(payload) // Recipient = Memo program (becomes destination_program in execute mode) @@ -1557,7 +1648,7 @@ func TestSimulate_Execute_SPLToken(t *testing.T) { // Use the SPL Memo program as the execute destination (same as SOL test above). ixData := []byte("spl execute memo") - payload := buildMockExecutePayload(nil, ixData, 0) + payload := buildMockExecutePayload(nil, ixData) payloadHex := "0x" + hex.EncodeToString(payload) // Recipient = Memo program (becomes destination_program in execute mode) @@ -1592,3 +1683,144 @@ func TestSimulate_Revert_SPLToken(t *testing.T) { require.NoError(t, err) requireSimulationSuccess(t, result) } + +// ---- Rescue ---- + +// buildAndSimulateRescue constructs a rescue_funds transaction and simulates it on devnet. +func buildAndSimulateRescue(t *testing.T, rpcClient *RPCClient, builder *TxBuilder, evmKey *ecdsa.PrivateKey, amount uint64, assetAddr string) *rpc.SimulateTransactionResult { + t.Helper() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + _, ethAddrHex := loadTestEVMKey(t) + recipientWallet := solana.NewWallet() + + txIDBytes := make([]byte, 32) + utxIDBytes := make([]byte, 32) + _, err := crand.Read(txIDBytes) + require.NoError(t, err) + _, err = crand.Read(utxIDBytes) + require.NoError(t, err) + + var txID, universalTxID [32]byte + copy(txID[:], txIDBytes) + copy(universalTxID[:], utxIDBytes) + + var sender [20]byte + senderBytes, err := hex.DecodeString(ethAddrHex) + require.NoError(t, err) + copy(sender[:], senderBytes) + + isNative := assetAddr == "" + var token [32]byte + var mintPubkey solana.PublicKey + if !isNative { + mintPubkey, err = solana.PublicKeyFromBase58(assetAddr) + require.NoError(t, err) + copy(token[:], mintPubkey.Bytes()) + } + + recipientPubkey := recipientWallet.PublicKey() + + // Fetch chain ID from TSS PDA + tssPDA, err := builder.deriveTSSPDA() + require.NoError(t, err) + chainID, err := builder.fetchTSSChainID(ctx, tssPDA) + require.NoError(t, err) + + // Construct TSS message for rescue (id=4) + var revertRecipient [32]byte + copy(revertRecipient[:], recipientPubkey.Bytes()) + var revertMint [32]byte + if !isNative { + copy(revertMint[:], token[:]) + } + + gasFee := uint64(0) + messageHash, err := builder.constructTSSMessage( + 4, chainID, amount, + txID, universalTxID, sender, token, gasFee, + [32]byte{}, nil, nil, + revertRecipient, revertMint, + ) + require.NoError(t, err) + + sig, recoveryID := signMessageHash(t, evmKey, messageHash) + + instructionData := builder.buildRescueData(txID, universalTxID, amount, gasFee, sig, recoveryID, messageHash) + + // Derive PDAs + configPDA, _, err := solana.FindProgramAddress([][]byte{[]byte("config")}, builder.gatewayAddress) + require.NoError(t, err) + vaultPDA, _, err := solana.FindProgramAddress([][]byte{[]byte("vault")}, builder.gatewayAddress) + require.NoError(t, err) + feeVaultPDA, _, err := solana.FindProgramAddress([][]byte{[]byte("fee_vault")}, builder.gatewayAddress) + require.NoError(t, err) + executedTxPDA, _, err := solana.FindProgramAddress([][]byte{[]byte("executed_sub_tx"), txID[:]}, builder.gatewayAddress) + require.NoError(t, err) + + relayerKeypair, err := builder.loadRelayerKeypair() + require.NoError(t, err) + + accounts := builder.buildRescueAccounts( + configPDA, vaultPDA, feeVaultPDA, tssPDA, recipientPubkey, + executedTxPDA, relayerKeypair.PublicKey(), + isNative, mintPubkey, + ) + + gatewayIx := solana.NewInstruction(builder.gatewayAddress, accounts, instructionData) + computeLimitIx := builder.buildSetComputeUnitLimitInstruction(400000) + + instructions := []solana.Instruction{computeLimitIx} + if !isNative { + createATAIx := builder.buildCreateATAIdempotentInstruction( + relayerKeypair.PublicKey(), recipientPubkey, mintPubkey, + ) + instructions = append(instructions, createATAIx) + } + instructions = append(instructions, gatewayIx) + + recentBlockhash, err := rpcClient.GetRecentBlockhash(ctx) + require.NoError(t, err) + + tx, err := solana.NewTransaction( + instructions, recentBlockhash, + solana.TransactionPayer(relayerKeypair.PublicKey()), + ) + require.NoError(t, err) + + _, err = tx.Sign(func(key solana.PublicKey) *solana.PrivateKey { + if key.Equals(relayerKeypair.PublicKey()) { + privKey := relayerKeypair + return &privKey + } + return nil + }) + require.NoError(t, err) + + result, err := rpcClient.SimulateTransaction(ctx, tx) + require.NoError(t, err, "SimulateTransaction RPC call failed") + + return result +} + +func TestSimulate_Rescue_NativeSOL(t *testing.T) { + rpcClient, builder := setupDevnetSimulation(t) + defer rpcClient.Close() + + evmKey, _ := loadTestEVMKey(t) + + result := buildAndSimulateRescue(t, rpcClient, builder, evmKey, 10000000, "") + requireSimulationSuccess(t, result) +} + +func TestSimulate_Rescue_SPLToken(t *testing.T) { + rpcClient, builder := setupDevnetSimulation(t) + defer rpcClient.Close() + + evmKey, _ := loadTestEVMKey(t) + + result := buildAndSimulateRescue(t, rpcClient, builder, evmKey, 500000, devnetSPLMint) + requireSimulationSuccess(t, result) +} diff --git a/universalClient/constant/constant.go b/universalClient/constant/constant.go index 82f6bdd1..ffd74d98 100644 --- a/universalClient/constant/constant.go +++ b/universalClient/constant/constant.go @@ -27,7 +27,7 @@ var DefaultNodeHome = os.ExpandEnv("$HOME/") + NodeDir // These messages are executed on behalf of the core validator by the grantee (hotkey of the Universal Validator). var RequiredMsgGrants = []string{ "/uexecutor.v1.MsgVoteInbound", - "/uexecutor.v1.MsgVoteGasPrice", + "/uexecutor.v1.MsgVoteChainMeta", "/uexecutor.v1.MsgVoteOutbound", "/utss.v1.MsgVoteTssKeyProcess", } diff --git a/universalClient/pushsigner/grant_verifier.go b/universalClient/pushsigner/grant_verifier.go index ed764dca..6b1e0c2d 100644 --- a/universalClient/pushsigner/grant_verifier.go +++ b/universalClient/pushsigner/grant_verifier.go @@ -87,7 +87,7 @@ func validateKeysAndGrants(keyringBackend config.KeyringBackend, keyringPassword // Verify grants against the specified granter authorizedMsgs, err := verifyGrants(grants, granter) if err != nil { - return nil, err + return nil, fmt.Errorf("%w (grantee: %s)", err, keyAddrStr) } return &validationResult{ diff --git a/universalClient/pushsigner/grant_verifier_test.go b/universalClient/pushsigner/grant_verifier_test.go index 61d41ac3..aeb465b9 100644 --- a/universalClient/pushsigner/grant_verifier_test.go +++ b/universalClient/pushsigner/grant_verifier_test.go @@ -21,7 +21,7 @@ func TestVerifyGrants(t *testing.T) { t.Run("all required grants present and valid", func(t *testing.T) { grants := []grantInfo{ {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteInbound", Expiration: &futureTime}, - {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteGasPrice", Expiration: &futureTime}, + {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteChainMeta", Expiration: &futureTime}, {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteOutbound", Expiration: &futureTime}, {Granter: granter, MessageType: "/utss.v1.MsgVoteTssKeyProcess", Expiration: &futureTime}, } @@ -39,7 +39,7 @@ func TestVerifyGrants(t *testing.T) { t.Run("grants with nil expiration are valid", func(t *testing.T) { grants := []grantInfo{ {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteInbound", Expiration: nil}, - {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteGasPrice", Expiration: nil}, + {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteChainMeta", Expiration: nil}, {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteOutbound", Expiration: nil}, {Granter: granter, MessageType: "/utss.v1.MsgVoteTssKeyProcess", Expiration: nil}, } @@ -64,7 +64,7 @@ func TestVerifyGrants(t *testing.T) { t.Run("expired grants are ignored", func(t *testing.T) { grants := []grantInfo{ {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteInbound", Expiration: &pastTime}, // Expired - {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteGasPrice", Expiration: &futureTime}, + {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteChainMeta", Expiration: &futureTime}, {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteOutbound", Expiration: &futureTime}, {Granter: granter, MessageType: "/utss.v1.MsgVoteTssKeyProcess", Expiration: &futureTime}, } @@ -80,7 +80,7 @@ func TestVerifyGrants(t *testing.T) { wrongGranter := "push1wronggranter" grants := []grantInfo{ {Granter: wrongGranter, MessageType: "/uexecutor.v1.MsgVoteInbound", Expiration: &futureTime}, - {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteGasPrice", Expiration: &futureTime}, + {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteChainMeta", Expiration: &futureTime}, {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteOutbound", Expiration: &futureTime}, {Granter: granter, MessageType: "/utss.v1.MsgVoteTssKeyProcess", Expiration: &futureTime}, } @@ -104,7 +104,7 @@ func TestVerifyGrants(t *testing.T) { grants := []grantInfo{ {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteInbound", Expiration: &futureTime}, {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteInbound", Expiration: &futureTime}, // Duplicate - {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteGasPrice", Expiration: &futureTime}, + {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteChainMeta", Expiration: &futureTime}, {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteOutbound", Expiration: &futureTime}, {Granter: granter, MessageType: "/utss.v1.MsgVoteTssKeyProcess", Expiration: &futureTime}, } @@ -117,7 +117,7 @@ func TestVerifyGrants(t *testing.T) { t.Run("extra non-required grants are ignored", func(t *testing.T) { grants := []grantInfo{ {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteInbound", Expiration: &futureTime}, - {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteGasPrice", Expiration: &futureTime}, + {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteChainMeta", Expiration: &futureTime}, {Granter: granter, MessageType: "/uexecutor.v1.MsgVoteOutbound", Expiration: &futureTime}, {Granter: granter, MessageType: "/utss.v1.MsgVoteTssKeyProcess", Expiration: &futureTime}, {Granter: granter, MessageType: "/some.other.v1.MsgNotRequired", Expiration: &futureTime}, // Extra grant @@ -209,7 +209,7 @@ func TestExtractGrantInfo(t *testing.T) { ga1Any, err := codectypes.NewAnyWithValue(ga1) require.NoError(t, err) - ga2 := &authz.GenericAuthorization{Msg: "/uexecutor.v1.MsgVoteGasPrice"} + ga2 := &authz.GenericAuthorization{Msg: "/uexecutor.v1.MsgVoteChainMeta"} ga2Any, err := codectypes.NewAnyWithValue(ga2) require.NoError(t, err) @@ -231,7 +231,7 @@ func TestExtractGrantInfo(t *testing.T) { grants := extractGrantInfo(resp, cdc) require.Len(t, grants, 2) assert.Equal(t, "/uexecutor.v1.MsgVoteInbound", grants[0].MessageType) - assert.Equal(t, "/uexecutor.v1.MsgVoteGasPrice", grants[1].MessageType) + assert.Equal(t, "/uexecutor.v1.MsgVoteChainMeta", grants[1].MessageType) }) } @@ -303,7 +303,7 @@ func TestValidationResult(t *testing.T) { KeyName: "test-key", KeyAddr: "push1keyaddr123", Granter: "push1granter123", - Messages: []string{"/uexecutor.v1.MsgVoteInbound", "/uexecutor.v1.MsgVoteGasPrice"}, + Messages: []string{"/uexecutor.v1.MsgVoteInbound", "/uexecutor.v1.MsgVoteChainMeta"}, } assert.Equal(t, "test-key", result.KeyName) diff --git a/universalClient/pushsigner/pushsigner.go b/universalClient/pushsigner/pushsigner.go index 19c5019a..75f16c32 100644 --- a/universalClient/pushsigner/pushsigner.go +++ b/universalClient/pushsigner/pushsigner.go @@ -104,9 +104,9 @@ func (s *Signer) VoteInbound(ctx context.Context, inbound *uexecutortypes.Inboun return voteInbound(ctx, s, s.log, s.granter, inbound) } -// VoteGasPrice votes on a gas price observation. -func (s *Signer) VoteGasPrice(ctx context.Context, chainID string, price uint64, blockNumber uint64) (string, error) { - return voteGasPrice(ctx, s, s.log, s.granter, chainID, price, blockNumber) +// VoteChainMeta votes on chain metadata (gas price, block height). +func (s *Signer) VoteChainMeta(ctx context.Context, chainID string, price uint64, chainHeight uint64) (string, error) { + return voteChainMeta(ctx, s, s.log, s.granter, chainID, price, chainHeight) } // VoteOutbound votes on an outbound transaction observation. diff --git a/universalClient/pushsigner/pushsigner_test.go b/universalClient/pushsigner/pushsigner_test.go index 41bf868a..5c59eb76 100644 --- a/universalClient/pushsigner/pushsigner_test.go +++ b/universalClient/pushsigner/pushsigner_test.go @@ -144,10 +144,10 @@ func TestSigner_VoteInbound(t *testing.T) { }) } -// TestSigner_VoteGasPrice tests the VoteGasPrice method signature. -func TestSigner_VoteGasPrice(t *testing.T) { +// TestSigner_VoteChainMeta tests the VoteChainMeta method signature. +func TestSigner_VoteChainMeta(t *testing.T) { t.Run("method exists", func(t *testing.T) { - // Method signature: VoteGasPrice(ctx context.Context, chainID string, price uint64, blockNumber uint64) (string, error) + // Method signature: VoteChainMeta(ctx context.Context, chainID string, price uint64, chainHeight uint64) (string, error) assert.True(t, true) }) } diff --git a/universalClient/pushsigner/vote.go b/universalClient/pushsigner/vote.go index 812d6153..dfaa9aaf 100644 --- a/universalClient/pushsigner/vote.go +++ b/universalClient/pushsigner/vote.go @@ -86,23 +86,23 @@ func voteInbound( return vote(ctx, signer, log, msg, memo) } -// voteGasPrice votes on a gas price observation -func voteGasPrice( +// voteChainMeta votes on chain metadata (gas price, block height) +func voteChainMeta( ctx context.Context, signer *Signer, log zerolog.Logger, granter string, chainID string, price uint64, - blockNumber uint64, + chainHeight uint64, ) (string, error) { - msg := &uexecutortypes.MsgVoteGasPrice{ + msg := &uexecutortypes.MsgVoteChainMeta{ Signer: granter, ObservedChainId: chainID, Price: price, - BlockNumber: blockNumber, + ChainHeight: chainHeight, } - memo := fmt.Sprintf("Vote gas price: %s @ %d", chainID, price) + memo := fmt.Sprintf("Vote chain meta: %s @ price=%d height=%d", chainID, price, chainHeight) return vote(ctx, signer, log, msg, memo) } diff --git a/universalClient/pushsigner/vote_test.go b/universalClient/pushsigner/vote_test.go index cc0e0749..48981ab4 100644 --- a/universalClient/pushsigner/vote_test.go +++ b/universalClient/pushsigner/vote_test.go @@ -59,35 +59,35 @@ func TestMsgVoteInboundConstruction(t *testing.T) { }) } -func TestMsgVoteGasPriceConstruction(t *testing.T) { - t.Run("construct valid MsgVoteGasPrice", func(t *testing.T) { +func TestMsgVoteChainMetaConstruction(t *testing.T) { + t.Run("construct valid MsgVoteChainMeta", func(t *testing.T) { granter := "push1granter123" chainID := "eip155:1" price := uint64(20000000000) - blockNumber := uint64(18500000) + chainHeight := uint64(18500000) - msg := &uexecutortypes.MsgVoteGasPrice{ + msg := &uexecutortypes.MsgVoteChainMeta{ Signer: granter, ObservedChainId: chainID, Price: price, - BlockNumber: blockNumber, + ChainHeight: chainHeight, } assert.Equal(t, granter, msg.Signer) assert.Equal(t, chainID, msg.ObservedChainId) assert.Equal(t, price, msg.Price) - assert.Equal(t, blockNumber, msg.BlockNumber) + assert.Equal(t, chainHeight, msg.ChainHeight) }) - t.Run("MsgVoteGasPrice with zero values", func(t *testing.T) { - msg := &uexecutortypes.MsgVoteGasPrice{ + t.Run("MsgVoteChainMeta with zero values", func(t *testing.T) { + msg := &uexecutortypes.MsgVoteChainMeta{ Signer: "push1granter123", ObservedChainId: "eip155:1", Price: 0, - BlockNumber: 0, + ChainHeight: 0, } assert.Equal(t, uint64(0), msg.Price) - assert.Equal(t, uint64(0), msg.BlockNumber) + assert.Equal(t, uint64(0), msg.ChainHeight) }) } @@ -251,11 +251,10 @@ func TestVoteMemoFormats(t *testing.T) { assert.Equal(t, expectedMemo, actualMemo) }) - t.Run("gas price vote memo format", func(t *testing.T) { + t.Run("chain meta vote memo format", func(t *testing.T) { chainID := "eip155:1" - price := "25000000000" - expectedMemo := "Vote gas price: eip155:1 @ 25000000000" - actualMemo := "Vote gas price: " + chainID + " @ " + price + expectedMemo := "Vote chain meta: eip155:1 @ price=25000000000 height=18500000" + actualMemo := "Vote chain meta: " + chainID + " @ price=25000000000 height=18500000" assert.Equal(t, expectedMemo, actualMemo) }) diff --git a/universalClient/tss/coordinator/coordinator.go b/universalClient/tss/coordinator/coordinator.go index 05a01536..fdd74b04 100644 --- a/universalClient/tss/coordinator/coordinator.go +++ b/universalClient/tss/coordinator/coordinator.go @@ -743,12 +743,6 @@ func (c *Coordinator) buildSignTransaction(ctx context.Context, eventData []byte return nil, errors.New("chains manager not configured") } - // Get gas price from pushcore oracle - gasPrice, err := c.pushCore.GetGasPrice(ctx, data.DestinationChain) - if err != nil { - return nil, errors.Wrapf(err, "failed to get gas price for chain %s", data.DestinationChain) - } - // Get the client for the destination chain client, err := c.chains.GetClient(data.DestinationChain) if err != nil { @@ -761,11 +755,11 @@ func (c *Coordinator) buildSignTransaction(ctx context.Context, eventData []byte return nil, errors.Wrapf(err, "failed to get tx builder for chain %s", data.DestinationChain) } - // Get the signing request with the gas price from oracle (nonce is required for SIGN) + // Get the signing request (nonce is required for SIGN) if assignedNonce == nil { return nil, errors.New("assigned nonce is required for sign transaction") } - signingReq, err := builder.GetOutboundSigningRequest(ctx, &data, gasPrice, *assignedNonce) + signingReq, err := builder.GetOutboundSigningRequest(ctx, &data, *assignedNonce) if err != nil { return nil, errors.Wrap(err, "failed to get outbound signing request") } diff --git a/universalClient/tss/expirysweeper/sweeper.go b/universalClient/tss/expirysweeper/sweeper.go index cdbc5ff0..7d724fc1 100644 --- a/universalClient/tss/expirysweeper/sweeper.go +++ b/universalClient/tss/expirysweeper/sweeper.go @@ -130,9 +130,10 @@ func (s *Sweeper) voteFailureAndMarkReverted(ctx context.Context, event *store.E s.logger.Warn().Str("event_id", event.EventID).Msg("pushSigner not configured, skipping failure vote") } else { observation := &uexecutortypes.OutboundObservation{ - Success: false, - TxHash: "", - ErrorMsg: errorMsg, + Success: false, + TxHash: "", + ErrorMsg: errorMsg, + GasFeeUsed: "0", } voteTxHash, err := s.pushSigner.VoteOutbound(ctx, data.TxID, data.UniversalTxId, observation) if err != nil { diff --git a/universalClient/tss/sessionmanager/sessionmanager.go b/universalClient/tss/sessionmanager/sessionmanager.go index e74a4968..52fe59da 100644 --- a/universalClient/tss/sessionmanager/sessionmanager.go +++ b/universalClient/tss/sessionmanager/sessionmanager.go @@ -6,7 +6,6 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "math/big" "strconv" "sync" "time" @@ -719,19 +718,12 @@ func (sm *SessionManager) checkExpiredSessions(ctx context.Context, blockDelay u } } -// GasPriceTolerancePercent defines the acceptable deviation from oracle gas price (e.g., 10 = 10%) -const GasPriceTolerancePercent = 10 - -// verifySigningRequest validates the coordinator's signing request: gas price and hash (coordinator nonce is source of truth). +// verifySigningRequest validates the coordinator's signing request: hash verification (coordinator nonce is source of truth). func (sm *SessionManager) verifySigningRequest(ctx context.Context, event *store.Event, req *common.UnSignedOutboundTxReq) error { if req == nil { return errors.New("unsigned transaction request is required for SIGN events") } - if req.GasPrice == nil { - return errors.New("gas price is missing in request") - } - if len(req.SigningHash) == 0 { return errors.New("signing hash is missing in request") } @@ -752,10 +744,6 @@ func (sm *SessionManager) verifySigningRequest(ctx context.Context, event *store return errors.Errorf("outbound disabled for chain %s, refusing to sign", chainID) } - if err := sm.validateGasPrice(ctx, chainID, req.GasPrice); err != nil { - return errors.Wrap(err, "gas price validation failed") - } - // Build with coordinator's nonce and compare hash if sm.chains == nil { sm.logger.Warn().Msg("chains manager not configured, skipping hash verification") @@ -787,7 +775,7 @@ func (sm *SessionManager) verifySigningRequest(ctx context.Context, event *store } // Use coordinator's nonce so our computed hash matches - signingReq, err := builder.GetOutboundSigningRequest(ctx, &outboundData, req.GasPrice, req.Nonce) + signingReq, err := builder.GetOutboundSigningRequest(ctx, &outboundData, req.Nonce) if err != nil { return errors.Wrap(err, "failed to get signing request for verification") } @@ -804,7 +792,6 @@ func (sm *SessionManager) verifySigningRequest(ctx context.Context, event *store sm.logger.Debug(). Str("event_id", event.EventID). - Str("gas_price", req.GasPrice.String()). Str("signing_hash", hex.EncodeToString(req.SigningHash)). Str("our_hash", hex.EncodeToString(signingReq.SigningHash)). Msg("sign metadata verified - hash matches") @@ -812,38 +799,6 @@ func (sm *SessionManager) verifySigningRequest(ctx context.Context, event *store return nil } -// validateGasPrice checks that the provided gas price is within acceptable bounds of the oracle price. -func (sm *SessionManager) validateGasPrice(ctx context.Context, chainID string, gasPrice *big.Int) error { - if sm.pushCore == nil { - sm.logger.Warn().Msg("pushCore not configured, skipping gas price validation") - return nil - } - - if gasPrice == nil { - return errors.New("gas price is nil") - } - - // Get the current oracle gas price - oraclePrice, err := sm.pushCore.GetGasPrice(ctx, chainID) - if err != nil { - return errors.Wrap(err, "failed to get oracle gas price") - } - - // Check if gas price is within tolerance - // Allow coordinator's price to be within ±GasPriceTolerancePercent of oracle price - tolerance := new(big.Int).Div(oraclePrice, big.NewInt(100/GasPriceTolerancePercent)) - minPrice := new(big.Int).Sub(oraclePrice, tolerance) - maxPrice := new(big.Int).Add(oraclePrice, tolerance) - - if gasPrice.Cmp(minPrice) < 0 { - return errors.Errorf("gas price %s is too low (min: %s, oracle: %s)", gasPrice.String(), minPrice.String(), oraclePrice.String()) - } - if gasPrice.Cmp(maxPrice) > 0 { - return errors.Errorf("gas price %s is too high (max: %s, oracle: %s)", gasPrice.String(), maxPrice.String(), oraclePrice.String()) - } - - return nil -} // getTSSAddress gets the TSS ECDSA address from the current TSS public key // The TSS address is always the same ECDSA address derived from the TSS public key @@ -866,10 +821,6 @@ func (sm *SessionManager) handleSigningComplete(_ context.Context, eventID strin "signature": hex.EncodeToString(signature), "signing_hash": hex.EncodeToString(signingReq.SigningHash), "nonce": signingReq.Nonce, - "gas_price": "0", - } - if signingReq.GasPrice != nil { - signingData["gas_price"] = signingReq.GasPrice.String() } // Unmarshal original event data, add signing_data, re-marshal diff --git a/universalClient/tss/sessionmanager/sessionmanager_test.go b/universalClient/tss/sessionmanager/sessionmanager_test.go index 28c45835..f98f7cf6 100644 --- a/universalClient/tss/sessionmanager/sessionmanager_test.go +++ b/universalClient/tss/sessionmanager/sessionmanager_test.go @@ -15,8 +15,6 @@ import ( "gorm.io/driver/sqlite" "gorm.io/gorm" - "math/big" - "github.com/pushchain/push-chain-node/universalClient/chains" "github.com/pushchain/push-chain-node/universalClient/chains/common" "github.com/pushchain/push-chain-node/universalClient/config" @@ -414,7 +412,6 @@ func TestVerifySigningRequest_OutboundDisabled(t *testing.T) { req := &common.UnSignedOutboundTxReq{ SigningHash: []byte{0x01, 0x02, 0x03}, - GasPrice: big.NewInt(1000000000), } t.Run("rejects signing when outbound disabled for destination chain", func(t *testing.T) { diff --git a/universalClient/tss/txbroadcaster/broadcaster.go b/universalClient/tss/txbroadcaster/broadcaster.go index d782fff7..f8d9fa4d 100644 --- a/universalClient/tss/txbroadcaster/broadcaster.go +++ b/universalClient/tss/txbroadcaster/broadcaster.go @@ -4,7 +4,6 @@ import ( "context" "encoding/hex" "encoding/json" - "math/big" "time" "github.com/pkg/errors" @@ -23,7 +22,6 @@ type SigningData struct { Signature string `json:"signature"` // hex-encoded 64/65 byte signature SigningHash string `json:"signing_hash"` // hex-encoded signing hash Nonce uint64 `json:"nonce"` - GasPrice string `json:"gas_price"` // string for big.Int } // SignedEventData wraps OutboundCreatedEvent with signing data appended by sessionManager. @@ -165,16 +163,8 @@ func reconstructSigningReq(sd *SigningData) (*common.UnSignedOutboundTxReq, erro return nil, errors.Wrap(err, "failed to decode signing hash") } - gasPrice := new(big.Int) - if sd.GasPrice != "" { - if _, ok := gasPrice.SetString(sd.GasPrice, 10); !ok { - return nil, errors.Errorf("invalid gas_price: %s", sd.GasPrice) - } - } - return &common.UnSignedOutboundTxReq{ SigningHash: signingHash, - Nonce: sd.Nonce, - GasPrice: gasPrice, + Nonce: sd.Nonce, }, nil } diff --git a/universalClient/tss/txbroadcaster/broadcaster_test.go b/universalClient/tss/txbroadcaster/broadcaster_test.go index f22eadce..860a16f5 100644 --- a/universalClient/tss/txbroadcaster/broadcaster_test.go +++ b/universalClient/tss/txbroadcaster/broadcaster_test.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "math/big" "reflect" "testing" "unsafe" @@ -32,8 +31,8 @@ import ( type mockTxBuilder struct{ mock.Mock } -func (m *mockTxBuilder) GetOutboundSigningRequest(ctx context.Context, data *uexecutortypes.OutboundCreatedEvent, gasPrice *big.Int, nonce uint64) (*common.UnSignedOutboundTxReq, error) { - args := m.Called(ctx, data, gasPrice, nonce) +func (m *mockTxBuilder) GetOutboundSigningRequest(ctx context.Context, data *uexecutortypes.OutboundCreatedEvent, nonce uint64) (*common.UnSignedOutboundTxReq, error) { + args := m.Called(ctx, data, nonce) if args.Get(0) == nil { return nil, args.Error(1) } @@ -60,6 +59,11 @@ func (m *mockTxBuilder) IsAlreadyExecuted(ctx context.Context, txID string) (boo return args.Bool(0), args.Error(1) } +func (m *mockTxBuilder) GetGasFeeUsed(ctx context.Context, txHash string) (string, error) { + args := m.Called(ctx, txHash) + return args.String(0), args.Error(1) +} + type mockChainClient struct{ builder *mockTxBuilder } func (m *mockChainClient) Start(context.Context) error { return nil } @@ -120,7 +124,6 @@ func makeSignedEventData(t *testing.T, destChain string, nonce uint64) []byte { Signature: sig, SigningHash: hash, Nonce: nonce, - GasPrice: "1000000000", }, } b, err := json.Marshal(data) diff --git a/universalClient/tss/txresolver/evm.go b/universalClient/tss/txresolver/evm.go index 8b04fdf7..4aa09afd 100644 --- a/universalClient/tss/txresolver/evm.go +++ b/universalClient/tss/txresolver/evm.go @@ -3,6 +3,7 @@ package txresolver import ( "context" + "github.com/pushchain/push-chain-node/universalClient/chains/common" "github.com/pushchain/push-chain-node/universalClient/store" "github.com/pushchain/push-chain-node/universalClient/tss/eventstore" ) @@ -44,8 +45,8 @@ func (r *Resolver) resolveEVM(ctx context.Context, event *store.Event, chainID, if count >= maxNotFoundRetries { delete(r.notFoundCounts, event.EventID) - // Protocol issue: tx dropped/not found — no txHash, no height - _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, "", 0, "tx not found on destination chain after max retries") + // Protocol issue: tx dropped/not found — no txHash, no height, no gas used + _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, "", 0, "0", "tx not found on destination chain after max retries") } return } @@ -60,8 +61,14 @@ func (r *Resolver) resolveEVM(ctx context.Context, event *store.Event, chainID, // Enough confirmations: finalize based on status if status == 0 { - // Destination chain revert — attach receipt block height and tx hash - _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, rawTxHash, blockHeight, "tx execution reverted on destination chain") + // Destination chain revert — fetch gas used and attach receipt info + gasFeeUsed := "0" + if builder, err := r.getBuilder(chainID); err == nil { + if fee, err := builder.GetGasFeeUsed(ctx, rawTxHash); err == nil { + gasFeeUsed = fee + } + } + _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, rawTxHash, blockHeight, gasFeeUsed, "tx execution reverted on destination chain") return } @@ -76,13 +83,17 @@ func (r *Resolver) resolveEVM(ctx context.Context, event *store.Event, chainID, } func (r *Resolver) verifyTxOnChain(ctx context.Context, chainID, txHash string) (bool, uint64, uint64, uint8, error) { - client, err := r.chains.GetClient(chainID) + builder, err := r.getBuilder(chainID) if err != nil { return false, 0, 0, 0, err } - builder, err := client.GetTxBuilder() + return builder.VerifyBroadcastedTx(ctx, txHash) +} + +func (r *Resolver) getBuilder(chainID string) (common.OutboundTxBuilder, error) { + client, err := r.chains.GetClient(chainID) if err != nil { - return false, 0, 0, 0, err + return nil, err } - return builder.VerifyBroadcastedTx(ctx, txHash) + return client.GetTxBuilder() } diff --git a/universalClient/tss/txresolver/resolver.go b/universalClient/tss/txresolver/resolver.go index 9ce9ebb8..d76b514f 100644 --- a/universalClient/tss/txresolver/resolver.go +++ b/universalClient/tss/txresolver/resolver.go @@ -120,7 +120,7 @@ func (r *Resolver) resolveEvent(ctx context.Context, event *store.Event) { r.logger.Warn().Err(extractErr).Str("event_id", event.EventID).Msg("invalid broadcasted tx hash and failed to extract outbound IDs") return } - _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, "", 0, "invalid broadcasted tx hash format") + _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, "", 0, "0", "invalid broadcasted tx hash format") return } @@ -133,16 +133,20 @@ func (r *Resolver) resolveEvent(ctx context.Context, event *store.Event) { r.resolveSVM(ctx, event, chainID) } -func (r *Resolver) voteFailureAndMarkReverted(ctx context.Context, event *store.Event, txID, utxID, txHash string, blockHeight uint64, errorMsg string) error { +func (r *Resolver) voteFailureAndMarkReverted(ctx context.Context, event *store.Event, txID, utxID, txHash string, blockHeight uint64, gasFeeUsed string, errorMsg string) error { if r.pushSigner == nil { r.logger.Warn().Str("event_id", event.EventID).Msg("pushSigner not configured, cannot vote failure") return nil } + if gasFeeUsed == "" { + gasFeeUsed = "0" + } observation := &uexecutortypes.OutboundObservation{ Success: false, BlockHeight: blockHeight, TxHash: txHash, ErrorMsg: errorMsg, + GasFeeUsed: gasFeeUsed, } voteTxHash, err := r.pushSigner.VoteOutbound(ctx, txID, utxID, observation) if err != nil { diff --git a/universalClient/tss/txresolver/resolver_test.go b/universalClient/tss/txresolver/resolver_test.go index a635e3ee..af7214e4 100644 --- a/universalClient/tss/txresolver/resolver_test.go +++ b/universalClient/tss/txresolver/resolver_test.go @@ -3,7 +3,6 @@ package txresolver import ( "context" "encoding/json" - "math/big" "reflect" "testing" "unsafe" @@ -31,8 +30,8 @@ import ( type mockTxBuilder struct{ mock.Mock } -func (m *mockTxBuilder) GetOutboundSigningRequest(ctx context.Context, data *uexecutortypes.OutboundCreatedEvent, gasPrice *big.Int, nonce uint64) (*common.UnSignedOutboundTxReq, error) { - args := m.Called(ctx, data, gasPrice, nonce) +func (m *mockTxBuilder) GetOutboundSigningRequest(ctx context.Context, data *uexecutortypes.OutboundCreatedEvent, nonce uint64) (*common.UnSignedOutboundTxReq, error) { + args := m.Called(ctx, data, nonce) if args.Get(0) == nil { return nil, args.Error(1) } @@ -59,6 +58,11 @@ func (m *mockTxBuilder) IsAlreadyExecuted(ctx context.Context, txID string) (boo return args.Bool(0), args.Error(1) } +func (m *mockTxBuilder) GetGasFeeUsed(ctx context.Context, txHash string) (string, error) { + args := m.Called(ctx, txHash) + return args.String(0), args.Error(1) +} + type mockChainClient struct{ builder *mockTxBuilder } func (m *mockChainClient) Start(context.Context) error { return nil } @@ -418,7 +422,7 @@ func TestVoteFailureAndMarkReverted(t *testing.T) { }) event := &store.Event{EventID: "ev-1"} - err := resolver.voteFailureAndMarkReverted(context.Background(), event, "tx-1", "utx-1", "0xhash", 12345, "some error") + err := resolver.voteFailureAndMarkReverted(context.Background(), event, "tx-1", "utx-1", "0xhash", 12345, "0", "some error") assert.NoError(t, err) }) } diff --git a/universalClient/tss/txresolver/svm.go b/universalClient/tss/txresolver/svm.go index 193b27c3..fd6f4b97 100644 --- a/universalClient/tss/txresolver/svm.go +++ b/universalClient/tss/txresolver/svm.go @@ -54,6 +54,6 @@ func (r *Resolver) resolveSVM(ctx context.Context, event *store.Event, chainID s return } - // PDA not found — tx was not executed on destination chain - _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, "", 0, "tx not executed on destination chain") + // PDA not found — tx was not executed on destination chain, no gas consumed + _ = r.voteFailureAndMarkReverted(ctx, event, txID, utxID, "", 0, "0", "tx not executed on destination chain") } diff --git a/x/uexecutor/autocli.go b/x/uexecutor/autocli.go index 5856254f..2eca2060 100755 --- a/x/uexecutor/autocli.go +++ b/x/uexecutor/autocli.go @@ -17,6 +17,32 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Use: "params", Short: "Query the current gov gated parameters", }, + { + RpcMethod: "GasPrice", + Use: "gas-price [chain-id]", + Short: "Query the median gas price for a specific chain (reads from ChainMeta store)", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "chain_id"}, + }, + }, + { + RpcMethod: "AllGasPrices", + Use: "all-gas-prices", + Short: "Query gas prices for all chains (reads from ChainMeta store)", + }, + { + RpcMethod: "ChainMeta", + Use: "chain-meta [chain-id]", + Short: "Query aggregated chain metadata (gas price + block height) for a specific chain", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "chain_id"}, + }, + }, + { + RpcMethod: "AllChainMetas", + Use: "all-chain-metas", + Short: "Query chain metadata for all chains", + }, }, SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{ "v2": { diff --git a/x/uexecutor/keeper/chain_meta.go b/x/uexecutor/keeper/chain_meta.go new file mode 100644 index 00000000..3ec63707 --- /dev/null +++ b/x/uexecutor/keeper/chain_meta.go @@ -0,0 +1,192 @@ +package keeper + +import ( + "context" + "errors" + "fmt" + "sort" + + "cosmossdk.io/collections" + sdkerrors "cosmossdk.io/errors" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// chainMetaVoteStalenessSeconds is the maximum age (in seconds) of a stored vote +// that is still eligible to be included in the median calculation. +const chainMetaVoteStalenessSeconds uint64 = 300 + +func (k Keeper) GetChainMeta(ctx context.Context, chainID string) (types.ChainMeta, bool, error) { + cm, err := k.ChainMetas.Get(ctx, chainID) + if err != nil { + if errors.Is(err, collections.ErrNotFound) { + return types.ChainMeta{}, false, nil + } + return types.ChainMeta{}, false, err + } + return cm, true, nil +} + +func (k Keeper) SetChainMeta(ctx context.Context, chainID string, chainMeta types.ChainMeta) error { + return k.ChainMetas.Set(ctx, chainID, chainMeta) +} + +// VoteChainMeta processes a universal validator's vote on chain metadata (gas price + chain height). +// +// Rules: +// 1. If blockNumber <= entry.LastAppliedChainHeight the tx is rejected — the validator +// must re-vote with a newer block height. +// 2. Each vote is stamped with the current block time (storedAt) when it is recorded. +// 3. When computing medians, only votes whose storedAt is within the last +// chainMetaVoteStalenessSeconds seconds are considered. +// 4. Price median and chain-height median are computed independently (upper median = len/2). +// 5. After a successful EVM call, LastAppliedChainHeight is updated. +func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAddress, observedChainId string, price, blockNumber uint64) error { + sdkCtx := sdk.UnwrapSDKContext(ctx) + now := uint64(sdkCtx.BlockTime().Unix()) + + entry, found, err := k.GetChainMeta(ctx, observedChainId) + if err != nil { + return sdkerrors.Wrap(err, "failed to fetch chain meta entry") + } + + if !found { + // First vote for this chain — no height check needed yet. + priceBig := math.NewUint(price).BigInt() + chainHeightBig := math.NewUint(blockNumber).BigInt() + if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, priceBig, chainHeightBig); evmErr != nil { + return sdkerrors.Wrap(evmErr, "failed to call EVM setChainMeta") + } + + newEntry := types.ChainMeta{ + ObservedChainId: observedChainId, + Signers: []string{universalValidator.String()}, + Prices: []uint64{price}, + ChainHeights: []uint64{blockNumber}, + StoredAts: []uint64{now}, + MedianIndex: 0, + LastAppliedChainHeight: blockNumber, + } + if err := k.SetChainMeta(ctx, observedChainId, newEntry); err != nil { + return sdkerrors.Wrap(err, "failed to set initial chain meta entry") + } + + return nil + } + + // Reject votes whose chain height has already been committed to the contract. + if blockNumber <= entry.LastAppliedChainHeight { + return fmt.Errorf( + "vote chain height %d is not greater than last applied chain height %d; re-vote with a newer block", + blockNumber, entry.LastAppliedChainHeight, + ) + } + + // Update or insert vote for this validator. + var updated bool + for i, s := range entry.Signers { + if s == universalValidator.String() { + entry.Prices[i] = price + entry.ChainHeights[i] = blockNumber + entry.StoredAts[i] = now + updated = true + break + } + } + + if !updated { + entry.Signers = append(entry.Signers, universalValidator.String()) + entry.Prices = append(entry.Prices, price) + entry.ChainHeights = append(entry.ChainHeights, blockNumber) + entry.StoredAts = append(entry.StoredAts, now) + } + + // Build a filtered pool: only votes stored within the staleness window. + type voteSnapshot struct { + price uint64 + chainHeight uint64 + } + var fresh []voteSnapshot + for i := range entry.Signers { + age := now - entry.StoredAts[i] + if age <= chainMetaVoteStalenessSeconds { + fresh = append(fresh, voteSnapshot{ + price: entry.Prices[i], + chainHeight: entry.ChainHeights[i], + }) + } + } + + if len(fresh) == 0 { + // No fresh votes — persist the updated entry but skip EVM call. + if err := k.SetChainMeta(ctx, observedChainId, entry); err != nil { + return sdkerrors.Wrap(err, "failed to set updated chain meta entry") + } + return nil + } + + // Compute independent upper medians (len/2) for price and chain height. + medianPrice := upperMedianUint64(fresh, func(v voteSnapshot) uint64 { return v.price }) + medianChainHeight := upperMedianUint64(fresh, func(v voteSnapshot) uint64 { return v.chainHeight }) + + // Update MedianIndex to reflect the price median position in the full slice + // (best-effort; used for storage/querying only). + entry.MedianIndex = uint64(computeMedianIndex(entry.Prices)) + + priceBig := math.NewUint(medianPrice).BigInt() + chainHeightBig := math.NewUint(medianChainHeight).BigInt() + if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, priceBig, chainHeightBig); evmErr != nil { + return sdkerrors.Wrap(evmErr, "failed to call EVM setChainMeta") + } + + entry.LastAppliedChainHeight = medianChainHeight + if err := k.SetChainMeta(ctx, observedChainId, entry); err != nil { + return sdkerrors.Wrap(err, "failed to set updated chain meta entry") + } + + return nil +} + +// upperMedianUint64 sorts the slice by the extracted key and returns the value at index len/2 +// (upper median for even-length slices). +func upperMedianUint64[T any](items []T, key func(T) uint64) uint64 { + type kv struct{ k uint64; v T } + arr := make([]kv, len(items)) + for i, item := range items { + arr[i] = kv{k: key(item), v: item} + } + sort.SliceStable(arr, func(i, j int) bool { return arr[i].k < arr[j].k }) + return arr[len(arr)/2].k +} + +// MigrateGasPricesToChainMeta seeds ChainMetas from existing GasPrices entries. +// Called once during the chain-meta upgrade. Existing gas price data (prices, block_nums, median_index) +// is carried over; StoredAts defaults to zero (treated as stale until validators re-vote). +func (k Keeper) MigrateGasPricesToChainMeta(ctx context.Context) error { + return k.GasPrices.Walk(ctx, nil, func(chainID string, gp types.GasPrice) (bool, error) { + // Skip if already migrated + existing, err := k.ChainMetas.Get(ctx, chainID) + if err == nil && existing.ObservedChainId != "" { + return false, nil // already exists, skip + } + + storedAts := make([]uint64, len(gp.Signers)) + + cm := types.ChainMeta{ + ObservedChainId: gp.ObservedChainId, + Signers: gp.Signers, + Prices: gp.Prices, + ChainHeights: gp.BlockNums, + StoredAts: storedAts, + MedianIndex: gp.MedianIndex, + LastAppliedChainHeight: 0, + } + + if err := k.ChainMetas.Set(ctx, chainID, cm); err != nil { + return true, err + } + + return false, nil + }) +} diff --git a/x/uexecutor/keeper/create_outbound.go b/x/uexecutor/keeper/create_outbound.go index 04ba8121..1021edff 100644 --- a/x/uexecutor/keeper/create_outbound.go +++ b/x/uexecutor/keeper/create_outbound.go @@ -8,6 +8,7 @@ import ( "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" evmtypes "github.com/cosmos/evm/x/vm/types" + "github.com/pushchain/push-chain-node/utils" "github.com/pushchain/push-chain-node/x/uexecutor/types" uregistrytypes "github.com/pushchain/push-chain-node/x/uregistry/types" ) @@ -70,7 +71,10 @@ func (k Keeper) BuildOutboundsFromReceipt( Prc20AssetAddr: event.Token, Sender: event.Sender, Payload: event.Payload, + GasFee: event.GasFee.String(), GasLimit: event.GasLimit.String(), + GasPrice: event.GasPrice.String(), + GasToken: event.GasToken, TxType: event.TxType, PcTx: &types.OriginatingPcTx{ TxHash: receipt.Hash, @@ -112,7 +116,6 @@ func (k Keeper) CreateUniversalTxFromPCTx( InboundTx: nil, // no inbound PcTx: []*types.PCTx{&pcTx}, // origin is PC OutboundTx: nil, - UniversalStatus: types.UniversalTxStatus_PC_EXECUTED_SUCCESS, } if err := k.CreateUniversalTx(ctx, universalTxKey, utx); err != nil { @@ -168,6 +171,149 @@ func (k Keeper) CreateUniversalTxFromReceiptIfOutbound( return k.attachOutboundsToUtx(ctx, utx.Id, outbounds, "") } +// AttachRescueOutboundFromReceipt scans the receipt for RescueFundsOnSourceChain events +// emitted by UniversalGatewayPC and, for each one found, attaches a RESCUE_FUNDS outbound +// to the original UTX referenced by the event's universalTxId. +// +// Unlike normal outbounds (which create a new UTX), rescue outbounds are appended to the +// already-existing UTX whose funds are stuck on the source chain. +func (k Keeper) AttachRescueOutboundFromReceipt( + ctx sdk.Context, + receipt *evmtypes.MsgEthereumTxResponse, + pcTx types.PCTx, +) error { + universalGatewayPC := strings.ToLower(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_GATEWAY_PC"].Address) + + evmChainID, err := utils.ExtractEvmChainID(ctx.ChainID()) + if err != nil { + return fmt.Errorf("rescue: failed to extract EVM chain ID: %w", err) + } + pushChainCaip := fmt.Sprintf("eip155:%s", evmChainID) + + for _, lg := range receipt.Logs { + if lg.Removed { + continue + } + if strings.ToLower(lg.Address) != universalGatewayPC { + continue + } + if len(lg.Topics) == 0 { + continue + } + if strings.ToLower(lg.Topics[0]) != strings.ToLower(types.RescueFundsOnSourceChainEventSig) { + continue + } + + event, err := types.DecodeRescueFundsOnSourceChainFromLog(lg) + if err != nil { + return fmt.Errorf("failed to decode RescueFundsOnSourceChain: %w", err) + } + + // The universalTxId in the event is a 0x-prefixed bytes32 matching our UTX key. + originalUtxId := strings.TrimPrefix(event.UniversalTxId, "0x") + + originalUtx, found, err := k.GetUniversalTx(ctx, originalUtxId) + if err != nil { + return fmt.Errorf("rescue: failed to fetch UTX %s: %w", originalUtxId, err) + } + if !found { + return fmt.Errorf("rescue: original UTX %s not found", originalUtxId) + } + if originalUtx.InboundTx == nil { + return fmt.Errorf("rescue: UTX %s has no inbound tx", originalUtxId) + } + + // Rescue eligibility differs by inbound type: + // + // CEA inbounds: the deposit (first PCTx) must have failed, meaning the funds + // never arrived on Push Chain and are still locked on the source chain. + // + // Non-CEA inbounds: the auto-generated INBOUND_REVERT outbound must exist and + // have reached REVERTED status, meaning TSS could not return the funds to the + // source chain and they are stuck (held by the gateway contract or in escrow). + if originalUtx.InboundTx.IsCEA { + if len(originalUtx.PcTx) == 0 || originalUtx.PcTx[0] == nil || originalUtx.PcTx[0].Status != "FAILED" { + return fmt.Errorf("rescue: UTX %s CEA deposit did not fail", originalUtxId) + } + } else { + hasRevertedAutoRevert := false + for _, ob := range originalUtx.OutboundTx { + if ob != nil && ob.TxType == types.TxType_INBOUND_REVERT && ob.OutboundStatus == types.Status_REVERTED { + hasRevertedAutoRevert = true + break + } + } + if !hasRevertedAutoRevert { + return fmt.Errorf("rescue: UTX %s has no reverted inbound-revert outbound", originalUtxId) + } + } + + // Guard against duplicate rescue outbounds: reject if an active rescue + // (PENDING or OBSERVED) already exists. A REVERTED rescue may be retried. + for _, ob := range originalUtx.OutboundTx { + if ob == nil || ob.TxType != types.TxType_RESCUE_FUNDS { + continue + } + if ob.OutboundStatus == types.Status_PENDING || ob.OutboundStatus == types.Status_OBSERVED { + return fmt.Errorf("rescue: UTX %s already has an active rescue outbound (%s)", originalUtxId, ob.Id) + } + } + + // Resolve external asset address from PRC20 → token config for the source chain. + tokenCfg, err := k.uregistryKeeper.GetTokenConfigByPRC20( + ctx, + originalUtx.InboundTx.SourceChain, + event.PRC20, + ) + if err != nil { + return fmt.Errorf("rescue: token config not found for PRC20 %s on %s: %w", + event.PRC20, originalUtx.InboundTx.SourceChain, err) + } + + // Rescued funds go to the original revert recipient (or the sender as fallback). + recipient := originalUtx.InboundTx.Sender + if originalUtx.InboundTx.RevertInstructions != nil && + originalUtx.InboundTx.RevertInstructions.FundRecipient != "" { + recipient = originalUtx.InboundTx.RevertInstructions.FundRecipient + } + + logIndex := fmt.Sprintf("%d", lg.Index) + outbound := &types.OutboundTx{ + Id: types.GetRescueFundsOutboundId(pushChainCaip, receipt.Hash, logIndex), + DestinationChain: originalUtx.InboundTx.SourceChain, + Recipient: recipient, + Amount: originalUtx.InboundTx.Amount, + ExternalAssetAddr: tokenCfg.Address, + Prc20AssetAddr: event.PRC20, + Sender: event.Sender, + GasFee: event.GasFee.String(), + GasPrice: event.GasPrice.String(), + GasLimit: event.GasLimit.String(), + TxType: types.TxType_RESCUE_FUNDS, + OutboundStatus: types.Status_PENDING, + PcTx: &types.OriginatingPcTx{ + TxHash: receipt.Hash, + LogIndex: logIndex, + }, + } + + // Record the rescue call as a PCTx on the original UTX so the full + // PC-side history is visible (deposit FAILED → rescue call → outbound). + if err := k.UpdateUniversalTx(ctx, originalUtxId, func(utx *types.UniversalTx) error { + utx.PcTx = append(utx.PcTx, &pcTx) + return nil + }); err != nil { + return fmt.Errorf("rescue: failed to record PCTx on UTX %s: %w", originalUtxId, err) + } + + if err := k.attachOutboundsToUtx(ctx, originalUtxId, []*types.OutboundTx{outbound}, ""); err != nil { + return fmt.Errorf("rescue: failed to attach outbound to UTX %s: %w", originalUtxId, err) + } + } + + return nil +} + func (k Keeper) attachOutboundsToUtx( ctx sdk.Context, utxId string, @@ -201,7 +347,10 @@ func (k Keeper) attachOutboundsToUtx( AssetAddr: outbound.ExternalAssetAddr, Sender: outbound.Sender, Payload: outbound.Payload, + GasFee: outbound.GasFee, GasLimit: outbound.GasLimit, + GasPrice: outbound.GasPrice, + GasToken: outbound.GasToken, TxType: outbound.TxType.String(), PcTxHash: pcTxHash, LogIndex: logIndex, diff --git a/x/uexecutor/keeper/evm.go b/x/uexecutor/keeper/evm.go index 292de1e7..aa136439 100644 --- a/x/uexecutor/keeper/evm.go +++ b/x/uexecutor/keeper/evm.go @@ -316,11 +316,174 @@ func (k Keeper) CallUniversalCoreSetGasPrice( ) } -// Calls Handler Contract to deposit prc20 tokens +// Calls UniversalCore Contract to set chain metadata (gas price + chain height). +// The contract uses block.timestamp for the observed-at value. +func (k Keeper) CallUniversalCoreSetChainMeta( + ctx sdk.Context, + chainNamespace string, + price *big.Int, + chainHeight *big.Int, +) (*evmtypes.MsgEthereumTxResponse, error) { + handlerAddr := common.HexToAddress(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_CORE"].Address) + + abi, err := types.ParseUniversalCoreABI() + if err != nil { + return nil, errors.Wrap(err, "failed to parse Handler Contract ABI") + } + + ueModuleAccAddress, _ := k.GetUeModuleAddress(ctx) + + nonce, err := k.GetModuleAccountNonce(ctx) + if err != nil { + return nil, err + } + + if _, err := k.IncrementModuleAccountNonce(ctx); err != nil { + return nil, err + } + + return k.evmKeeper.DerivedEVMCall( + ctx, + abi, + ueModuleAccAddress, + handlerAddr, + big.NewInt(0), + nil, + true, + false, + true, + &nonce, + "setChainMeta", + chainNamespace, + price, + chainHeight, + ) +} + +// GetUniversalCoreQuoterAddress reads the uniswapV3Quoter address stored in UniversalCore. +func (k Keeper) GetUniversalCoreQuoterAddress(ctx sdk.Context) (common.Address, error) { + handlerAddr := common.HexToAddress(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_CORE"].Address) + + abi, err := types.ParseUniversalCoreABI() + if err != nil { + return common.Address{}, errors.Wrap(err, "failed to parse UniversalCore ABI") + } + + ueModuleAccAddress, _ := k.GetUeModuleAddress(ctx) + + receipt, err := k.evmKeeper.CallEVM(ctx, abi, ueModuleAccAddress, handlerAddr, false, "uniswapV3Quoter") + if err != nil { + return common.Address{}, errors.Wrap(err, "failed to call uniswapV3Quoter") + } + + results, err := abi.Methods["uniswapV3Quoter"].Outputs.Unpack(receipt.Ret) + if err != nil { + return common.Address{}, errors.Wrap(err, "failed to unpack uniswapV3Quoter result") + } + + return results[0].(common.Address), nil +} + +// GetUniversalCoreWPCAddress reads the WPC (wrapped PC) address stored in UniversalCore. +func (k Keeper) GetUniversalCoreWPCAddress(ctx sdk.Context) (common.Address, error) { + handlerAddr := common.HexToAddress(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_CORE"].Address) + + abi, err := types.ParseUniversalCoreABI() + if err != nil { + return common.Address{}, errors.Wrap(err, "failed to parse UniversalCore ABI") + } + + ueModuleAccAddress, _ := k.GetUeModuleAddress(ctx) + + receipt, err := k.evmKeeper.CallEVM(ctx, abi, ueModuleAccAddress, handlerAddr, false, "WPC") + if err != nil { + return common.Address{}, errors.Wrap(err, "failed to call WPC") + } + + results, err := abi.Methods["WPC"].Outputs.Unpack(receipt.Ret) + if err != nil { + return common.Address{}, errors.Wrap(err, "failed to unpack WPC result") + } + + return results[0].(common.Address), nil +} + +// GetDefaultFeeTierForToken reads defaultFeeTier[prc20] from UniversalCore. +func (k Keeper) GetDefaultFeeTierForToken(ctx sdk.Context, prc20Address common.Address) (*big.Int, error) { + handlerAddr := common.HexToAddress(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_CORE"].Address) + + abi, err := types.ParseUniversalCoreABI() + if err != nil { + return nil, errors.Wrap(err, "failed to parse UniversalCore ABI") + } + + ueModuleAccAddress, _ := k.GetUeModuleAddress(ctx) + + receipt, err := k.evmKeeper.CallEVM(ctx, abi, ueModuleAccAddress, handlerAddr, false, "defaultFeeTier", prc20Address) + if err != nil { + return nil, errors.Wrap(err, "failed to call defaultFeeTier") + } + + results, err := abi.Methods["defaultFeeTier"].Outputs.Unpack(receipt.Ret) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack defaultFeeTier result") + } + + // go-ethereum unpacks uint24 as *big.Int (non-standard widths always map to *big.Int) + fee, ok := results[0].(*big.Int) + if !ok { + return nil, fmt.Errorf("unexpected type for defaultFeeTier: %T", results[0]) + } + + return fee, nil +} + +// GetSwapQuote calls QuoterV2.quoteExactInputSingle (commit=false) to get the expected +// output amount for swapping prc20 → wpc. +func (k Keeper) GetSwapQuote( + ctx sdk.Context, + quoterAddr, prc20Address, wpcAddress common.Address, + fee, amount *big.Int, +) (*big.Int, error) { + quoterABI, err := types.ParseUniswapQuoterV2ABI() + if err != nil { + return nil, errors.Wrap(err, "failed to parse QuoterV2 ABI") + } + + ueModuleAccAddress, _ := k.GetUeModuleAddress(ctx) + + params := types.AbiQuoteExactInputSingleParams{ + TokenIn: prc20Address, + TokenOut: wpcAddress, + AmountIn: amount, + Fee: fee, + SqrtPriceLimitX96: big.NewInt(0), + } + + receipt, err := k.evmKeeper.CallEVM(ctx, quoterABI, ueModuleAccAddress, quoterAddr, false, "quoteExactInputSingle", params) + if err != nil { + return nil, errors.Wrap(err, "QuoterV2 quoteExactInputSingle failed") + } + + results, err := quoterABI.Methods["quoteExactInputSingle"].Outputs.Unpack(receipt.Ret) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack quoteExactInputSingle result") + } + + amountOut, ok := results[0].(*big.Int) + if !ok { + return nil, fmt.Errorf("unexpected type for amountOut: %T", results[0]) + } + + return amountOut, nil +} + +// Calls Handler Contract to deposit prc20 tokens with auto-swap. +// fee and minPCOut must be pre-computed by the caller (see GetDefaultFeeTierForToken / GetSwapQuote). func (k Keeper) CallPRC20DepositAutoSwap( ctx sdk.Context, prc20Address, to common.Address, - amount *big.Int, + amount, fee, minPCOut *big.Int, ) (*evmtypes.MsgEthereumTxResponse, error) { handlerAddr := common.HexToAddress(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_CORE"].Address) @@ -357,8 +520,108 @@ func (k Keeper) CallPRC20DepositAutoSwap( prc20Address, amount, to, + fee, + minPCOut, + big.NewInt(0), // deadline = 0 → contract uses its default + ) +} + +// CallUniversalCoreRefundUnusedGas calls refundUnusedGas on UniversalCore to return excess gas fee +// to the recipient. withSwap=true swaps the gas token back to PC; withSwap=false deposits PRC20 directly. +func (k Keeper) CallUniversalCoreRefundUnusedGas( + ctx sdk.Context, + gasToken common.Address, + amount *big.Int, + recipient common.Address, + withSwap bool, + fee *big.Int, + minPCOut *big.Int, +) (*evmtypes.MsgEthereumTxResponse, error) { + handlerAddr := common.HexToAddress(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_CORE"].Address) + + abi, err := types.ParseUniversalCoreABI() + if err != nil { + return nil, errors.Wrap(err, "failed to parse UniversalCore ABI") + } + + ueModuleAccAddress, _ := k.GetUeModuleAddress(ctx) + + nonce, err := k.GetModuleAccountNonce(ctx) + if err != nil { + return nil, err + } + + if _, err := k.IncrementModuleAccountNonce(ctx); err != nil { + return nil, err + } + + // fee is uint24 in Solidity — pass as *big.Int (go-ethereum ABI packs non-standard widths as *big.Int) + return k.evmKeeper.DerivedEVMCall( + ctx, + abi, + ueModuleAccAddress, + handlerAddr, big.NewInt(0), + nil, + true, + false, + true, + &nonce, + "refundUnusedGas", + gasToken, + amount, + recipient, + withSwap, + fee, + minPCOut, + ) +} + +// CallExecuteUniversalTx calls executeUniversalTx on a smart-contract recipient. +// This is used for isCEA inbounds whose recipient is a deployed contract (not a UEA). +func (k Keeper) CallExecuteUniversalTx( + ctx sdk.Context, + recipientAddr common.Address, + sourceChain string, + ceaAddress []byte, + payload []byte, + amount *big.Int, + prc20AssetAddr common.Address, + txId [32]byte, +) (*evmtypes.MsgEthereumTxResponse, error) { + recipientABI, err := types.ParseRecipientContractABI() + if err != nil { + return nil, errors.Wrap(err, "failed to parse recipient contract ABI") + } + + ueModuleAccAddress, _ := k.GetUeModuleAddress(ctx) + + nonce, err := k.GetModuleAccountNonce(ctx) + if err != nil { + return nil, err + } + if _, err := k.IncrementModuleAccountNonce(ctx); err != nil { + return nil, err + } + + return k.evmKeeper.DerivedEVMCall( + ctx, + recipientABI, + ueModuleAccAddress, + recipientAddr, big.NewInt(0), - big.NewInt(0), + nil, + true, + false, + true, + &nonce, + "executeUniversalTx", + sourceChain, + ceaAddress, + payload, + amount, + prc20AssetAddr, + txId, ) } + diff --git a/x/uexecutor/keeper/evm_hooks.go b/x/uexecutor/keeper/evm_hooks.go index d65dc5fa..507bb5ab 100644 --- a/x/uexecutor/keeper/evm_hooks.go +++ b/x/uexecutor/keeper/evm_hooks.go @@ -50,12 +50,13 @@ func (h EVMHooks) PostTxProcessing( Status: "SUCCESS", } - // This will: - // - check if outbound exists - // - create universal tx if needed - // - attach outbounds - // - emit events - return h.k.CreateUniversalTxFromReceiptIfOutbound(ctx, protoReceipt, pcTx) + // Handle normal outbounds (UniversalTxOutbound events → new UTX + outbounds). + if err := h.k.CreateUniversalTxFromReceiptIfOutbound(ctx, protoReceipt, pcTx); err != nil { + return err + } + + // Handle rescue outbounds (RescueFundsOnSourceChain events → attach to original UTX). + return h.k.AttachRescueOutboundFromReceipt(ctx, protoReceipt, pcTx) } func convertReceiptLogs(logs []*ethtypes.Log) []*evmtypes.Log { diff --git a/x/uexecutor/keeper/execute_inbound_funds.go b/x/uexecutor/keeper/execute_inbound_funds.go index e99d5935..c3a10497 100644 --- a/x/uexecutor/keeper/execute_inbound_funds.go +++ b/x/uexecutor/keeper/execute_inbound_funds.go @@ -34,13 +34,13 @@ func (k Keeper) ExecuteInboundFunds(ctx context.Context, utx types.UniversalTx) if err != nil { pcTx.Status = "FAILED" // or "PENDING_REVERT" pcTx.ErrorMsg = err.Error() - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED + } else { pcTx.TxHash = receipt.Hash pcTx.GasUsed = receipt.GasUsed pcTx.Status = "SUCCESS" pcTx.ErrorMsg = "" - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_SUCCESS + } utx.PcTx = append(utx.PcTx, &pcTx) @@ -64,7 +64,7 @@ func (k Keeper) ExecuteInboundFunds(ctx context.Context, utx types.UniversalTx) Sender: inbound.Sender, TxType: types.TxType_INBOUND_REVERT, OutboundStatus: types.Status_PENDING, - Id: types.GetOutboundRevertId(inbound.TxHash), + Id: types.GetOutboundRevertId(inbound.SourceChain, inbound.TxHash), } _ = k.attachOutboundsToUtx(sdkCtx, utx.Id, []*types.OutboundTx{&revertOutbound}, err.Error()) } diff --git a/x/uexecutor/keeper/execute_inbound_funds_and_payload.go b/x/uexecutor/keeper/execute_inbound_funds_and_payload.go index c485e155..a312a650 100644 --- a/x/uexecutor/keeper/execute_inbound_funds_and_payload.go +++ b/x/uexecutor/keeper/execute_inbound_funds_and_payload.go @@ -3,6 +3,7 @@ package keeper import ( "context" "fmt" + "math/big" "strings" sdk "github.com/cosmos/cosmos-sdk/types" @@ -32,29 +33,37 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni var execErr error var receipt *evmtypes.MsgEthereumTxResponse var ueaAddr common.Address + var isSmartContract bool - // When isCEA is true, validate recipient is a UEA before attempting deposit if utx.InboundTx.IsCEA { - // Validate and use recipient as the UEA address + // isCEA path: recipient is explicitly specified. + // Three-way check: + // 1. Recipient is a UEA → existing flow (deposit + ExecutePayloadV2) + // 2. Recipient is a deployed smart contract (not UEA) → deposit + executeUniversalTx + // 3. Neither → record FAILED PCTx, no INBOUND_REVERT if !strings.HasPrefix(strings.ToLower(utx.InboundTx.Recipient), "0x") { execErr = fmt.Errorf("recipient must be a valid hex address when isCEA is true") - shouldRevert = true - revertReason = execErr.Error() } else { ueaAddr = common.HexToAddress(utx.InboundTx.Recipient) - // --- Step 1: Validate that recipient is a UEA _, isUEA, ueaCheckErr := k.CallFactoryGetOriginForUEA(sdkCtx, ueModuleAccAddress, factoryAddress, ueaAddr) if ueaCheckErr != nil { execErr = fmt.Errorf("failed to verify UEA: %w", ueaCheckErr) - shouldRevert = true - revertReason = execErr.Error() - } else if !isUEA { - execErr = fmt.Errorf("recipient is not a valid UEA") - shouldRevert = true - revertReason = execErr.Error() + } else if isUEA { + // UEA path: deposit PRC20 into the UEA, then execute payload via UEA + receipt, execErr = k.depositPRC20( + sdkCtx, + utx.InboundTx.SourceChain, + utx.InboundTx.AssetAddr, + ueaAddr, + utx.InboundTx.Amount, + ) + if execErr != nil { + execErr = fmt.Errorf("depositPRC20 failed: %w", execErr) + } } else { - // --- Step 2: Recipient is valid UEA, deposit PRC20 into it + // Non-UEA path (smart contract or EOA): deposit PRC20 and call executeUniversalTx + isSmartContract = true receipt, execErr = k.depositPRC20( sdkCtx, utx.InboundTx.SourceChain, @@ -64,14 +73,12 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni ) if execErr != nil { execErr = fmt.Errorf("depositPRC20 failed: %w", execErr) - shouldRevert = true - revertReason = execErr.Error() } } } + // isCEA failures never create an INBOUND_REVERT outbound. } else { // Original logic: check factory for UEA, deploy if not deployed - // --- Step 1: check factory for UEA ueaAddrRes, isDeployed, err := k.CallFactoryToGetUEAAddressForOrigin(sdkCtx, ueModuleAccAddress, factoryAddress, &universalAccountId) if err != nil { execErr = fmt.Errorf("factory lookup failed: %w", err) @@ -80,7 +87,6 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni } else { ueaAddr = ueaAddrRes - // deploy UEA if not yet deployed if !isDeployed { deployReceipt, dErr := k.DeployUEAV2(ctx, ueModuleAccAddress, &universalAccountId) if dErr != nil { @@ -105,7 +111,6 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni } if execErr == nil { - // --- Step 2: deposit PRC20 into UEA receipt, err = k.depositPRC20( sdkCtx, utx.InboundTx.SourceChain, @@ -137,16 +142,13 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni } updateErr := k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { utx.PcTx = append(utx.PcTx, &depositPcTx) - if execErr != nil { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED - } return nil }) if updateErr != nil { return updateErr } - // If deposit failed, stop here (don’t attempt payload execution) + // If deposit failed, stop here. if execErr != nil { if shouldRevert { revertOutbound := &types.OutboundTx{ @@ -162,9 +164,8 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni Sender: utx.InboundTx.Sender, TxType: types.TxType_INBOUND_REVERT, OutboundStatus: types.Status_PENDING, - Id: types.GetOutboundRevertId(utx.InboundTx.TxHash), + Id: types.GetOutboundRevertId(utx.InboundTx.SourceChain, utx.InboundTx.TxHash), } - _ = k.attachOutboundsToUtx( sdkCtx, universalTxKey, @@ -172,7 +173,62 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni revertReason, ) } + return nil + } + + // Smart contract path: call executeUniversalTx and return + if isSmartContract { + tokenConfig, tcErr := k.uregistryKeeper.GetTokenConfig(sdkCtx, utx.InboundTx.SourceChain, utx.InboundTx.AssetAddr) + + var contractReceipt *evmtypes.MsgEthereumTxResponse + var contractErr error + + if tcErr != nil { + contractErr = fmt.Errorf("token config lookup failed: %w", tcErr) + } else { + prc20Addr := common.HexToAddress(tokenConfig.NativeRepresentation.ContractAddress) + + amount := new(big.Int) + amount, ok := amount.SetString(utx.InboundTx.Amount, 10) + if !ok { + contractErr = fmt.Errorf("invalid amount: %s", utx.InboundTx.Amount) + } else { + txId := common.HexToHash(utx.Id) + + var payload []byte + if utx.InboundTx.UniversalPayload != nil && utx.InboundTx.UniversalPayload.Data != "" { + payload = common.FromHex(utx.InboundTx.UniversalPayload.Data) + } + + contractReceipt, contractErr = k.CallExecuteUniversalTx( + sdkCtx, + ueaAddr, + utx.InboundTx.SourceChain, + []byte(utx.InboundTx.Sender), + payload, + amount, + prc20Addr, + txId, + ) + } + } + callPcTx := types.PCTx{ + Sender: ueModuleAddressStr, + BlockHeight: uint64(sdkCtx.BlockHeight()), + Status: "FAILED", + } + if contractErr != nil { + callPcTx.ErrorMsg = contractErr.Error() + } else { + callPcTx.TxHash = contractReceipt.Hash + callPcTx.GasUsed = contractReceipt.GasUsed + callPcTx.Status = "SUCCESS" + } + _ = k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { + utx.PcTx = append(utx.PcTx, &callPcTx) + return nil + }) return nil } @@ -181,7 +237,6 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni // --- Step 3: compute and store payload hash payloadHashErr := k.StoreVerifiedPayloadHash(sdkCtx, utx, ueaAddr, ueModuleAddr) if payloadHashErr != nil { - // Update UniversalTx with payload hash error and stop errorPcTx := types.PCTx{ Sender: ueModuleAddressStr, BlockHeight: uint64(sdkCtx.BlockHeight()), @@ -190,14 +245,12 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni } _ = k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { utx.PcTx = append(utx.PcTx, &errorPcTx) - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED return nil }) return nil } - // --- Step 4: execute payload - // ueaAddr is already resolved and validated above (either from recipient for CEA, or from factory) + // --- Step 4: execute payload via UEA var payloadErr error receipt, payloadErr = k.ExecutePayloadV2(ctx, ueModuleAddr, ueaAddr, utx.InboundTx.UniversalPayload, utx.InboundTx.VerificationData) @@ -220,11 +273,6 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni updateErr = k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { utx.PcTx = append(utx.PcTx, &payloadPcTx) - if payloadErr != nil { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED - } else { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_SUCCESS - } return nil }) if updateErr != nil { diff --git a/x/uexecutor/keeper/execute_inbound_gas.go b/x/uexecutor/keeper/execute_inbound_gas.go index f1388e8e..9f4ac891 100644 --- a/x/uexecutor/keeper/execute_inbound_gas.go +++ b/x/uexecutor/keeper/execute_inbound_gas.go @@ -87,12 +87,56 @@ func (k Keeper) ExecuteInboundGas(ctx context.Context, inbound types.Inbound) er } if execErr == nil { - // --- step 4: deposit + swap - receipt, execErr = k.CallPRC20DepositAutoSwap(sdkCtx, prc20AddressHex, ueaAddr, amount) + // --- step 4: fetch swap quote and compute minPCOut with 5% slippage + var ( + quoterAddr common.Address + wpcAddr common.Address + fee *big.Int + quote *big.Int + ) + + quoterAddr, execErr = k.GetUniversalCoreQuoterAddress(sdkCtx) if execErr != nil { shouldRevert = true revertReason = execErr.Error() } + + if execErr == nil { + wpcAddr, execErr = k.GetUniversalCoreWPCAddress(sdkCtx) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } + + if execErr == nil { + fee, execErr = k.GetDefaultFeeTierForToken(sdkCtx, prc20AddressHex) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } + + if execErr == nil { + quote, execErr = k.GetSwapQuote(sdkCtx, quoterAddr, prc20AddressHex, wpcAddr, fee, amount) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } + + if execErr == nil { + // 5% slippage: minPCOut = quote * 95 / 100 + minPCOut := new(big.Int).Mul(quote, big.NewInt(95)) + minPCOut.Div(minPCOut, big.NewInt(100)) + + // --- step 5: deposit + swap + receipt, execErr = k.CallPRC20DepositAutoSwap(sdkCtx, prc20AddressHex, ueaAddr, amount, fee, minPCOut) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } } } } @@ -112,9 +156,9 @@ func (k Keeper) ExecuteInboundGas(ctx context.Context, inbound types.Inbound) er updateErr := k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { utx.PcTx = append(utx.PcTx, &pcTx) if execErr != nil { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED + } else { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_SUCCESS + } return nil }) @@ -137,7 +181,7 @@ func (k Keeper) ExecuteInboundGas(ctx context.Context, inbound types.Inbound) er Sender: inbound.Sender, TxType: types.TxType_INBOUND_REVERT, OutboundStatus: types.Status_PENDING, - Id: types.GetOutboundRevertId(inbound.TxHash), + Id: types.GetOutboundRevertId(inbound.SourceChain, inbound.TxHash), } _ = k.attachOutboundsToUtx( diff --git a/x/uexecutor/keeper/execute_inbound_gas_and_payload.go b/x/uexecutor/keeper/execute_inbound_gas_and_payload.go index b6b52fc1..6d830cbd 100644 --- a/x/uexecutor/keeper/execute_inbound_gas_and_payload.go +++ b/x/uexecutor/keeper/execute_inbound_gas_and_payload.go @@ -84,20 +84,60 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive } if execErr == nil { - // --- Step 4: deposit + autoswap + // --- Step 4: fetch swap quote and compute minPCOut with 5% slippage prc20AddressHex := common.HexToAddress( tokenConfig.NativeRepresentation.ContractAddress, ) - receipt, execErr = k.CallPRC20DepositAutoSwap( - sdkCtx, - prc20AddressHex, - ueaAddr, - amount, + + var ( + quoterAddr common.Address + wpcAddr common.Address + fee *big.Int + quote *big.Int ) + + quoterAddr, execErr = k.GetUniversalCoreQuoterAddress(sdkCtx) if execErr != nil { shouldRevert = true revertReason = execErr.Error() } + + if execErr == nil { + wpcAddr, execErr = k.GetUniversalCoreWPCAddress(sdkCtx) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } + + if execErr == nil { + fee, execErr = k.GetDefaultFeeTierForToken(sdkCtx, prc20AddressHex) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } + + if execErr == nil { + quote, execErr = k.GetSwapQuote(sdkCtx, quoterAddr, prc20AddressHex, wpcAddr, fee, amount) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } + + if execErr == nil { + // 5% slippage: minPCOut = quote * 95 / 100 + minPCOut := new(big.Int).Mul(quote, big.NewInt(95)) + minPCOut.Div(minPCOut, big.NewInt(100)) + + // --- Step 5: deposit + autoswap + receipt, execErr = k.CallPRC20DepositAutoSwap(sdkCtx, prc20AddressHex, ueaAddr, amount, fee, minPCOut) + if execErr != nil { + shouldRevert = true + revertReason = execErr.Error() + } + } } } } @@ -120,7 +160,7 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive updateErr := k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { utx.PcTx = append(utx.PcTx, &depositPcTx) if execErr != nil { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED + } return nil }) @@ -143,7 +183,7 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive Sender: utx.InboundTx.Sender, TxType: types.TxType_INBOUND_REVERT, OutboundStatus: types.Status_PENDING, - Id: types.GetOutboundRevertId(utx.InboundTx.TxHash), + Id: types.GetOutboundRevertId(utx.InboundTx.SourceChain, utx.InboundTx.TxHash), } _ = k.attachOutboundsToUtx( @@ -160,7 +200,7 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive ueModuleAddr, _ := k.GetUeModuleAddress(ctx) - // --- Step 5: payload hash + // --- Step 6: payload hash payloadHashErr := k.StoreVerifiedPayloadHash(sdkCtx, utx, ueaAddr, ueModuleAddr) if payloadHashErr != nil { errorPcTx := types.PCTx{ @@ -171,13 +211,13 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive } _ = k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { utx.PcTx = append(utx.PcTx, &errorPcTx) - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED + return nil }) return nil } - // --- Step 6: execute payload + // --- Step 7: execute payload // ueaAddr is already resolved and validated in step 3 receipt, err = k.ExecutePayloadV2( ctx, @@ -207,9 +247,9 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive updateErr = k.UpdateUniversalTx(ctx, universalTxKey, func(utx *types.UniversalTx) error { utx.PcTx = append(utx.PcTx, &payloadPcTx) if err != nil { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_FAILED + } else { - utx.UniversalStatus = types.UniversalTxStatus_PC_EXECUTED_SUCCESS + } return nil }) diff --git a/x/uexecutor/keeper/gas_price.go b/x/uexecutor/keeper/gas_price.go index f4834486..9e80b8e8 100644 --- a/x/uexecutor/keeper/gas_price.go +++ b/x/uexecutor/keeper/gas_price.go @@ -11,6 +11,7 @@ import ( sdkerrors "cosmossdk.io/errors" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pushchain/push-chain-node/x/uexecutor/types" ) @@ -108,3 +109,4 @@ func computeMedianIndex(values []uint64) int { sort.SliceStable(arr, func(i, j int) bool { return arr[i].Val < arr[j].Val }) return arr[len(arr)/2].Idx } + diff --git a/x/uexecutor/keeper/keeper.go b/x/uexecutor/keeper/keeper.go index c959e948..1fd4d8c3 100755 --- a/x/uexecutor/keeper/keeper.go +++ b/x/uexecutor/keeper/keeper.go @@ -49,6 +49,9 @@ type Keeper struct { // GasPrices collection stores aggregated gas price data for each chain GasPrices collections.Map[string, types.GasPrice] + + // ChainMetas collection stores aggregated chain metadata (gas price + block height) for each chain + ChainMetas collections.Map[string, types.ChainMeta] } // NewKeeper creates a new Keeper instance @@ -118,6 +121,14 @@ func NewKeeper( collections.StringKey, codec.CollValue[types.GasPrice](cdc), ), + + ChainMetas: collections.NewMap( + sb, + types.ChainMetaKey, + types.ChainMetasName, + collections.StringKey, + codec.CollValue[types.ChainMeta](cdc), + ), } return k diff --git a/x/uexecutor/keeper/msg_execute_payload.go b/x/uexecutor/keeper/msg_execute_payload.go index 64efbe60..90b0da03 100644 --- a/x/uexecutor/keeper/msg_execute_payload.go +++ b/x/uexecutor/keeper/msg_execute_payload.go @@ -72,6 +72,9 @@ func (k Keeper) ExecutePayload(ctx context.Context, evmFrom common.Address, univ if err := k.CreateUniversalTxFromReceiptIfOutbound(sdkCtx, receipt, pcTx); err != nil { return err } + if err := k.AttachRescueOutboundFromReceipt(sdkCtx, receipt, pcTx); err != nil { + return err + } gasUnitsUsed := receipt.GasUsed gasUnitsUsedBig := new(big.Int).SetUint64(gasUnitsUsed) diff --git a/x/uexecutor/keeper/msg_server.go b/x/uexecutor/keeper/msg_server.go index 5ef96f65..c2f97fff 100755 --- a/x/uexecutor/keeper/msg_server.go +++ b/x/uexecutor/keeper/msg_server.go @@ -176,3 +176,35 @@ func (ms msgServer) VoteOutbound(ctx context.Context, msg *types.MsgVoteOutbound return &types.MsgVoteOutboundResponse{}, nil } + +// VoteChainMeta implements types.MsgServer. +func (ms msgServer) VoteChainMeta(ctx context.Context, msg *types.MsgVoteChainMeta) (*types.MsgVoteChainMetaResponse, error) { + signerAccAddr, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, fmt.Errorf("invalid signer address: %w", err) + } + + signerValAddr := sdk.ValAddress(signerAccAddr) + + isBonded, err := ms.k.uvalidatorKeeper.IsBondedUniversalValidator(ctx, msg.Signer) + if err != nil { + return nil, errors.Wrapf(err, "failed to check bonded status for signer %s", msg.Signer) + } + if !isBonded { + return nil, fmt.Errorf("universal validator for signer %s is not bonded", msg.Signer) + } + + isTombstoned, err := ms.k.uvalidatorKeeper.IsTombstonedUniversalValidator(ctx, msg.Signer) + if err != nil { + return nil, errors.Wrapf(err, "failed to check tombstoned status for signer %s", msg.Signer) + } + if isTombstoned { + return nil, fmt.Errorf("universal validator for signer %s is tombstoned", msg.Signer) + } + + err = ms.k.VoteChainMeta(ctx, signerValAddr, msg.ObservedChainId, msg.Price, msg.ChainHeight) + if err != nil { + return nil, err + } + return &types.MsgVoteChainMetaResponse{}, nil +} diff --git a/x/uexecutor/keeper/msg_vote_inbound.go b/x/uexecutor/keeper/msg_vote_inbound.go index 8f80b0a3..b0c296c6 100644 --- a/x/uexecutor/keeper/msg_vote_inbound.go +++ b/x/uexecutor/keeper/msg_vote_inbound.go @@ -59,7 +59,6 @@ func (k Keeper) VoteInbound(ctx context.Context, universalValidator sdk.ValAddre InboundTx: &inbound, PcTx: nil, OutboundTx: nil, - UniversalStatus: types.UniversalTxStatus_PENDING_INBOUND_EXECUTION, } // Step 4: If finalized, create the UniversalTx diff --git a/x/uexecutor/keeper/outbound.go b/x/uexecutor/keeper/outbound.go index 11d6042d..892f02a8 100644 --- a/x/uexecutor/keeper/outbound.go +++ b/x/uexecutor/keeper/outbound.go @@ -44,55 +44,165 @@ func (k Keeper) FinalizeOutbound(ctx context.Context, utxId string, outbound typ } obs := outbound.ObservedTx - if obs == nil || obs.Success { - return nil - } - - // Only refund for funds-related tx types - if outbound.TxType != types.TxType_FUNDS && outbound.TxType != types.TxType_GAS_AND_PAYLOAD && - outbound.TxType != types.TxType_FUNDS_AND_PAYLOAD { + if obs == nil { return nil } sdkCtx := sdk.UnwrapSDKContext(ctx) - // Decide refund recipient safely - recipient := outbound.Sender - if outbound.RevertInstructions != nil && - outbound.RevertInstructions.FundRecipient != "" { - recipient = outbound.RevertInstructions.FundRecipient + if !obs.Success { + return k.handleFailedOutbound(sdkCtx, utxId, outbound, obs) } - // Mint tokens back - amount := new(big.Int) - amount, ok := amount.SetString(outbound.Amount, 10) - if !ok { - return fmt.Errorf("invalid amount: %s", outbound.Amount) + return k.handleSuccessfulOutbound(sdkCtx, utxId, outbound, obs) +} + +// handleFailedOutbound mints back the bridged tokens to the revert recipient, +// then attempts to refund any excess gas (gasFee - gasFeeUsed) just like a +// successful outbound would. Both operations are recorded on the outbound. +func (k Keeper) handleFailedOutbound(ctx sdk.Context, utxId string, outbound types.OutboundTx, obs *types.OutboundObservation) error { + // Only revert bridged funds for funds-related tx types + if outbound.TxType == types.TxType_FUNDS || outbound.TxType == types.TxType_GAS_AND_PAYLOAD || + outbound.TxType == types.TxType_FUNDS_AND_PAYLOAD { + + // Decide revert recipient safely + recipient := outbound.Sender + if outbound.RevertInstructions != nil && + outbound.RevertInstructions.FundRecipient != "" { + recipient = outbound.RevertInstructions.FundRecipient + } + + amount := new(big.Int) + amount, ok := amount.SetString(outbound.Amount, 10) + if !ok { + return fmt.Errorf("invalid amount: %s", outbound.Amount) + } + receipt, err := k.CallPRC20Deposit(ctx, common.HexToAddress(outbound.Prc20AssetAddr), common.HexToAddress(recipient), amount) + + pcTx := types.PCTx{ + Sender: outbound.Sender, + BlockHeight: uint64(ctx.BlockHeight()), + } + if err != nil { + pcTx.Status = "FAILED" + pcTx.ErrorMsg = err.Error() + } else { + pcTx.TxHash = receipt.Hash + pcTx.GasUsed = receipt.GasUsed + pcTx.Status = "SUCCESS" + } + outbound.PcRevertExecution = &pcTx } - receipt, err := k.CallPRC20Deposit(sdkCtx, common.HexToAddress(outbound.Prc20AssetAddr), common.HexToAddress(recipient), amount) - // Update outbound status outbound.OutboundStatus = types.Status_REVERTED - pcTx := types.PCTx{ - TxHash: "", // no hash if depositPRC20 failed + // Refund excess gas regardless of tx type — gas was consumed on the external + // chain whether the execution succeeded or failed. + k.applyGasRefund(ctx, &outbound, obs) + + return k.UpdateOutbound(ctx, utxId, outbound) +} + +// handleSuccessfulOutbound refunds unused gas fee when gasFee > gasFeeUsed. +func (k Keeper) handleSuccessfulOutbound(ctx sdk.Context, utxId string, outbound types.OutboundTx, obs *types.OutboundObservation) error { + k.applyGasRefund(ctx, &outbound, obs) + return k.UpdateOutbound(ctx, utxId, outbound) +} + +// applyGasRefund computes the excess gas (gasFee - gasFeeUsed) and, if positive, +// calls UniversalCore refundUnusedGas. The result is recorded in outbound.PcRefundExecution. +// It is called for both successful and failed outbounds — gas is consumed on the +// external chain regardless of execution outcome. +func (k Keeper) applyGasRefund(ctx sdk.Context, outbound *types.OutboundTx, obs *types.OutboundObservation) { + if obs.GasFeeUsed == "" || outbound.GasFee == "" || outbound.GasToken == "" { + return + } + + gasFee := new(big.Int) + if _, ok := gasFee.SetString(outbound.GasFee, 10); !ok { + return + } + + gasFeeUsed := new(big.Int) + if _, ok := gasFeeUsed.SetString(obs.GasFeeUsed, 10); !ok { + return + } + + // No excess gas to refund + if gasFee.Cmp(gasFeeUsed) <= 0 { + return + } + + refundAmount := new(big.Int).Sub(gasFee, gasFeeUsed) + gasToken := common.HexToAddress(outbound.GasToken) + + // Refund recipient: prefer fund_recipient in revert_instructions, fall back to sender + refundRecipient := outbound.Sender + if outbound.RevertInstructions != nil && outbound.RevertInstructions.FundRecipient != "" { + refundRecipient = outbound.RevertInstructions.FundRecipient + } + recipientAddr := common.HexToAddress(refundRecipient) + + refundPcTx := &types.PCTx{ Sender: outbound.Sender, - GasUsed: 0, - BlockHeight: uint64(sdkCtx.BlockHeight()), + BlockHeight: uint64(ctx.BlockHeight()), + } + + // Step 1: try refund with swap (gasToken → PC native) + fee, swapErr := k.GetDefaultFeeTierForToken(ctx, gasToken) + var swapFallbackReason string + + if swapErr == nil { + quote, quoteErr := k.getSwapQuoteForRefund(ctx, gasToken, fee, refundAmount) + if quoteErr == nil { + minPCOut := new(big.Int).Mul(quote, big.NewInt(95)) + minPCOut.Div(minPCOut, big.NewInt(100)) + + resp, err := k.CallUniversalCoreRefundUnusedGas(ctx, gasToken, refundAmount, recipientAddr, true, fee, minPCOut) + if err == nil { + refundPcTx.TxHash = resp.Hash + refundPcTx.GasUsed = resp.GasUsed + refundPcTx.Status = "SUCCESS" + outbound.PcRefundExecution = refundPcTx + return + } + swapFallbackReason = fmt.Sprintf("swap refund failed: %s", err.Error()) + } else { + swapFallbackReason = fmt.Sprintf("quote fetch failed: %s", quoteErr.Error()) + } + } else { + swapFallbackReason = fmt.Sprintf("fee tier fetch failed: %s", swapErr.Error()) } + // Step 2: fallback — refund without swap (deposit PRC20 directly to recipient) + ctx.Logger().Error("applyGasRefund: swap refund failed, falling back to no-swap", + "outbound_id", outbound.Id, + "reason", swapFallbackReason, + ) + + resp, err := k.CallUniversalCoreRefundUnusedGas(ctx, gasToken, refundAmount, recipientAddr, false, big.NewInt(0), big.NewInt(0)) if err != nil { - pcTx.Status = "FAILED" - pcTx.ErrorMsg = err.Error() + refundPcTx.Status = "FAILED" + refundPcTx.ErrorMsg = err.Error() } else { - pcTx.TxHash = receipt.Hash - pcTx.GasUsed = receipt.GasUsed - pcTx.Status = "SUCCESS" - pcTx.ErrorMsg = "" + refundPcTx.TxHash = resp.Hash + refundPcTx.GasUsed = resp.GasUsed + refundPcTx.Status = "SUCCESS" } - outbound.PcRevertExecution = &pcTx + outbound.PcRefundExecution = refundPcTx + outbound.RefundSwapError = swapFallbackReason +} - // Store Reverted tx in Outbound - return k.UpdateOutbound(ctx, utxId, outbound) +// getSwapQuoteForRefund fetches a Uniswap quote for the gas token refund swap. +func (k Keeper) getSwapQuoteForRefund(ctx sdk.Context, gasToken common.Address, fee *big.Int, amount *big.Int) (*big.Int, error) { + quoterAddr, err := k.GetUniversalCoreQuoterAddress(ctx) + if err != nil { + return nil, err + } + wpcAddr, err := k.GetUniversalCoreWPCAddress(ctx) + if err != nil { + return nil, err + } + return k.GetSwapQuote(ctx, quoterAddr, gasToken, wpcAddr, fee, amount) } diff --git a/x/uexecutor/keeper/query_server.go b/x/uexecutor/keeper/query_server.go index 1dbf79ed..95de3c7d 100755 --- a/x/uexecutor/keeper/query_server.go +++ b/x/uexecutor/keeper/query_server.go @@ -58,6 +58,50 @@ func (k Querier) GetUniversalTx(goCtx context.Context, req *types.QueryGetUniver }, nil } +// computeUniversalStatus derives a UniversalTxStatus from the actual state of the +// UTX's components instead of reading a stored field that can go stale. +// +// Priority: outbounds > PC txs > inbound presence. +func computeUniversalStatus(utx *types.UniversalTx) types.UniversalTxStatus { + if len(utx.OutboundTx) > 0 { + anyPending := false + anyReverted := false + for _, ob := range utx.OutboundTx { + if ob == nil { + continue + } + switch ob.OutboundStatus { + case types.Status_PENDING: + anyPending = true + case types.Status_REVERTED: + anyReverted = true + } + } + if anyPending { + return types.UniversalTxStatus_OUTBOUND_PENDING + } + if anyReverted { + return types.UniversalTxStatus_OUTBOUND_FAILED + } + return types.UniversalTxStatus_OUTBOUND_SUCCESS + } + + if len(utx.PcTx) > 0 { + for _, pc := range utx.PcTx { + if pc != nil && pc.Status == "FAILED" { + return types.UniversalTxStatus_PC_EXECUTED_FAILED + } + } + return types.UniversalTxStatus_PC_EXECUTED_SUCCESS + } + + if utx.InboundTx != nil { + return types.UniversalTxStatus_PENDING_INBOUND_EXECUTION + } + + return types.UniversalTxStatus_UNIVERSAL_TX_STATUS_UNSPECIFIED +} + // convertToUniversalTxLegacy maps the current (post-upgrade) UniversalTx to the legacy shape func convertToUniversalTxLegacy(current *types.UniversalTx) *types.UniversalTxLegacy { if current == nil { @@ -108,7 +152,7 @@ func convertToUniversalTxLegacy(current *types.UniversalTx) *types.UniversalTxLe InboundTx: legacyInbound, PcTx: pcTxs, OutboundTx: legacyOutbound, - UniversalStatus: current.UniversalStatus, + UniversalStatus: computeUniversalStatus(current), } } @@ -179,6 +223,7 @@ func (k Keeper) AllPendingInbounds(goCtx context.Context, req *types.QueryAllPen } // GasPrice implements types.QueryServer. +// Sources data from ChainMetas (the new unified store) to maintain backward compatibility. func (k Querier) GasPrice(goCtx context.Context, req *types.QueryGasPriceRequest) (*types.QueryGasPriceResponse, error) { if req == nil || req.ChainId == "" { return nil, status.Error(codes.InvalidArgument, "chain_id is required") @@ -186,7 +231,18 @@ func (k Querier) GasPrice(goCtx context.Context, req *types.QueryGasPriceRequest ctx := sdk.UnwrapSDKContext(goCtx) - // Try to fetch the gas price from keeper + // Source from ChainMetas first (preferred post-upgrade storage) + cm, err := k.ChainMetas.Get(ctx, req.ChainId) + if err == nil { + return &types.QueryGasPriceResponse{ + GasPrice: chainMetaToGasPrice(&cm), + }, nil + } + if !errors.Is(err, collections.ErrNotFound) { + return nil, status.Error(codes.Internal, err.Error()) + } + + // Fallback to legacy GasPrices store (pre-upgrade nodes) gasPrice, err := k.GasPrices.Get(ctx, req.ChainId) if err != nil { if errors.Is(err, collections.ErrNotFound) { @@ -195,12 +251,12 @@ func (k Querier) GasPrice(goCtx context.Context, req *types.QueryGasPriceRequest return nil, status.Error(codes.Internal, err.Error()) } - return &types.QueryGasPriceResponse{ - GasPrice: &gasPrice, - }, nil + return &types.QueryGasPriceResponse{GasPrice: &gasPrice}, nil } // AllGasPrices implements types.QueryServer. +// Sources data from ChainMetas (the new unified store) to maintain backward compatibility. +// Falls back to the legacy GasPrices store for entries not yet migrated. func (k Querier) AllGasPrices(goCtx context.Context, req *types.QueryAllGasPricesRequest) (*types.QueryAllGasPricesResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") @@ -210,8 +266,9 @@ func (k Querier) AllGasPrices(goCtx context.Context, req *types.QueryAllGasPrice var all []*types.GasPrice - items, pageRes, err := query.CollectionPaginate(ctx, k.GasPrices, req.Pagination, func(key string, value types.GasPrice) (*types.GasPrice, error) { - return &value, nil + // Primary: read from ChainMetas + items, pageRes, err := query.CollectionPaginate(ctx, k.ChainMetas, req.Pagination, func(_ string, value types.ChainMeta) (*types.GasPrice, error) { + return chainMetaToGasPrice(&value), nil }) if err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -224,3 +281,57 @@ func (k Querier) AllGasPrices(goCtx context.Context, req *types.QueryAllGasPrice Pagination: pageRes, }, nil } + +// ChainMeta implements types.QueryServer. +// Returns the aggregated chain metadata (gas price + chain height) for a specific chain. +func (k Querier) ChainMeta(goCtx context.Context, req *types.QueryChainMetaRequest) (*types.QueryChainMetaResponse, error) { + if req == nil || req.ChainId == "" { + return nil, status.Error(codes.InvalidArgument, "chain_id is required") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + + cm, err := k.ChainMetas.Get(ctx, req.ChainId) + if err != nil { + if errors.Is(err, collections.ErrNotFound) { + return nil, status.Errorf(codes.NotFound, "no chain meta found for chain_id: %s", req.ChainId) + } + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryChainMetaResponse{ChainMeta: &cm}, nil +} + +// AllChainMetas implements types.QueryServer. +// Returns paginated chain meta entries for all registered chains. +func (k Querier) AllChainMetas(goCtx context.Context, req *types.QueryAllChainMetasRequest) (*types.QueryAllChainMetasResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + + items, pageRes, err := query.CollectionPaginate(ctx, k.ChainMetas, req.Pagination, func(_ string, value types.ChainMeta) (*types.ChainMeta, error) { + return &value, nil + }) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryAllChainMetasResponse{ + ChainMetas: items, + Pagination: pageRes, + }, nil +} + +// chainMetaToGasPrice converts a ChainMeta into the legacy GasPrice shape +// so that existing API consumers see no breaking change. +func chainMetaToGasPrice(cm *types.ChainMeta) *types.GasPrice { + return &types.GasPrice{ + ObservedChainId: cm.ObservedChainId, + Signers: cm.Signers, + BlockNums: cm.ChainHeights, + Prices: cm.Prices, + MedianIndex: cm.MedianIndex, + } +} diff --git a/x/uexecutor/keeper/universal_tx.go b/x/uexecutor/keeper/universal_tx.go index d260c026..d81dd29b 100644 --- a/x/uexecutor/keeper/universal_tx.go +++ b/x/uexecutor/keeper/universal_tx.go @@ -25,7 +25,9 @@ func (k Keeper) CreateUniversalTx(ctx context.Context, key string, utx types.Uni return k.UniversalTx.Set(ctx, key, utx) } -// GetUniversalTx retrieves a UniversalTx by key, returns (value, found, error) +// GetUniversalTx retrieves a UniversalTx by key, returns (value, found, error). +// UniversalStatus is always populated on-the-fly from the actual component states +// so it is never stale regardless of what was written to storage. func (k Keeper) GetUniversalTx(ctx context.Context, key string) (types.UniversalTx, bool, error) { utx, err := k.UniversalTx.Get(ctx, key) if err != nil { @@ -67,28 +69,6 @@ func (k Keeper) HasUniversalTx(ctx context.Context, key string) (bool, error) { return k.UniversalTx.Has(ctx, key) } -// UpdateUniversalTxStatus sets a new status for the UniversalTx -func (k Keeper) UpdateUniversalTxStatus(ctx context.Context, key string, newStatus types.UniversalTxStatus) error { - utx, err := k.UniversalTx.Get(ctx, key) - if err != nil { - return err - } - - utx.UniversalStatus = newStatus - return k.UniversalTx.Set(ctx, key, utx) -} - -// GetUniversalTxStatus retrieves the status of a UniversalTx -func (k Keeper) GetUniversalTxStatus(ctx context.Context, key string) (types.UniversalTxStatus, bool, error) { - utx, found, err := k.GetUniversalTx(ctx, key) - if err != nil { - return types.UniversalTxStatus_UNIVERSAL_TX_STATUS_UNSPECIFIED, false, err - } - if !found { - return types.UniversalTxStatus_UNIVERSAL_TX_STATUS_UNSPECIFIED, false, nil - } - return utx.UniversalStatus, true, nil -} func (k Keeper) BuildPcUniversalTxKey(ctx context.Context, pc types.PCTx) (string, error) { sdkCtx := sdk.UnwrapSDKContext(ctx) diff --git a/x/uexecutor/migrations/v4/migrate.go b/x/uexecutor/migrations/v4/migrate.go index 7d4b4040..5f575a96 100644 --- a/x/uexecutor/migrations/v4/migrate.go +++ b/x/uexecutor/migrations/v4/migrate.go @@ -45,11 +45,10 @@ func MigrateUniversalTx(ctx sdk.Context, k *keeper.Keeper, cdc codec.BinaryCodec // Build new UniversalTx using old key as new .Id newTx := uexecutortypes.UniversalTx{ - Id: oldKey, - InboundTx: mapInbound(oldTx.InboundTx), - PcTx: oldTx.PcTx, - OutboundTx: mapOutbound(oldTx.OutboundTx), - UniversalStatus: oldTx.UniversalStatus, + Id: oldKey, + InboundTx: mapInbound(oldTx.InboundTx), + PcTx: oldTx.PcTx, + OutboundTx: mapOutbound(oldTx.OutboundTx), } if err := k.UniversalTx.Set(ctx, newTx.Id, newTx); err != nil { diff --git a/x/uexecutor/migrations/v5/migrate.go b/x/uexecutor/migrations/v5/migrate.go new file mode 100644 index 00000000..cc82b1b6 --- /dev/null +++ b/x/uexecutor/migrations/v5/migrate.go @@ -0,0 +1,13 @@ +package v5 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/pushchain/push-chain-node/x/uexecutor/keeper" +) + +// MigrateGasPricesToChainMeta seeds the ChainMetas collection from the legacy +// GasPrices store. This is idempotent — existing ChainMeta entries are not overwritten. +func MigrateGasPricesToChainMeta(ctx sdk.Context, k *keeper.Keeper) error { + return k.MigrateGasPricesToChainMeta(ctx) +} diff --git a/x/uexecutor/module.go b/x/uexecutor/module.go index 2e7f261d..dbe947e8 100755 --- a/x/uexecutor/module.go +++ b/x/uexecutor/module.go @@ -25,11 +25,12 @@ import ( v2 "github.com/pushchain/push-chain-node/x/uexecutor/migrations/v2" v4 "github.com/pushchain/push-chain-node/x/uexecutor/migrations/v4" + v5 "github.com/pushchain/push-chain-node/x/uexecutor/migrations/v5" ) const ( // ConsensusVersion defines the current x/uexecutor module consensus version. - ConsensusVersion = 4 + ConsensusVersion = 5 ) var ( @@ -180,7 +181,14 @@ func (a AppModule) RegisterServices(cfg module.Configurator) { // Register UExecutor custom migration for v2 (from version 3 -> 4) if err := cfg.RegisterMigration(types.ModuleName, 3, a.migrateToV4()); err != nil { - panic(fmt.Sprintf("failed to migrate %s from version 2 to 3: %v", types.ModuleName, err)) + panic(fmt.Sprintf("failed to migrate %s from version 3 to 4: %v", types.ModuleName, err)) + } + + // Register UExecutor migration from version 4 -> 5 (chain-meta upgrade) + // GasPrices → ChainMetas migration is handled explicitly in the upgrade handler + // before RunMigrations is called, so this is a no-op. + if err := cfg.RegisterMigration(types.ModuleName, 4, a.migrateToV5()); err != nil { + panic(fmt.Sprintf("failed to migrate %s from version 4 to 5: %v", types.ModuleName, err)) } } @@ -208,6 +216,13 @@ func (a AppModule) migrateToV4() module.MigrationHandler { } } +func (a AppModule) migrateToV5() module.MigrationHandler { + return func(ctx sdk.Context) error { + ctx.Logger().Info("🔧 Running uexecutor module migration: v4 → v5 (chain-meta)") + return v5.MigrateGasPricesToChainMeta(ctx, &a.keeper) + } +} + // ConsensusVersion is a sequence number for state-breaking change of the // module. It should be incremented on each consensus-breaking change // introduced by the module. To avoid wrong/empty versions, the initial version diff --git a/x/uexecutor/types/abi.go b/x/uexecutor/types/abi.go index 05a652a6..0512ad62 100644 --- a/x/uexecutor/types/abi.go +++ b/x/uexecutor/types/abi.go @@ -299,9 +299,104 @@ const UNIVERSAL_CORE_ABI = `[ ], "outputs": [], "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setChainMeta", + "inputs": [ + { "name": "chainNamespace", "type": "string", "internalType": "string" }, + { "name": "price", "type": "uint256", "internalType": "uint256" }, + { "name": "chainHeight", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "gasPriceByChainNamespace", + "inputs": [{ "name": "", "type": "string", "internalType": "string" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "chainHeightByChainNamespace", + "inputs": [{ "name": "", "type": "string", "internalType": "string" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "timestampObservedAtByChainNamespace", + "inputs": [{ "name": "", "type": "string", "internalType": "string" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "uniswapV3Quoter", + "inputs": [], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "WPC", + "inputs": [], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "defaultFeeTier", + "inputs": [{ "name": "", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint24", "internalType": "uint24" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "refundUnusedGas", + "inputs": [ + { "name": "gasToken", "type": "address", "internalType": "address" }, + { "name": "amount", "type": "uint256", "internalType": "uint256" }, + { "name": "recipient", "type": "address", "internalType": "address" }, + { "name": "withSwap", "type": "bool", "internalType": "bool" }, + { "name": "fee", "type": "uint24", "internalType": "uint24" }, + { "name": "minPCOut", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [], + "stateMutability": "nonpayable" } ]` +const UNISWAP_QUOTER_V2_ABI = `[ + { + "type": "function", + "name": "quoteExactInputSingle", + "inputs": [ + { + "name": "params", + "type": "tuple", + "internalType": "struct IQuoterV2.QuoteExactInputSingleParams", + "components": [ + { "name": "tokenIn", "type": "address", "internalType": "address" }, + { "name": "tokenOut", "type": "address", "internalType": "address" }, + { "name": "amountIn", "type": "uint256", "internalType": "uint256" }, + { "name": "fee", "type": "uint24", "internalType": "uint24" }, + { "name": "sqrtPriceLimitX96", "type": "uint160", "internalType": "uint160" } + ] + } + ], + "outputs": [ + { "name": "amountOut", "type": "uint256", "internalType": "uint256" }, + { "name": "sqrtPriceX96After", "type": "uint160", "internalType": "uint160" }, + { "name": "initializedTicksCrossed", "type": "uint32", "internalType": "uint32" }, + { "name": "gasEstimate", "type": "uint256", "internalType": "uint256" } + ], + "stateMutability": "nonpayable" + } +]` + const PRC20ABI = `[ { "type": "function", @@ -691,6 +786,10 @@ func ParseFactoryABI() (abi.ABI, error) { return abi.JSON(strings.NewReader(FactoryV1ABI)) } +func ParseUniswapQuoterV2ABI() (abi.ABI, error) { + return abi.JSON(strings.NewReader(UNISWAP_QUOTER_V2_ABI)) +} + func ParseUeaABI() (abi.ABI, error) { return abi.JSON(strings.NewReader(UeaV1ABI)) } @@ -703,6 +802,28 @@ func ParseUniversalCoreABI() (abi.ABI, error) { return abi.JSON(strings.NewReader(UNIVERSAL_CORE_ABI)) } +// RecipientContractABI is the ABI for smart-contract recipients that implement executeUniversalTx. +const RecipientContractABI = `[ + { + "type": "function", + "name": "executeUniversalTx", + "inputs": [ + { "name": "sourceChain", "type": "string" }, + { "name": "ceaAddress", "type": "bytes" }, + { "name": "payload", "type": "bytes" }, + { "name": "amount", "type": "uint256" }, + { "name": "prc20AssetAddr", "type": "address" }, + { "name": "txId", "type": "bytes32" } + ], + "outputs": [], + "stateMutability": "nonpayable" + } +]` + +func ParseRecipientContractABI() (abi.ABI, error) { + return abi.JSON(strings.NewReader(RecipientContractABI)) +} + type AbiUniversalPayload struct { To common.Address Value *big.Int @@ -768,3 +889,12 @@ func NewAbiUniversalAccountId(proto *UniversalAccountId) (AbiUniversalAccountId, Owner: owner, }, nil } + +// AbiQuoteExactInputSingleParams matches IQuoterV2.QuoteExactInputSingleParams +type AbiQuoteExactInputSingleParams struct { + TokenIn common.Address + TokenOut common.Address + AmountIn *big.Int + Fee *big.Int // uint24 + SqrtPriceLimitX96 *big.Int // uint160, 0 = no limit +} diff --git a/x/uexecutor/types/chain_meta.go b/x/uexecutor/types/chain_meta.go new file mode 100644 index 00000000..8a80d9c7 --- /dev/null +++ b/x/uexecutor/types/chain_meta.go @@ -0,0 +1,19 @@ +package types + +import ( + "encoding/json" +) + +// Stringer method for ChainMeta. +func (p ChainMeta) String() string { + bz, err := json.Marshal(p) + if err != nil { + panic(err) + } + return string(bz) +} + +// ValidateBasic does the sanity check on the ChainMeta fields. +func (p ChainMeta) ValidateBasic() error { + return nil +} diff --git a/x/uexecutor/types/chain_meta.pb.go b/x/uexecutor/types/chain_meta.pb.go new file mode 100644 index 00000000..8d40390f --- /dev/null +++ b/x/uexecutor/types/chain_meta.pb.go @@ -0,0 +1,843 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: uexecutor/v1/chain_meta.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ChainMeta stores aggregated chain metadata (gas price + block height) for a given chain +type ChainMeta struct { + ObservedChainId string `protobuf:"bytes,1,opt,name=observed_chain_id,json=observedChainId,proto3" json:"observed_chain_id,omitempty"` + Signers []string `protobuf:"bytes,2,rep,name=signers,proto3" json:"signers,omitempty"` + Prices []uint64 `protobuf:"varint,3,rep,packed,name=prices,proto3" json:"prices,omitempty"` + ChainHeights []uint64 `protobuf:"varint,4,rep,packed,name=chain_heights,json=chainHeights,proto3" json:"chain_heights,omitempty"` + StoredAts []uint64 `protobuf:"varint,5,rep,packed,name=stored_ats,json=storedAts,proto3" json:"stored_ats,omitempty"` + MedianIndex uint64 `protobuf:"varint,6,opt,name=median_index,json=medianIndex,proto3" json:"median_index,omitempty"` + LastAppliedChainHeight uint64 `protobuf:"varint,7,opt,name=last_applied_chain_height,json=lastAppliedChainHeight,proto3" json:"last_applied_chain_height,omitempty"` +} + +func (m *ChainMeta) Reset() { *m = ChainMeta{} } +func (*ChainMeta) ProtoMessage() {} +func (*ChainMeta) Descriptor() ([]byte, []int) { + return fileDescriptor_7d3b1b8d71b3d806, []int{0} +} +func (m *ChainMeta) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ChainMeta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ChainMeta.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 *ChainMeta) XXX_Merge(src proto.Message) { + xxx_messageInfo_ChainMeta.Merge(m, src) +} +func (m *ChainMeta) XXX_Size() int { + return m.Size() +} +func (m *ChainMeta) XXX_DiscardUnknown() { + xxx_messageInfo_ChainMeta.DiscardUnknown(m) +} + +var xxx_messageInfo_ChainMeta proto.InternalMessageInfo + +func (m *ChainMeta) GetObservedChainId() string { + if m != nil { + return m.ObservedChainId + } + return "" +} + +func (m *ChainMeta) GetSigners() []string { + if m != nil { + return m.Signers + } + return nil +} + +func (m *ChainMeta) GetPrices() []uint64 { + if m != nil { + return m.Prices + } + return nil +} + +func (m *ChainMeta) GetChainHeights() []uint64 { + if m != nil { + return m.ChainHeights + } + return nil +} + +func (m *ChainMeta) GetStoredAts() []uint64 { + if m != nil { + return m.StoredAts + } + return nil +} + +func (m *ChainMeta) GetMedianIndex() uint64 { + if m != nil { + return m.MedianIndex + } + return 0 +} + +func (m *ChainMeta) GetLastAppliedChainHeight() uint64 { + if m != nil { + return m.LastAppliedChainHeight + } + return 0 +} + +func init() { + proto.RegisterType((*ChainMeta)(nil), "uexecutor.v1.ChainMeta") +} + +func init() { proto.RegisterFile("uexecutor/v1/chain_meta.proto", fileDescriptor_7d3b1b8d71b3d806) } + +var fileDescriptor_7d3b1b8d71b3d806 = []byte{ + // 360 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x41, 0x6b, 0xfa, 0x30, + 0x18, 0xc6, 0x5b, 0xf5, 0xaf, 0x34, 0x7f, 0xc7, 0x30, 0x88, 0x64, 0x82, 0xb5, 0x6e, 0x97, 0x22, + 0x68, 0x91, 0xc1, 0x60, 0xbb, 0x39, 0x2f, 0xf3, 0x30, 0x18, 0x3d, 0xee, 0x52, 0x62, 0x1b, 0xda, + 0x80, 0x6d, 0x4a, 0x93, 0x8a, 0xfb, 0x0a, 0x3b, 0xed, 0xb8, 0xa3, 0x9f, 0x60, 0xec, 0x63, 0xec, + 0xe8, 0x71, 0xc7, 0xa1, 0x87, 0xed, 0x63, 0x8c, 0x26, 0xd3, 0x5e, 0xc2, 0xfb, 0xfe, 0x9e, 0x27, + 0xef, 0x43, 0xde, 0x80, 0x5e, 0x4e, 0xd6, 0xc4, 0xcf, 0x05, 0xcb, 0x9c, 0xd5, 0xc4, 0xf1, 0x23, + 0x4c, 0x13, 0x2f, 0x26, 0x02, 0x8f, 0xd3, 0x8c, 0x09, 0x06, 0x9b, 0x47, 0x79, 0xbc, 0x9a, 0x74, + 0xdb, 0x21, 0x0b, 0x99, 0x14, 0x9c, 0xa2, 0x52, 0x9e, 0x6e, 0x0b, 0xc7, 0x34, 0x61, 0x8e, 0x3c, + 0x15, 0x3a, 0x7f, 0xab, 0x00, 0x63, 0x56, 0xcc, 0xba, 0x27, 0x02, 0xc3, 0x21, 0x68, 0xb1, 0x05, + 0x27, 0xd9, 0x8a, 0x04, 0x9e, 0x4a, 0xa0, 0x01, 0xd2, 0x2d, 0xdd, 0x36, 0xdc, 0xd3, 0x83, 0x20, + 0xdd, 0xf3, 0x00, 0x22, 0xd0, 0xe0, 0x34, 0x4c, 0x48, 0xc6, 0x51, 0xc5, 0xaa, 0xda, 0x86, 0x7b, + 0x68, 0x61, 0x07, 0xd4, 0xd3, 0x8c, 0xfa, 0x84, 0xa3, 0xaa, 0x55, 0xb5, 0x6b, 0xee, 0x5f, 0x07, + 0x2f, 0xc0, 0x89, 0x1a, 0x1a, 0x11, 0x1a, 0x46, 0x82, 0xa3, 0x9a, 0x94, 0x9b, 0x12, 0xde, 0x29, + 0x06, 0x7b, 0x00, 0x70, 0xc1, 0x32, 0x12, 0x78, 0x58, 0x70, 0xf4, 0x4f, 0x3a, 0x0c, 0x45, 0xa6, + 0x82, 0xc3, 0x01, 0x68, 0xc6, 0x24, 0xa0, 0x38, 0xf1, 0x68, 0x12, 0x90, 0x35, 0xaa, 0x5b, 0xba, + 0x5d, 0x73, 0xff, 0x2b, 0x36, 0x2f, 0x10, 0xbc, 0x06, 0x67, 0x4b, 0xcc, 0x85, 0x87, 0xd3, 0x74, + 0x49, 0x8f, 0x0f, 0x51, 0x99, 0xa8, 0x21, 0xfd, 0x9d, 0xc2, 0x30, 0x55, 0xfa, 0xac, 0x4c, 0xbf, + 0x19, 0xbc, 0x6e, 0xfa, 0xda, 0xcf, 0xa6, 0xaf, 0x3f, 0x7f, 0xbf, 0x0f, 0xdb, 0xe5, 0xc2, 0xcb, + 0x6d, 0xdf, 0x3e, 0x7c, 0xec, 0x4c, 0x7d, 0xbb, 0x33, 0xf5, 0xaf, 0x9d, 0xa9, 0xbf, 0xec, 0x4d, + 0x6d, 0xbb, 0x37, 0xb5, 0xcf, 0xbd, 0xa9, 0x3d, 0x5e, 0x85, 0x54, 0x44, 0xf9, 0x62, 0xec, 0xb3, + 0xd8, 0x49, 0x73, 0x1e, 0xc9, 0x4b, 0xb2, 0x1a, 0xc9, 0x72, 0x94, 0xb0, 0x80, 0x38, 0x6b, 0xa7, + 0x1c, 0x2b, 0x9e, 0x52, 0xc2, 0x17, 0x75, 0xf9, 0x13, 0x97, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x56, 0x15, 0xab, 0x60, 0xe1, 0x01, 0x00, 0x00, +} + +func (this *ChainMeta) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ChainMeta) + if !ok { + that2, ok := that.(ChainMeta) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.ObservedChainId != that1.ObservedChainId { + return false + } + if len(this.Signers) != len(that1.Signers) { + return false + } + for i := range this.Signers { + if this.Signers[i] != that1.Signers[i] { + return false + } + } + if len(this.Prices) != len(that1.Prices) { + return false + } + for i := range this.Prices { + if this.Prices[i] != that1.Prices[i] { + return false + } + } + if len(this.ChainHeights) != len(that1.ChainHeights) { + return false + } + for i := range this.ChainHeights { + if this.ChainHeights[i] != that1.ChainHeights[i] { + return false + } + } + if len(this.StoredAts) != len(that1.StoredAts) { + return false + } + for i := range this.StoredAts { + if this.StoredAts[i] != that1.StoredAts[i] { + return false + } + } + if this.MedianIndex != that1.MedianIndex { + return false + } + if this.LastAppliedChainHeight != that1.LastAppliedChainHeight { + return false + } + return true +} +func (m *ChainMeta) 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 *ChainMeta) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ChainMeta) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LastAppliedChainHeight != 0 { + i = encodeVarintChainMeta(dAtA, i, uint64(m.LastAppliedChainHeight)) + i-- + dAtA[i] = 0x38 + } + if m.MedianIndex != 0 { + i = encodeVarintChainMeta(dAtA, i, uint64(m.MedianIndex)) + i-- + dAtA[i] = 0x30 + } + if len(m.StoredAts) > 0 { + dAtA2 := make([]byte, len(m.StoredAts)*10) + var j1 int + for _, num := range m.StoredAts { + for num >= 1<<7 { + dAtA2[j1] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j1++ + } + dAtA2[j1] = uint8(num) + j1++ + } + i -= j1 + copy(dAtA[i:], dAtA2[:j1]) + i = encodeVarintChainMeta(dAtA, i, uint64(j1)) + i-- + dAtA[i] = 0x2a + } + if len(m.ChainHeights) > 0 { + dAtA4 := make([]byte, len(m.ChainHeights)*10) + var j3 int + for _, num := range m.ChainHeights { + for num >= 1<<7 { + dAtA4[j3] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j3++ + } + dAtA4[j3] = uint8(num) + j3++ + } + i -= j3 + copy(dAtA[i:], dAtA4[:j3]) + i = encodeVarintChainMeta(dAtA, i, uint64(j3)) + i-- + dAtA[i] = 0x22 + } + if len(m.Prices) > 0 { + dAtA6 := make([]byte, len(m.Prices)*10) + var j5 int + for _, num := range m.Prices { + for num >= 1<<7 { + dAtA6[j5] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j5++ + } + dAtA6[j5] = uint8(num) + j5++ + } + i -= j5 + copy(dAtA[i:], dAtA6[:j5]) + i = encodeVarintChainMeta(dAtA, i, uint64(j5)) + i-- + dAtA[i] = 0x1a + } + if len(m.Signers) > 0 { + for iNdEx := len(m.Signers) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Signers[iNdEx]) + copy(dAtA[i:], m.Signers[iNdEx]) + i = encodeVarintChainMeta(dAtA, i, uint64(len(m.Signers[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.ObservedChainId) > 0 { + i -= len(m.ObservedChainId) + copy(dAtA[i:], m.ObservedChainId) + i = encodeVarintChainMeta(dAtA, i, uint64(len(m.ObservedChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintChainMeta(dAtA []byte, offset int, v uint64) int { + offset -= sovChainMeta(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ChainMeta) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ObservedChainId) + if l > 0 { + n += 1 + l + sovChainMeta(uint64(l)) + } + if len(m.Signers) > 0 { + for _, s := range m.Signers { + l = len(s) + n += 1 + l + sovChainMeta(uint64(l)) + } + } + if len(m.Prices) > 0 { + l = 0 + for _, e := range m.Prices { + l += sovChainMeta(uint64(e)) + } + n += 1 + sovChainMeta(uint64(l)) + l + } + if len(m.ChainHeights) > 0 { + l = 0 + for _, e := range m.ChainHeights { + l += sovChainMeta(uint64(e)) + } + n += 1 + sovChainMeta(uint64(l)) + l + } + if len(m.StoredAts) > 0 { + l = 0 + for _, e := range m.StoredAts { + l += sovChainMeta(uint64(e)) + } + n += 1 + sovChainMeta(uint64(l)) + l + } + if m.MedianIndex != 0 { + n += 1 + sovChainMeta(uint64(m.MedianIndex)) + } + if m.LastAppliedChainHeight != 0 { + n += 1 + sovChainMeta(uint64(m.LastAppliedChainHeight)) + } + return n +} + +func sovChainMeta(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozChainMeta(x uint64) (n int) { + return sovChainMeta(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ChainMeta) 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 ErrIntOverflowChainMeta + } + 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: ChainMeta: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ChainMeta: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObservedChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + 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 ErrInvalidLengthChainMeta + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthChainMeta + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ObservedChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signers", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + 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 ErrInvalidLengthChainMeta + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthChainMeta + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signers = append(m.Signers, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Prices = append(m.Prices, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthChainMeta + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthChainMeta + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.Prices) == 0 { + m.Prices = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Prices = append(m.Prices, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field Prices", wireType) + } + case 4: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ChainHeights = append(m.ChainHeights, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthChainMeta + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthChainMeta + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.ChainHeights) == 0 { + m.ChainHeights = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ChainHeights = append(m.ChainHeights, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field ChainHeights", wireType) + } + case 5: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.StoredAts = append(m.StoredAts, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthChainMeta + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthChainMeta + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.StoredAts) == 0 { + m.StoredAts = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.StoredAts = append(m.StoredAts, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field StoredAts", wireType) + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MedianIndex", wireType) + } + m.MedianIndex = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MedianIndex |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastAppliedChainHeight", wireType) + } + m.LastAppliedChainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowChainMeta + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastAppliedChainHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipChainMeta(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthChainMeta + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipChainMeta(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowChainMeta + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowChainMeta + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowChainMeta + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthChainMeta + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupChainMeta + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthChainMeta + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthChainMeta = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowChainMeta = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupChainMeta = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/uexecutor/types/constants.go b/x/uexecutor/types/constants.go index 35d94535..d125e3b8 100644 --- a/x/uexecutor/types/constants.go +++ b/x/uexecutor/types/constants.go @@ -43,5 +43,9 @@ const ( ) var UniversalTxOutboundEventSig = crypto.Keccak256Hash([]byte( - "UniversalTxOutbound(bytes32,address,string,address,bytes,uint256,address,uint256,uint256,bytes,uint256,address,uint8)", + "UniversalTxOutbound(bytes32,address,string,address,bytes,uint256,address,uint256,uint256,bytes,uint256,address,uint8,uint256)", +)).Hex() + +var RescueFundsOnSourceChainEventSig = crypto.Keccak256Hash([]byte( + "RescueFundsOnSourceChain(bytes32,address,string,address,uint8,uint256,uint256,uint256)", )).Hex() diff --git a/x/uexecutor/types/events.go b/x/uexecutor/types/events.go index 8ad2f911..59e62187 100644 --- a/x/uexecutor/types/events.go +++ b/x/uexecutor/types/events.go @@ -21,7 +21,10 @@ type OutboundCreatedEvent struct { AssetAddr string `json:"asset_addr"` Sender string `json:"sender"` Payload string `json:"payload"` + GasFee string `json:"gas_fee"` GasLimit string `json:"gas_limit"` + GasPrice string `json:"gas_price"` + GasToken string `json:"gas_token"` TxType string `json:"tx_type"` PcTxHash string `json:"pc_tx_hash"` LogIndex string `json:"log_index"` @@ -49,7 +52,10 @@ func NewOutboundCreatedEvent(e OutboundCreatedEvent) (sdk.Event, error) { sdk.NewAttribute("asset_addr", e.AssetAddr), sdk.NewAttribute("sender", e.Sender), sdk.NewAttribute("payload", e.Payload), + sdk.NewAttribute("gas_fee", e.GasFee), sdk.NewAttribute("gas_limit", e.GasLimit), + sdk.NewAttribute("gas_price", e.GasPrice), + sdk.NewAttribute("gas_token", e.GasToken), sdk.NewAttribute("tx_type", e.TxType), sdk.NewAttribute("pc_tx_hash", e.PcTxHash), sdk.NewAttribute("log_index", e.LogIndex), diff --git a/x/uexecutor/types/gateway_pc_event_decode.go b/x/uexecutor/types/gateway_pc_event_decode.go index 8a2da39b..d56e2bef 100644 --- a/x/uexecutor/types/gateway_pc_event_decode.go +++ b/x/uexecutor/types/gateway_pc_event_decode.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "math/big" + "strings" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/ethereum/go-ethereum/accounts/abi" @@ -24,6 +25,7 @@ type UniversalTxOutboundEvent struct { ProtocolFee *big.Int // fee kept by protocol RevertRecipient string // where funds go on full revert TxType TxType // ← single source of truth from proto + GasPrice *big.Int // gas price on destination chain at time of outbound } func DecodeUniversalTxOutboundFromLog(log *evmtypes.Log) (*UniversalTxOutboundEvent, error) { @@ -58,6 +60,7 @@ func DecodeUniversalTxOutboundFromLog(log *evmtypes.Log) (*UniversalTxOutboundEv {Type: uint256Type}, // protocolFee {Type: addressType}, // revertRecipient {Type: uint8Type}, // txType + {Type: uint256Type}, // gasPrice } values, err := arguments.Unpack(log.Data) @@ -65,7 +68,7 @@ func DecodeUniversalTxOutboundFromLog(log *evmtypes.Log) (*UniversalTxOutboundEv return nil, fmt.Errorf("failed to unpack UniversalTxOutbound: %w", err) } - if len(values) != 10 { + if len(values) != 11 { return nil, fmt.Errorf("unexpected number of unpacked values: %d", len(values)) } @@ -89,6 +92,74 @@ func DecodeUniversalTxOutboundFromLog(log *evmtypes.Log) (*UniversalTxOutboundEv event.RevertRecipient = values[i].(common.Address).Hex() i++ event.TxType = SolidityTxTypeToProto(values[i].(uint8)) + i++ + event.GasPrice = values[i].(*big.Int) + + return event, nil +} + +// RescueFundsOnSourceChainEvent holds decoded data from the RescueFundsOnSourceChain +// event emitted by UniversalGatewayPC when a user initiates a rescue on the source chain. +type RescueFundsOnSourceChainEvent struct { + UniversalTxId string // 0x-prefixed bytes32 — the original UTX whose funds are stuck + PRC20 string // 0x-prefixed address — PRC20 token whose counterpart is locked + ChainNamespace string // source chain namespace (e.g. "eip155") + Sender string // 0x-prefixed address — user who initiated the rescue + TxType TxType // always TxType_RESCUE_FUNDS + GasFee *big.Int // gas fee charged (in gas-token units) + GasPrice *big.Int // gas price on the source chain + GasLimit *big.Int // gas limit used for the rescue execution +} + +// DecodeRescueFundsOnSourceChainFromLog decodes a RescueFundsOnSourceChain event log. +// +// Event signature: +// +// RescueFundsOnSourceChain(bytes32 indexed universalTxId, address indexed prc20, +// string chainNamespace, address indexed sender, uint8 txType, +// uint256 gasFee, uint256 gasPrice, uint256 gasLimit) +// +// Topics: [sig, universalTxId, prc20, sender] +// Data: [chainNamespace, txType, gasFee, gasPrice, gasLimit] +func DecodeRescueFundsOnSourceChainFromLog(log *evmtypes.Log) (*RescueFundsOnSourceChainEvent, error) { + if len(log.Topics) < 4 { + return nil, fmt.Errorf("RescueFundsOnSourceChain: need 4 topics, got %d", len(log.Topics)) + } + if strings.ToLower(log.Topics[0]) != strings.ToLower(RescueFundsOnSourceChainEventSig) { + return nil, fmt.Errorf("not a RescueFundsOnSourceChain event") + } + + event := &RescueFundsOnSourceChainEvent{ + UniversalTxId: log.Topics[1], // bytes32 as 0x-prefixed hex + PRC20: common.HexToAddress(log.Topics[2]).Hex(), + Sender: common.HexToAddress(log.Topics[3]).Hex(), + } + + stringType, _ := abi.NewType("string", "", nil) + uint8Type, _ := abi.NewType("uint8", "", nil) + uint256Type, _ := abi.NewType("uint256", "", nil) + + arguments := abi.Arguments{ + {Type: stringType}, // chainNamespace + {Type: uint8Type}, // txType + {Type: uint256Type}, // gasFee + {Type: uint256Type}, // gasPrice + {Type: uint256Type}, // gasLimit + } + + values, err := arguments.Unpack(log.Data) + if err != nil { + return nil, fmt.Errorf("failed to unpack RescueFundsOnSourceChain data: %w", err) + } + if len(values) != 5 { + return nil, fmt.Errorf("RescueFundsOnSourceChain: unexpected value count %d", len(values)) + } + + event.ChainNamespace = values[0].(string) + event.TxType = SolidityTxTypeToProto(values[1].(uint8)) + event.GasFee = values[2].(*big.Int) + event.GasPrice = values[3].(*big.Int) + event.GasLimit = values[4].(*big.Int) return event, nil } diff --git a/x/uexecutor/types/keys.go b/x/uexecutor/types/keys.go index d2c7c880..9716aa38 100755 --- a/x/uexecutor/types/keys.go +++ b/x/uexecutor/types/keys.go @@ -30,6 +30,9 @@ var ( GasPricesKey = collections.NewPrefix(5) GasPricesName = "gas_prices" + + ChainMetaKey = collections.NewPrefix(6) + ChainMetasName = "chain_metas" ) const ( @@ -77,9 +80,21 @@ func GetOutboundBallotKey( return hex.EncodeToString(hash[:]), nil } -// Outbound Id for a inbound revert tx -func GetOutboundRevertId(inboundTxHash string) string { - data := fmt.Sprintf("%s:REVERT", inboundTxHash) +// GetOutboundRevertId generates a deterministic outbound ID for an inbound-revert +// outbound. sourceChain is the CAIP-2 identifier of the chain the inbound came from +// (e.g. "eip155:1"), mirroring the UTX key convention. +func GetOutboundRevertId(sourceChain string, inboundTxHash string) string { + data := fmt.Sprintf("%s:%s:REVERT", sourceChain, inboundTxHash) + hash := sha256.Sum256([]byte(data)) + return hex.EncodeToString(hash[:]) +} + +// GetRescueFundsOutboundId generates a deterministic outbound ID for a rescue-funds +// outbound. pushChainCaip is the CAIP-2 identifier of Push Chain (e.g. "eip155:2240"), +// mirroring the convention used by GetPcUniversalTxKey. This ID is also used as the +// subTxId on the source-chain gateway call, providing replay protection. +func GetRescueFundsOutboundId(pushChainCaip string, pcTxHash string, logIndex string) string { + data := fmt.Sprintf("%s:%s:%s:RESCUE", pushChainCaip, pcTxHash, logIndex) hash := sha256.Sum256([]byte(data)) return hex.EncodeToString(hash[:]) } diff --git a/x/uexecutor/types/msg_vote_chain_meta.go b/x/uexecutor/types/msg_vote_chain_meta.go new file mode 100644 index 00000000..f4052aa6 --- /dev/null +++ b/x/uexecutor/types/msg_vote_chain_meta.go @@ -0,0 +1,59 @@ +package types + +import ( + "cosmossdk.io/errors" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ sdk.Msg = &MsgVoteChainMeta{} +) + +// NewMsgVoteChainMeta creates new instance of MsgVoteChainMeta +func NewMsgVoteChainMeta( + sender sdk.Address, + observedChainId string, + price, chainHeight uint64, +) *MsgVoteChainMeta { + return &MsgVoteChainMeta{ + Signer: sender.String(), + ObservedChainId: observedChainId, + Price: price, + ChainHeight: chainHeight, + } +} + +// Route returns the name of the module +func (msg MsgVoteChainMeta) Route() string { return ModuleName } + +// Type returns the action +func (msg MsgVoteChainMeta) Type() string { return "msg_vote_chain_meta" } + +// GetSignBytes implements the LegacyMsg interface. +func (msg MsgVoteChainMeta) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// GetSigners returns the expected signers for a MsgVoteChainMeta message. +func (msg *MsgVoteChainMeta) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Signer) + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data. +func (msg *MsgVoteChainMeta) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Signer); err != nil { + return errors.Wrap(err, "invalid signer address") + } + if msg.ObservedChainId == "" { + return errors.Wrap(sdkerrors.ErrInvalidRequest, "observed_chain_id cannot be empty") + } + if msg.Price == 0 { + return errors.Wrap(sdkerrors.ErrInvalidRequest, "price must be greater than 0") + } + if msg.ChainHeight == 0 { + return errors.Wrap(sdkerrors.ErrInvalidRequest, "chain_height must be greater than 0") + } + return nil +} diff --git a/x/uexecutor/types/msg_vote_outbound.go b/x/uexecutor/types/msg_vote_outbound.go index 61f01170..8b1c8d9a 100644 --- a/x/uexecutor/types/msg_vote_outbound.go +++ b/x/uexecutor/types/msg_vote_outbound.go @@ -68,8 +68,15 @@ func (msg *MsgVoteOutbound) ValidateBasic() error { // Validate observed_tx content obs := msg.ObservedTx + // gas_fee_used is always required — the external chain consumes gas regardless + // of success or failure, and excess gas must be refundable in both cases. + if strings.TrimSpace(obs.GasFeeUsed) == "" { + return errors.Wrap(sdkerrors.ErrInvalidRequest, + "observed_tx.gas_fee_used is required") + } + if obs.Success { - // Success requires tx_hash AND block_height > 0 + // Success additionally requires tx_hash and block_height. if strings.TrimSpace(obs.TxHash) == "" { return errors.Wrap(sdkerrors.ErrInvalidRequest, "observed_tx.tx_hash required when success=true") @@ -78,10 +85,8 @@ func (msg *MsgVoteOutbound) ValidateBasic() error { return errors.Wrap(sdkerrors.ErrInvalidRequest, "observed_tx.block_height must be > 0 when success=true") } - } else { - // Failure case: - // tx_hash MAY be empty. + // Failure case: tx_hash MAY be empty. // BUT if tx_hash is present, block_height must be > 0. if strings.TrimSpace(obs.TxHash) != "" && obs.BlockHeight == 0 { return errors.Wrap(sdkerrors.ErrInvalidRequest, diff --git a/x/uexecutor/types/query.pb.go b/x/uexecutor/types/query.pb.go index 9d058555..d47a8f5c 100644 --- a/x/uexecutor/types/query.pb.go +++ b/x/uexecutor/types/query.pb.go @@ -215,6 +215,192 @@ func (m *QueryAllGasPricesResponse) GetPagination() *query.PageResponse { return nil } +// Single chain meta +type QueryChainMetaRequest struct { + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *QueryChainMetaRequest) Reset() { *m = QueryChainMetaRequest{} } +func (m *QueryChainMetaRequest) String() string { return proto.CompactTextString(m) } +func (*QueryChainMetaRequest) ProtoMessage() {} +func (*QueryChainMetaRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{4} +} +func (m *QueryChainMetaRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryChainMetaRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryChainMetaRequest.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 *QueryChainMetaRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryChainMetaRequest.Merge(m, src) +} +func (m *QueryChainMetaRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryChainMetaRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryChainMetaRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryChainMetaRequest proto.InternalMessageInfo + +func (m *QueryChainMetaRequest) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +type QueryChainMetaResponse struct { + ChainMeta *ChainMeta `protobuf:"bytes,1,opt,name=chain_meta,json=chainMeta,proto3" json:"chain_meta,omitempty"` +} + +func (m *QueryChainMetaResponse) Reset() { *m = QueryChainMetaResponse{} } +func (m *QueryChainMetaResponse) String() string { return proto.CompactTextString(m) } +func (*QueryChainMetaResponse) ProtoMessage() {} +func (*QueryChainMetaResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{5} +} +func (m *QueryChainMetaResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryChainMetaResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryChainMetaResponse.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 *QueryChainMetaResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryChainMetaResponse.Merge(m, src) +} +func (m *QueryChainMetaResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryChainMetaResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryChainMetaResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryChainMetaResponse proto.InternalMessageInfo + +func (m *QueryChainMetaResponse) GetChainMeta() *ChainMeta { + if m != nil { + return m.ChainMeta + } + return nil +} + +// All chain metas +type QueryAllChainMetasRequest struct { + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAllChainMetasRequest) Reset() { *m = QueryAllChainMetasRequest{} } +func (m *QueryAllChainMetasRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAllChainMetasRequest) ProtoMessage() {} +func (*QueryAllChainMetasRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{6} +} +func (m *QueryAllChainMetasRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAllChainMetasRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAllChainMetasRequest.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 *QueryAllChainMetasRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAllChainMetasRequest.Merge(m, src) +} +func (m *QueryAllChainMetasRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAllChainMetasRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAllChainMetasRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAllChainMetasRequest proto.InternalMessageInfo + +func (m *QueryAllChainMetasRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +type QueryAllChainMetasResponse struct { + ChainMetas []*ChainMeta `protobuf:"bytes,1,rep,name=chain_metas,json=chainMetas,proto3" json:"chain_metas,omitempty"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAllChainMetasResponse) Reset() { *m = QueryAllChainMetasResponse{} } +func (m *QueryAllChainMetasResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAllChainMetasResponse) ProtoMessage() {} +func (*QueryAllChainMetasResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{7} +} +func (m *QueryAllChainMetasResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAllChainMetasResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAllChainMetasResponse.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 *QueryAllChainMetasResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAllChainMetasResponse.Merge(m, src) +} +func (m *QueryAllChainMetasResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAllChainMetasResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAllChainMetasResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAllChainMetasResponse proto.InternalMessageInfo + +func (m *QueryAllChainMetasResponse) GetChainMetas() []*ChainMeta { + if m != nil { + return m.ChainMetas + } + return nil +} + +func (m *QueryAllChainMetasResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + // Existing types type QueryParamsRequest struct { } @@ -223,7 +409,7 @@ func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryParamsRequest) ProtoMessage() {} func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{4} + return fileDescriptor_94816af5d57d33a7, []int{8} } func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -262,7 +448,7 @@ func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryParamsResponse) ProtoMessage() {} func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{5} + return fileDescriptor_94816af5d57d33a7, []int{9} } func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -307,7 +493,7 @@ func (m *QueryAllPendingInboundsRequest) Reset() { *m = QueryAllPendingI func (m *QueryAllPendingInboundsRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllPendingInboundsRequest) ProtoMessage() {} func (*QueryAllPendingInboundsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{6} + return fileDescriptor_94816af5d57d33a7, []int{10} } func (m *QueryAllPendingInboundsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -352,7 +538,7 @@ func (m *QueryAllPendingInboundsResponse) Reset() { *m = QueryAllPending func (m *QueryAllPendingInboundsResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllPendingInboundsResponse) ProtoMessage() {} func (*QueryAllPendingInboundsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{7} + return fileDescriptor_94816af5d57d33a7, []int{11} } func (m *QueryAllPendingInboundsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -404,7 +590,7 @@ func (m *QueryGetUniversalTxRequest) Reset() { *m = QueryGetUniversalTxR func (m *QueryGetUniversalTxRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetUniversalTxRequest) ProtoMessage() {} func (*QueryGetUniversalTxRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{8} + return fileDescriptor_94816af5d57d33a7, []int{12} } func (m *QueryGetUniversalTxRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -448,7 +634,7 @@ func (m *QueryGetUniversalTxResponse) Reset() { *m = QueryGetUniversalTx func (m *QueryGetUniversalTxResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetUniversalTxResponse) ProtoMessage() {} func (*QueryGetUniversalTxResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{9} + return fileDescriptor_94816af5d57d33a7, []int{13} } func (m *QueryGetUniversalTxResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -492,7 +678,7 @@ func (m *QueryAllUniversalTxRequest) Reset() { *m = QueryAllUniversalTxR func (m *QueryAllUniversalTxRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllUniversalTxRequest) ProtoMessage() {} func (*QueryAllUniversalTxRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{10} + return fileDescriptor_94816af5d57d33a7, []int{14} } func (m *QueryAllUniversalTxRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -537,7 +723,7 @@ func (m *QueryAllUniversalTxResponse) Reset() { *m = QueryAllUniversalTx func (m *QueryAllUniversalTxResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllUniversalTxResponse) ProtoMessage() {} func (*QueryAllUniversalTxResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_94816af5d57d33a7, []int{11} + return fileDescriptor_94816af5d57d33a7, []int{15} } func (m *QueryAllUniversalTxResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -585,6 +771,10 @@ func init() { proto.RegisterType((*QueryGasPriceResponse)(nil), "uexecutor.v1.QueryGasPriceResponse") proto.RegisterType((*QueryAllGasPricesRequest)(nil), "uexecutor.v1.QueryAllGasPricesRequest") proto.RegisterType((*QueryAllGasPricesResponse)(nil), "uexecutor.v1.QueryAllGasPricesResponse") + proto.RegisterType((*QueryChainMetaRequest)(nil), "uexecutor.v1.QueryChainMetaRequest") + proto.RegisterType((*QueryChainMetaResponse)(nil), "uexecutor.v1.QueryChainMetaResponse") + proto.RegisterType((*QueryAllChainMetasRequest)(nil), "uexecutor.v1.QueryAllChainMetasRequest") + proto.RegisterType((*QueryAllChainMetasResponse)(nil), "uexecutor.v1.QueryAllChainMetasResponse") proto.RegisterType((*QueryParamsRequest)(nil), "uexecutor.v1.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "uexecutor.v1.QueryParamsResponse") proto.RegisterType((*QueryAllPendingInboundsRequest)(nil), "uexecutor.v1.QueryAllPendingInboundsRequest") @@ -598,53 +788,61 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/query.proto", fileDescriptor_94816af5d57d33a7) } var fileDescriptor_94816af5d57d33a7 = []byte{ - // 735 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x96, 0x41, 0x4f, 0x13, 0x4d, - 0x18, 0xc7, 0xd9, 0xbe, 0x79, 0xfb, 0xd2, 0x87, 0xbe, 0x1c, 0xc6, 0x4a, 0xca, 0x82, 0x4b, 0x5d, - 0x0c, 0x20, 0x81, 0xdd, 0x14, 0xa2, 0x47, 0x13, 0x30, 0x91, 0x90, 0x70, 0xa8, 0x8d, 0x5e, 0xbc, - 0x34, 0xd3, 0xee, 0x64, 0x3b, 0xb1, 0xec, 0x2e, 0x9d, 0xdd, 0xa6, 0x84, 0x10, 0xa3, 0x47, 0x3d, - 0x68, 0xe2, 0xc9, 0x78, 0xf7, 0x13, 0xf8, 0x21, 0x3c, 0x92, 0x78, 0xf1, 0x68, 0xc0, 0x0f, 0x62, - 0x98, 0x9d, 0x29, 0x3b, 0x65, 0x5a, 0x38, 0xf4, 0xb6, 0x7d, 0xe6, 0x3f, 0xcf, 0xf3, 0xfb, 0x3f, - 0x7d, 0x66, 0x67, 0xa1, 0x9c, 0x90, 0x3e, 0x69, 0x25, 0x71, 0xd8, 0x75, 0x7b, 0x55, 0xf7, 0x28, - 0x21, 0xdd, 0x63, 0x27, 0xea, 0x86, 0x71, 0x88, 0x8a, 0x83, 0x15, 0xa7, 0x57, 0x35, 0x17, 0xfd, - 0x30, 0xf4, 0x3b, 0xc4, 0xc5, 0x11, 0x75, 0x71, 0x10, 0x84, 0x31, 0x8e, 0x69, 0x18, 0xb0, 0x54, - 0x6b, 0xaa, 0x59, 0xe2, 0xe3, 0x88, 0xc8, 0x95, 0x45, 0x65, 0xc5, 0xc7, 0xac, 0x11, 0x75, 0x69, - 0x8b, 0x88, 0xd5, 0xf5, 0x56, 0xc8, 0x0e, 0x43, 0xe6, 0x36, 0x31, 0x23, 0x69, 0x71, 0xb7, 0x57, - 0x6d, 0x92, 0x18, 0x57, 0xdd, 0x08, 0xfb, 0x34, 0xe0, 0x45, 0x52, 0xad, 0x5d, 0x85, 0xd2, 0xf3, - 0x4b, 0xc5, 0x1e, 0x66, 0xb5, 0xcb, 0x14, 0x75, 0x72, 0x94, 0x10, 0x16, 0xa3, 0x79, 0x98, 0x6e, - 0xb5, 0x31, 0x0d, 0x1a, 0xd4, 0x2b, 0x1b, 0x15, 0x63, 0xad, 0x50, 0xff, 0x8f, 0xff, 0xde, 0xf7, - 0xec, 0x03, 0xb8, 0x3b, 0xb4, 0x85, 0x45, 0x61, 0xc0, 0x08, 0xda, 0x86, 0xc2, 0x00, 0x85, 0x6f, - 0x9a, 0xd9, 0x9a, 0x73, 0xb2, 0x7e, 0x9d, 0xc1, 0x96, 0x69, 0x5f, 0x3c, 0xd9, 0x4d, 0x28, 0xf3, - 0x6c, 0x3b, 0x9d, 0x8e, 0x5c, 0x65, 0x12, 0xe2, 0x19, 0xc0, 0x15, 0xb0, 0xc8, 0xb8, 0xe2, 0xa4, - 0xee, 0x9c, 0x4b, 0x77, 0x4e, 0xda, 0x5a, 0xe1, 0xce, 0xa9, 0x61, 0x5f, 0x1a, 0xa8, 0x67, 0x76, - 0xda, 0x5f, 0x0d, 0x98, 0xd7, 0x14, 0x11, 0xd8, 0x8f, 0x00, 0x06, 0xd8, 0xac, 0x6c, 0x54, 0xfe, - 0x19, 0xc3, 0x5d, 0x90, 0xdc, 0x0c, 0xed, 0x29, 0x70, 0x39, 0x0e, 0xb7, 0x7a, 0x23, 0x5c, 0x5a, - 0x53, 0xa1, 0x2b, 0x01, 0xe2, 0x70, 0x35, 0xdc, 0xc5, 0x87, 0xd2, 0xbb, 0xfd, 0x14, 0xee, 0x28, - 0x51, 0x01, 0xbb, 0x01, 0xf9, 0x88, 0x47, 0x44, 0x3b, 0x4a, 0x2a, 0xa8, 0x50, 0x0b, 0x8d, 0xdd, - 0x06, 0x4b, 0xfa, 0xae, 0x91, 0xc0, 0xa3, 0x81, 0xbf, 0x1f, 0x34, 0xc3, 0x24, 0xf0, 0x26, 0xde, - 0xe2, 0x0f, 0x06, 0x2c, 0x8d, 0x2c, 0x25, 0xd8, 0x97, 0x60, 0x86, 0xa6, 0xb1, 0x06, 0xf5, 0xd2, - 0x4e, 0x17, 0xea, 0x20, 0x42, 0xfb, 0xde, 0x04, 0x5b, 0xba, 0x01, 0x66, 0x3a, 0xa2, 0x24, 0x7e, - 0x19, 0xd0, 0x1e, 0xe9, 0x32, 0xdc, 0x79, 0xd1, 0x97, 0x9e, 0x67, 0x21, 0x37, 0x98, 0xea, 0x1c, - 0xf5, 0x6c, 0x0c, 0x0b, 0x5a, 0xb5, 0xc0, 0xde, 0x85, 0x62, 0x22, 0xc3, 0x8d, 0xb8, 0x2f, 0x9a, - 0xb4, 0xa4, 0x36, 0x3e, 0xb3, 0xf1, 0x80, 0xf8, 0xb8, 0x75, 0x5c, 0x9f, 0x49, 0xae, 0x42, 0xb6, - 0x27, 0x80, 0x76, 0x3a, 0x1d, 0x0d, 0xd0, 0xa4, 0xfe, 0x84, 0x6f, 0x86, 0x70, 0x32, 0x5c, 0x46, - 0x38, 0x79, 0x02, 0xff, 0x67, 0x9d, 0xc8, 0x61, 0x9f, 0x1f, 0x69, 0xa5, 0x5e, 0xcc, 0x98, 0x98, - 0xdc, 0xff, 0xb3, 0xf5, 0x3d, 0x0f, 0xff, 0x72, 0x50, 0xf4, 0x1a, 0xf2, 0xe9, 0xcc, 0xa2, 0x8a, - 0x4a, 0x71, 0xfd, 0x48, 0x98, 0xf7, 0xc7, 0x28, 0xd2, 0x22, 0xf6, 0xe2, 0xbb, 0x9f, 0x7f, 0x3e, - 0xe7, 0xe6, 0x50, 0xc9, 0x55, 0xde, 0x90, 0xe9, 0x71, 0x40, 0x5f, 0x0c, 0x40, 0xd7, 0xe7, 0x13, - 0x6d, 0x68, 0xf2, 0x8e, 0x3c, 0x31, 0xe6, 0xe6, 0x2d, 0xd5, 0x82, 0x68, 0x85, 0x13, 0x55, 0x90, - 0x35, 0x44, 0x94, 0xca, 0x1b, 0x54, 0x42, 0x7c, 0x34, 0x60, 0x56, 0x1d, 0x40, 0xb4, 0xa6, 0xa9, - 0xa4, 0x9d, 0x68, 0xf3, 0xe1, 0x2d, 0x94, 0x82, 0x67, 0x8d, 0xf3, 0xd8, 0xa8, 0xa2, 0xf2, 0x28, - 0x73, 0xe1, 0x9e, 0x50, 0xef, 0x14, 0xbd, 0x37, 0x60, 0x56, 0x1d, 0x24, 0x2d, 0x91, 0x76, 0xa4, - 0xb5, 0x44, 0xfa, 0xa9, 0xb4, 0x97, 0x39, 0xd1, 0x3d, 0xb4, 0x30, 0x86, 0x08, 0xbd, 0x81, 0x69, - 0xf9, 0x12, 0x46, 0xb6, 0xce, 0xad, 0x7a, 0x7f, 0x99, 0xcb, 0x63, 0x35, 0xa2, 0xf2, 0x3a, 0xaf, - 0xfc, 0x00, 0xd9, 0xae, 0xfe, 0x3e, 0x75, 0x4f, 0xe4, 0x1d, 0x78, 0x8a, 0xde, 0x1a, 0x50, 0xcc, - 0x5e, 0x1f, 0x68, 0x45, 0xef, 0x70, 0xf8, 0x12, 0x33, 0x57, 0x6f, 0xd4, 0x09, 0x9a, 0x0a, 0xa7, - 0x31, 0x51, 0x79, 0x04, 0x0d, 0xdb, 0xad, 0xfd, 0x38, 0xb7, 0x8c, 0xb3, 0x73, 0xcb, 0xf8, 0x7d, - 0x6e, 0x19, 0x9f, 0x2e, 0xac, 0xa9, 0xb3, 0x0b, 0x6b, 0xea, 0xd7, 0x85, 0x35, 0xf5, 0xea, 0xb1, - 0x4f, 0xe3, 0x76, 0xd2, 0x74, 0x5a, 0xe1, 0xa1, 0x1b, 0x25, 0xac, 0xcd, 0xb9, 0xf9, 0xd3, 0x26, - 0x7f, 0xdc, 0x0c, 0x42, 0x8f, 0xb8, 0xfd, 0x4c, 0x66, 0xfe, 0x39, 0xd1, 0xcc, 0xf3, 0xaf, 0x80, - 0xed, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x67, 0x0b, 0x8a, 0x2c, 0xb1, 0x08, 0x00, 0x00, + // 862 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x96, 0x41, 0x6f, 0xeb, 0x44, + 0x10, 0xc7, 0xbb, 0x41, 0x94, 0x64, 0x92, 0xd7, 0xc3, 0x12, 0x4a, 0xe2, 0xf6, 0xb9, 0x79, 0x6e, + 0x69, 0x43, 0x69, 0x6d, 0xa5, 0x15, 0x15, 0x27, 0x24, 0x5a, 0x89, 0xaa, 0x52, 0x91, 0x42, 0x04, + 0x17, 0x2e, 0xd1, 0xc6, 0x5e, 0x39, 0x16, 0x89, 0xed, 0x66, 0xed, 0x28, 0x55, 0x55, 0x21, 0x40, + 0x5c, 0xe0, 0x00, 0x12, 0x27, 0xc4, 0x81, 0x1b, 0x1f, 0x84, 0x13, 0xc7, 0x4a, 0x5c, 0x38, 0xa2, + 0x96, 0x0f, 0xf2, 0x94, 0xf5, 0xda, 0xf1, 0xa6, 0x76, 0xda, 0x43, 0x6e, 0xeb, 0x9d, 0x99, 0x9d, + 0xdf, 0x7f, 0x76, 0xac, 0x59, 0xa8, 0x85, 0x74, 0x42, 0xcd, 0x30, 0xf0, 0x46, 0xc6, 0xb8, 0x65, + 0x5c, 0x85, 0x74, 0x74, 0xad, 0xfb, 0x23, 0x2f, 0xf0, 0x70, 0x25, 0xb1, 0xe8, 0xe3, 0x96, 0xb2, + 0x69, 0x7b, 0x9e, 0x3d, 0xa0, 0x06, 0xf1, 0x1d, 0x83, 0xb8, 0xae, 0x17, 0x90, 0xc0, 0xf1, 0x5c, + 0x16, 0xf9, 0x2a, 0xf2, 0x29, 0xc1, 0xb5, 0x4f, 0x63, 0xcb, 0xa6, 0x64, 0xb1, 0x09, 0xeb, 0xfa, + 0x23, 0xc7, 0xa4, 0xc2, 0xfa, 0x52, 0xb2, 0x9a, 0x7d, 0xe2, 0xb8, 0xdd, 0x21, 0x0d, 0x88, 0x30, + 0xef, 0x9b, 0x1e, 0x1b, 0x7a, 0xcc, 0xe8, 0x11, 0x46, 0x23, 0x36, 0x63, 0xdc, 0xea, 0xd1, 0x80, + 0xb4, 0x0c, 0x9f, 0xd8, 0x8e, 0xcb, 0x19, 0x22, 0x5f, 0xad, 0x05, 0xd5, 0xcf, 0xa7, 0x1e, 0xe7, + 0x84, 0xb5, 0xa7, 0x19, 0x3a, 0xf4, 0x2a, 0xa4, 0x2c, 0xc0, 0x75, 0x28, 0x46, 0xe7, 0x3a, 0x56, + 0x0d, 0x35, 0x50, 0xb3, 0xd4, 0x79, 0x8b, 0x7f, 0x5f, 0x58, 0xda, 0x25, 0xbc, 0x33, 0x17, 0xc2, + 0x7c, 0xcf, 0x65, 0x14, 0x1f, 0x43, 0x29, 0x21, 0xe5, 0x41, 0xe5, 0xa3, 0x75, 0x3d, 0x5d, 0x0e, + 0x3d, 0x09, 0x29, 0xda, 0x62, 0xa5, 0xf5, 0xa0, 0xc6, 0x4f, 0xfb, 0x64, 0x30, 0x88, 0xad, 0x2c, + 0x86, 0xf8, 0x14, 0x60, 0x06, 0x2c, 0x4e, 0xdc, 0xd5, 0x23, 0x75, 0xfa, 0x54, 0x9d, 0x1e, 0x55, + 0x5e, 0xa8, 0xd3, 0xdb, 0xc4, 0x8e, 0x05, 0x74, 0x52, 0x91, 0xda, 0xef, 0x08, 0xea, 0x19, 0x49, + 0x04, 0xf6, 0x87, 0x00, 0x09, 0x36, 0xab, 0xa1, 0xc6, 0x1b, 0x0b, 0xb8, 0x4b, 0x31, 0x37, 0xc3, + 0xe7, 0x12, 0x5c, 0x81, 0xc3, 0xed, 0x3d, 0x09, 0x17, 0xe5, 0x94, 0xe8, 0x8e, 0x44, 0x3d, 0xcf, + 0xa6, 0xf5, 0xfd, 0x8c, 0x06, 0xe4, 0x19, 0x77, 0xd0, 0x86, 0xf5, 0xf9, 0x18, 0xa1, 0xe6, 0x04, + 0x60, 0xd6, 0x10, 0xa2, 0x66, 0xef, 0xca, 0x6a, 0x66, 0x41, 0x25, 0x33, 0x5e, 0x6a, 0xe6, 0xac, + 0x44, 0x89, 0x7d, 0xe9, 0x17, 0xf1, 0x07, 0x02, 0x25, 0x2b, 0x8b, 0x60, 0xff, 0x08, 0xca, 0x33, + 0xf6, 0xf8, 0x2a, 0x72, 0xe1, 0x21, 0x81, 0x5f, 0xe2, 0x65, 0x54, 0x01, 0x73, 0xc0, 0x36, 0x19, + 0x91, 0x61, 0xac, 0x5f, 0x3b, 0x83, 0xb7, 0xa5, 0x5d, 0xc1, 0x7b, 0x00, 0xab, 0x3e, 0xdf, 0x11, + 0x25, 0xa9, 0xca, 0xa8, 0xc2, 0x5b, 0xf8, 0x68, 0x7d, 0x50, 0x63, 0xed, 0x6d, 0xea, 0x5a, 0x8e, + 0x6b, 0x5f, 0xb8, 0x3d, 0x2f, 0x74, 0xad, 0xa5, 0x97, 0xf9, 0x27, 0x04, 0x5b, 0xb9, 0xa9, 0x04, + 0xfb, 0x16, 0x94, 0x9d, 0x68, 0xaf, 0xeb, 0x58, 0x51, 0xad, 0x4b, 0x1d, 0x10, 0x5b, 0x17, 0xd6, + 0x12, 0x4b, 0x7a, 0x20, 0xee, 0xfc, 0x9c, 0x06, 0x5f, 0xba, 0xce, 0x98, 0x8e, 0x18, 0x19, 0x7c, + 0x31, 0x89, 0x35, 0xaf, 0x41, 0x21, 0x69, 0xef, 0x82, 0x63, 0x69, 0x04, 0x36, 0x32, 0xbd, 0x05, + 0xf6, 0x29, 0x54, 0xc2, 0x78, 0xbb, 0x1b, 0x4c, 0x44, 0x91, 0xb6, 0xe4, 0xc2, 0xa7, 0x02, 0x2f, + 0xa9, 0x4d, 0xcc, 0xeb, 0x4e, 0x39, 0x9c, 0x6d, 0x69, 0xd6, 0xac, 0x09, 0x33, 0x80, 0x96, 0x75, + 0x09, 0x7f, 0x22, 0xa1, 0x64, 0x3e, 0x8d, 0x50, 0xf2, 0x31, 0xbc, 0x48, 0x2b, 0x89, 0xdb, 0xbd, + 0x9e, 0x2b, 0xa5, 0x53, 0x49, 0x89, 0x58, 0xde, 0xfd, 0x1c, 0xfd, 0x55, 0x84, 0x37, 0x39, 0x28, + 0xfe, 0x1a, 0x56, 0xa3, 0x9e, 0xc5, 0x0d, 0x99, 0xe2, 0xf1, 0x2f, 0xa1, 0xbc, 0x5a, 0xe0, 0x11, + 0x25, 0xd1, 0x36, 0xbf, 0xfb, 0xe7, 0xff, 0x5f, 0x0b, 0xeb, 0xb8, 0x6a, 0x48, 0xf3, 0x2a, 0xfa, + 0x1d, 0xf0, 0x6f, 0x08, 0xf0, 0xe3, 0xfe, 0xc4, 0x07, 0x19, 0xe7, 0xe6, 0xfe, 0x31, 0xca, 0xe1, + 0x33, 0xbd, 0x05, 0xd1, 0x2e, 0x27, 0x6a, 0x60, 0x75, 0x8e, 0x28, 0x72, 0xef, 0x3a, 0x31, 0xc4, + 0xcf, 0x08, 0xd6, 0xe4, 0x06, 0xc4, 0xcd, 0x8c, 0x4c, 0x99, 0x1d, 0xad, 0xbc, 0xff, 0x0c, 0x4f, + 0xc1, 0xd3, 0xe4, 0x3c, 0x1a, 0x6e, 0xc8, 0x3c, 0x52, 0x5f, 0x18, 0x37, 0x8e, 0x75, 0x8b, 0x7f, + 0x44, 0xb0, 0x26, 0x37, 0x52, 0x26, 0x51, 0x66, 0x4b, 0x67, 0x12, 0x65, 0x77, 0xa5, 0xb6, 0xcd, + 0x89, 0x5e, 0xe2, 0x8d, 0x05, 0x44, 0xf8, 0x1b, 0x28, 0xc6, 0x13, 0x11, 0x6b, 0x59, 0x6a, 0xe5, + 0xc7, 0x84, 0xb2, 0xbd, 0xd0, 0x47, 0x64, 0xde, 0xe7, 0x99, 0x77, 0xb0, 0x66, 0x64, 0xbf, 0x7d, + 0x8c, 0x9b, 0x78, 0x18, 0xde, 0xe2, 0x6f, 0x11, 0x54, 0xd2, 0xb3, 0x1c, 0xef, 0x66, 0x2b, 0x9c, + 0x7f, 0x51, 0x28, 0x7b, 0x4f, 0xfa, 0x09, 0x9a, 0x06, 0xa7, 0x51, 0x70, 0x2d, 0x87, 0x86, 0xe1, + 0xef, 0x11, 0x94, 0x92, 0x61, 0x84, 0xb3, 0x24, 0xce, 0x0f, 0x74, 0x65, 0x67, 0xb1, 0x93, 0x48, + 0xfd, 0x01, 0x4f, 0xfd, 0x1e, 0xde, 0x36, 0x72, 0x9e, 0x79, 0xe9, 0x4a, 0xfc, 0x80, 0xe0, 0x85, + 0x34, 0x4c, 0x71, 0x8e, 0xc4, 0x47, 0x43, 0x5d, 0x69, 0x3e, 0xed, 0x28, 0x88, 0x5e, 0x71, 0xa2, + 0x0d, 0x5c, 0xcf, 0x23, 0x62, 0xa7, 0xed, 0xbf, 0xef, 0x55, 0x74, 0x77, 0xaf, 0xa2, 0xff, 0xee, + 0x55, 0xf4, 0xcb, 0x83, 0xba, 0x72, 0xf7, 0xa0, 0xae, 0xfc, 0xfb, 0xa0, 0xae, 0x7c, 0x75, 0x62, + 0x3b, 0x41, 0x3f, 0xec, 0xe9, 0xa6, 0x37, 0x34, 0xfc, 0x90, 0xf5, 0x79, 0x14, 0x5f, 0x1d, 0xf2, + 0xe5, 0xa1, 0xeb, 0x59, 0xd4, 0x98, 0xa4, 0x8e, 0xe6, 0x0f, 0xe1, 0xde, 0x2a, 0x7f, 0xa0, 0x1e, + 0xbf, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x1e, 0x2c, 0x9d, 0xe7, 0x6b, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -671,6 +869,10 @@ type QueryClient interface { GasPrice(ctx context.Context, in *QueryGasPriceRequest, opts ...grpc.CallOption) (*QueryGasPriceResponse, error) // 🔹 Queries all gas prices across chains AllGasPrices(ctx context.Context, in *QueryAllGasPricesRequest, opts ...grpc.CallOption) (*QueryAllGasPricesResponse, error) + // 🔹 Queries chain meta for a specific chain + ChainMeta(ctx context.Context, in *QueryChainMetaRequest, opts ...grpc.CallOption) (*QueryChainMetaResponse, error) + // 🔹 Queries all chain metas across chains + AllChainMetas(ctx context.Context, in *QueryAllChainMetasRequest, opts ...grpc.CallOption) (*QueryAllChainMetasResponse, error) } type queryClient struct { @@ -735,6 +937,24 @@ func (c *queryClient) AllGasPrices(ctx context.Context, in *QueryAllGasPricesReq return out, nil } +func (c *queryClient) ChainMeta(ctx context.Context, in *QueryChainMetaRequest, opts ...grpc.CallOption) (*QueryChainMetaResponse, error) { + out := new(QueryChainMetaResponse) + err := c.cc.Invoke(ctx, "/uexecutor.v1.Query/ChainMeta", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AllChainMetas(ctx context.Context, in *QueryAllChainMetasRequest, opts ...grpc.CallOption) (*QueryAllChainMetasResponse, error) { + out := new(QueryAllChainMetasResponse) + err := c.cc.Invoke(ctx, "/uexecutor.v1.Query/AllChainMetas", 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. @@ -749,6 +969,10 @@ type QueryServer interface { GasPrice(context.Context, *QueryGasPriceRequest) (*QueryGasPriceResponse, error) // 🔹 Queries all gas prices across chains AllGasPrices(context.Context, *QueryAllGasPricesRequest) (*QueryAllGasPricesResponse, error) + // 🔹 Queries chain meta for a specific chain + ChainMeta(context.Context, *QueryChainMetaRequest) (*QueryChainMetaResponse, error) + // 🔹 Queries all chain metas across chains + AllChainMetas(context.Context, *QueryAllChainMetasRequest) (*QueryAllChainMetasResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -773,6 +997,12 @@ func (*UnimplementedQueryServer) GasPrice(ctx context.Context, req *QueryGasPric func (*UnimplementedQueryServer) AllGasPrices(ctx context.Context, req *QueryAllGasPricesRequest) (*QueryAllGasPricesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllGasPrices not implemented") } +func (*UnimplementedQueryServer) ChainMeta(ctx context.Context, req *QueryChainMetaRequest) (*QueryChainMetaResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ChainMeta not implemented") +} +func (*UnimplementedQueryServer) AllChainMetas(ctx context.Context, req *QueryAllChainMetasRequest) (*QueryAllChainMetasResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AllChainMetas not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -886,6 +1116,42 @@ func _Query_AllGasPrices_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Query_ChainMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryChainMetaRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ChainMeta(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/uexecutor.v1.Query/ChainMeta", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ChainMeta(ctx, req.(*QueryChainMetaRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AllChainMetas_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAllChainMetasRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AllChainMetas(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/uexecutor.v1.Query/AllChainMetas", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AllChainMetas(ctx, req.(*QueryAllChainMetasRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "uexecutor.v1.Query", HandlerType: (*QueryServer)(nil), @@ -914,6 +1180,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "AllGasPrices", Handler: _Query_AllGasPrices_Handler, }, + { + MethodName: "ChainMeta", + Handler: _Query_ChainMeta_Handler, + }, + { + MethodName: "AllChainMetas", + Handler: _Query_AllChainMetas_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/query.proto", @@ -1068,7 +1342,7 @@ func (m *QueryAllGasPricesResponse) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } -func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryChainMetaRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1078,20 +1352,27 @@ func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryChainMetaRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryChainMetaRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } -func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryChainMetaResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1101,19 +1382,19 @@ func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryChainMetaResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryChainMetaResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.Params != nil { + if m.ChainMeta != nil { { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ChainMeta.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -1126,7 +1407,7 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *QueryAllPendingInboundsRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryAllChainMetasRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1136,12 +1417,12 @@ func (m *QueryAllPendingInboundsRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryAllPendingInboundsRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryAllChainMetasRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryAllPendingInboundsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryAllChainMetasRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1161,7 +1442,7 @@ func (m *QueryAllPendingInboundsRequest) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } -func (m *QueryAllPendingInboundsResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryAllChainMetasResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1171,12 +1452,12 @@ func (m *QueryAllPendingInboundsResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryAllPendingInboundsResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryAllChainMetasResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryAllPendingInboundsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryAllChainMetasResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1193,11 +1474,16 @@ func (m *QueryAllPendingInboundsResponse) MarshalToSizedBuffer(dAtA []byte) (int i-- dAtA[i] = 0x12 } - if len(m.InboundIds) > 0 { - for iNdEx := len(m.InboundIds) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.InboundIds[iNdEx]) - copy(dAtA[i:], m.InboundIds[iNdEx]) - i = encodeVarintQuery(dAtA, i, uint64(len(m.InboundIds[iNdEx]))) + if len(m.ChainMetas) > 0 { + for iNdEx := len(m.ChainMetas) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ChainMetas[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } i-- dAtA[i] = 0xa } @@ -1205,7 +1491,7 @@ func (m *QueryAllPendingInboundsResponse) MarshalToSizedBuffer(dAtA []byte) (int return len(dAtA) - i, nil } -func (m *QueryGetUniversalTxRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1215,27 +1501,20 @@ func (m *QueryGetUniversalTxRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryGetUniversalTxRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryGetUniversalTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.Id) > 0 { - i -= len(m.Id) - copy(dAtA[i:], m.Id) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Id))) - i-- - dAtA[i] = 0xa - } return len(dAtA) - i, nil } -func (m *QueryGetUniversalTxResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1245,19 +1524,19 @@ func (m *QueryGetUniversalTxResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryGetUniversalTxResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryGetUniversalTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.UniversalTx != nil { + if m.Params != nil { { - size, err := m.UniversalTx.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -1270,7 +1549,7 @@ func (m *QueryGetUniversalTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } -func (m *QueryAllUniversalTxRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryAllPendingInboundsRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1280,12 +1559,12 @@ func (m *QueryAllUniversalTxRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryAllUniversalTxRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryAllPendingInboundsRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryAllUniversalTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryAllPendingInboundsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1305,7 +1584,7 @@ func (m *QueryAllUniversalTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } -func (m *QueryAllUniversalTxResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryAllPendingInboundsResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1315,12 +1594,12 @@ func (m *QueryAllUniversalTxResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryAllUniversalTxResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryAllPendingInboundsResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryAllUniversalTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryAllPendingInboundsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1337,19 +1616,163 @@ func (m *QueryAllUniversalTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, er i-- dAtA[i] = 0x12 } - if len(m.UniversalTxs) > 0 { - for iNdEx := len(m.UniversalTxs) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.UniversalTxs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } + if len(m.InboundIds) > 0 { + for iNdEx := len(m.InboundIds) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.InboundIds[iNdEx]) + copy(dAtA[i:], m.InboundIds[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.InboundIds[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryGetUniversalTxRequest) 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 *QueryGetUniversalTxRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGetUniversalTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryGetUniversalTxResponse) 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 *QueryGetUniversalTxResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGetUniversalTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.UniversalTx != nil { + { + size, err := m.UniversalTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAllUniversalTxRequest) 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 *QueryAllUniversalTxRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAllUniversalTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAllUniversalTxResponse) 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 *QueryAllUniversalTxResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAllUniversalTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.UniversalTxs) > 0 { + for iNdEx := len(m.UniversalTxs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.UniversalTxs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } } return len(dAtA) - i, nil } @@ -1423,6 +1846,64 @@ func (m *QueryAllGasPricesResponse) Size() (n int) { return n } +func (m *QueryChainMetaRequest) 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 *QueryChainMetaResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ChainMeta != nil { + l = m.ChainMeta.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllChainMetasRequest) 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 *QueryAllChainMetasResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ChainMetas) > 0 { + for _, e := range m.ChainMetas { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func (m *QueryParamsRequest) Size() (n int) { if m == nil { return 0 @@ -1915,6 +2396,380 @@ func (m *QueryAllGasPricesResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryChainMetaRequest) 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: QueryChainMetaRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryChainMetaRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", 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.ChainId = string(dAtA[iNdEx:postIndex]) + 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 *QueryChainMetaResponse) 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: QueryChainMetaResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryChainMetaResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainMeta", 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.ChainMeta == nil { + m.ChainMeta = &ChainMeta{} + } + if err := m.ChainMeta.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 *QueryAllChainMetasRequest) 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: QueryAllChainMetasRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllChainMetasRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.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 *QueryAllChainMetasResponse) 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: QueryAllChainMetasResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllChainMetasResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainMetas", 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 + } + m.ChainMetas = append(m.ChainMetas, &ChainMeta{}) + if err := m.ChainMetas[len(m.ChainMetas)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.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 *QueryParamsRequest) Unmarshal(dAtA []byte) 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 cb34f647..1317b283 100644 --- a/x/uexecutor/types/query.pb.gw.go +++ b/x/uexecutor/types/query.pb.gw.go @@ -267,6 +267,96 @@ func local_request_Query_AllGasPrices_0(ctx context.Context, marshaler runtime.M } +func request_Query_ChainMeta_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryChainMetaRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["chain_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id") + } + + protoReq.ChainId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) + } + + msg, err := client.ChainMeta(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ChainMeta_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryChainMetaRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["chain_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id") + } + + protoReq.ChainId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) + } + + msg, err := server.ChainMeta(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_AllChainMetas_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_AllChainMetas_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllChainMetasRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_AllChainMetas_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.AllChainMetas(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AllChainMetas_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllChainMetasRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_AllChainMetas_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.AllChainMetas(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. @@ -411,6 +501,52 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_ChainMeta_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_ChainMeta_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_ChainMeta_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AllChainMetas_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_AllChainMetas_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_AllChainMetas_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -572,6 +708,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_ChainMeta_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_ChainMeta_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_ChainMeta_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AllChainMetas_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_AllChainMetas_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_AllChainMetas_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -587,6 +763,10 @@ var ( pattern_Query_GasPrice_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"uexecutor", "v1", "gas_price", "chain_id"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_AllGasPrices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "gas_prices"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_ChainMeta_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"uexecutor", "v1", "chain_meta", "chain_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AllChainMetas_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "chain_metas"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -601,4 +781,8 @@ var ( forward_Query_GasPrice_0 = runtime.ForwardResponseMessage forward_Query_AllGasPrices_0 = runtime.ForwardResponseMessage + + forward_Query_ChainMeta_0 = runtime.ForwardResponseMessage + + forward_Query_AllChainMetas_0 = runtime.ForwardResponseMessage ) diff --git a/x/uexecutor/types/tx.pb.go b/x/uexecutor/types/tx.pb.go index 348a8d59..58a2a46d 100644 --- a/x/uexecutor/types/tx.pb.go +++ b/x/uexecutor/types/tx.pb.go @@ -654,6 +654,112 @@ func (m *MsgVoteGasPriceResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgVoteGasPriceResponse proto.InternalMessageInfo +// MsgVoteChainMeta is broadcasted by Universal Validators to submit observed chain metadata (gas price + block height) +type MsgVoteChainMeta struct { + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + ObservedChainId string `protobuf:"bytes,2,opt,name=observed_chain_id,json=observedChainId,proto3" json:"observed_chain_id,omitempty"` + Price uint64 `protobuf:"varint,3,opt,name=price,proto3" json:"price,omitempty"` + ChainHeight uint64 `protobuf:"varint,4,opt,name=chain_height,json=chainHeight,proto3" json:"chain_height,omitempty"` +} + +func (m *MsgVoteChainMeta) Reset() { *m = MsgVoteChainMeta{} } +func (m *MsgVoteChainMeta) String() string { return proto.CompactTextString(m) } +func (*MsgVoteChainMeta) ProtoMessage() {} +func (*MsgVoteChainMeta) Descriptor() ([]byte, []int) { + return fileDescriptor_88d6216044506365, []int{12} +} +func (m *MsgVoteChainMeta) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteChainMeta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteChainMeta.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 *MsgVoteChainMeta) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteChainMeta.Merge(m, src) +} +func (m *MsgVoteChainMeta) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteChainMeta) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteChainMeta.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteChainMeta proto.InternalMessageInfo + +func (m *MsgVoteChainMeta) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +func (m *MsgVoteChainMeta) GetObservedChainId() string { + if m != nil { + return m.ObservedChainId + } + return "" +} + +func (m *MsgVoteChainMeta) GetPrice() uint64 { + if m != nil { + return m.Price + } + return 0 +} + +func (m *MsgVoteChainMeta) GetChainHeight() uint64 { + if m != nil { + return m.ChainHeight + } + return 0 +} + +// MsgVoteChainMetaResponse defines the response for MsgVoteChainMeta +type MsgVoteChainMetaResponse struct { +} + +func (m *MsgVoteChainMetaResponse) Reset() { *m = MsgVoteChainMetaResponse{} } +func (m *MsgVoteChainMetaResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVoteChainMetaResponse) ProtoMessage() {} +func (*MsgVoteChainMetaResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_88d6216044506365, []int{13} +} +func (m *MsgVoteChainMetaResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteChainMetaResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteChainMetaResponse.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 *MsgVoteChainMetaResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteChainMetaResponse.Merge(m, src) +} +func (m *MsgVoteChainMetaResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteChainMetaResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteChainMetaResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteChainMetaResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgUpdateParams)(nil), "uexecutor.v1.MsgUpdateParams") proto.RegisterType((*MsgUpdateParamsResponse)(nil), "uexecutor.v1.MsgUpdateParamsResponse") @@ -667,65 +773,71 @@ func init() { proto.RegisterType((*MsgVoteOutboundResponse)(nil), "uexecutor.v1.MsgVoteOutboundResponse") proto.RegisterType((*MsgVoteGasPrice)(nil), "uexecutor.v1.MsgVoteGasPrice") proto.RegisterType((*MsgVoteGasPriceResponse)(nil), "uexecutor.v1.MsgVoteGasPriceResponse") + proto.RegisterType((*MsgVoteChainMeta)(nil), "uexecutor.v1.MsgVoteChainMeta") + proto.RegisterType((*MsgVoteChainMetaResponse)(nil), "uexecutor.v1.MsgVoteChainMetaResponse") } func init() { proto.RegisterFile("uexecutor/v1/tx.proto", fileDescriptor_88d6216044506365) } var fileDescriptor_88d6216044506365 = []byte{ - // 840 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0x4f, 0x4f, 0x33, 0x45, - 0x1c, 0xee, 0x42, 0x5b, 0xd3, 0x69, 0x7d, 0xdf, 0xb7, 0x6b, 0x6b, 0xff, 0x00, 0x05, 0xaa, 0x06, - 0x2c, 0xd2, 0x95, 0x9a, 0x70, 0xe8, 0x8d, 0x2a, 0x31, 0x8d, 0x29, 0xd4, 0x15, 0x3c, 0x70, 0x69, - 0xa6, 0xbb, 0xe3, 0x76, 0x23, 0xbb, 0xb3, 0xd9, 0x99, 0x69, 0xca, 0xcd, 0x78, 0x34, 0x31, 0xf1, - 0xe4, 0x77, 0x30, 0x5e, 0x38, 0xf8, 0x01, 0x3c, 0x72, 0x24, 0x7a, 0xf1, 0x44, 0x0c, 0x1c, 0xf8, - 0x1a, 0x66, 0x67, 0xff, 0x6f, 0x4b, 0x31, 0x9c, 0xde, 0x0b, 0x99, 0x7d, 0x9e, 0xdf, 0xef, 0xe1, - 0xf7, 0x3c, 0x3b, 0x33, 0x5d, 0x50, 0x66, 0x68, 0x86, 0x14, 0x46, 0xb1, 0x2d, 0x4d, 0x0f, 0x24, - 0x3a, 0x6b, 0x5b, 0x36, 0xa6, 0x58, 0x2c, 0x04, 0x70, 0x7b, 0x7a, 0x50, 0x2f, 0x42, 0x43, 0x37, - 0xb1, 0xc4, 0xff, 0xba, 0x05, 0xf5, 0x8a, 0x82, 0x89, 0x81, 0x89, 0x64, 0x10, 0xcd, 0x69, 0x34, - 0x88, 0xe6, 0x11, 0xd5, 0xb8, 0xe0, 0x95, 0x85, 0x88, 0xc7, 0x94, 0x34, 0xac, 0x61, 0xbe, 0x94, - 0x9c, 0x95, 0x87, 0xd6, 0x5c, 0xa1, 0x91, 0x4b, 0xb8, 0x0f, 0x2e, 0xd5, 0xfc, 0x5d, 0x00, 0xaf, - 0x07, 0x44, 0x3b, 0xb7, 0x54, 0x48, 0xd1, 0x10, 0xda, 0xd0, 0x20, 0xe2, 0x21, 0xc8, 0x41, 0x46, - 0x27, 0xd8, 0xd6, 0xe9, 0x55, 0x55, 0xd8, 0x12, 0x76, 0x73, 0xbd, 0xea, 0x5f, 0x7f, 0xec, 0x97, - 0xbc, 0xc6, 0x23, 0x55, 0xb5, 0x11, 0x21, 0xdf, 0x50, 0x5b, 0x37, 0x35, 0x39, 0x2c, 0x15, 0x3b, - 0x20, 0x6b, 0x71, 0x85, 0xea, 0xca, 0x96, 0xb0, 0x9b, 0xef, 0x94, 0xda, 0x51, 0x87, 0x6d, 0x57, - 0xbd, 0x97, 0xbe, 0xb9, 0xdb, 0x4c, 0xc9, 0x5e, 0x65, 0xf7, 0x93, 0x1f, 0x1f, 0xaf, 0x5b, 0xa1, - 0xc6, 0x4f, 0x8f, 0xd7, 0xad, 0x5a, 0xe8, 0x2e, 0x31, 0x59, 0xb3, 0x06, 0x2a, 0x09, 0x48, 0x46, - 0xc4, 0xc2, 0x26, 0x41, 0xcd, 0x3f, 0x57, 0x40, 0x71, 0x40, 0xb4, 0x63, 0xde, 0x8a, 0x86, 0xf0, - 0xea, 0x12, 0x43, 0x55, 0xfc, 0x14, 0x64, 0x89, 0xae, 0x99, 0xc8, 0x7e, 0xd6, 0x87, 0x57, 0x27, - 0xca, 0xa0, 0xc4, 0x4c, 0x7d, 0x8a, 0x6c, 0x02, 0x2f, 0x47, 0x50, 0x51, 0x30, 0x33, 0xe9, 0x48, - 0x57, 0x3d, 0x4b, 0x5b, 0x71, 0x4b, 0xe7, 0x7e, 0xe5, 0x91, 0x5b, 0xd8, 0x57, 0x65, 0x91, 0xcd, - 0x61, 0xe2, 0x57, 0xa0, 0x18, 0x6a, 0x5a, 0xee, 0x68, 0xd5, 0x55, 0x2e, 0xd8, 0x78, 0x42, 0xd0, - 0x33, 0x20, 0xbf, 0x61, 0x09, 0x44, 0xdc, 0x03, 0xc5, 0x29, 0xb2, 0xf5, 0xef, 0x74, 0x05, 0x52, - 0x1d, 0x9b, 0x23, 0x15, 0x52, 0x58, 0x4d, 0x3b, 0xee, 0xe4, 0x37, 0x51, 0xe2, 0x0b, 0x48, 0x61, - 0x77, 0xcf, 0x89, 0xd7, 0xb3, 0xe6, 0x64, 0xbb, 0x16, 0xcb, 0x36, 0x1e, 0x56, 0x73, 0x0d, 0xd4, - 0xe6, 0xc0, 0x20, 0xdf, 0xdf, 0x56, 0xc0, 0xbb, 0x03, 0xa2, 0x0d, 0x74, 0xcd, 0x86, 0x14, 0x9d, - 0x1f, 0x1f, 0xbd, 0x3d, 0xd9, 0x1a, 0x7c, 0x26, 0x27, 0x8b, 0xa5, 0xd9, 0x0e, 0xfc, 0xb2, 0x20, - 0x5b, 0x23, 0x81, 0x88, 0xeb, 0x20, 0xe7, 0x8c, 0x0a, 0x29, 0xb3, 0x91, 0x97, 0x69, 0x08, 0x74, - 0x77, 0x12, 0x61, 0x56, 0x62, 0x61, 0x86, 0xc9, 0x34, 0x2b, 0xa0, 0x1c, 0x03, 0x82, 0x10, 0x7f, - 0x15, 0xc0, 0xab, 0x01, 0xd1, 0xbe, 0xc5, 0x14, 0xf5, 0xcd, 0x31, 0x66, 0xe6, 0x4b, 0x76, 0xa8, - 0x04, 0xde, 0xd1, 0xdd, 0x66, 0x2f, 0xb8, 0x72, 0xdc, 0xa7, 0xa7, 0x2c, 0xfb, 0x55, 0xdd, 0xed, - 0xc4, 0xdc, 0x45, 0x86, 0xa4, 0xf8, 0x14, 0xcd, 0x2a, 0x78, 0x3f, 0x8e, 0x04, 0x23, 0xdf, 0xb9, - 0x17, 0x84, 0x43, 0x9d, 0x32, 0xfa, 0xd2, 0x99, 0xdf, 0x03, 0x19, 0x3a, 0xf3, 0x5f, 0x75, 0x4e, - 0x4e, 0xd3, 0x59, 0x5f, 0x15, 0xcb, 0x20, 0xcb, 0x5c, 0x74, 0x95, 0xa3, 0x19, 0xc6, 0xe1, 0x1e, - 0xc8, 0xe3, 0x31, 0x41, 0xf6, 0x14, 0xa9, 0x23, 0x3a, 0xe3, 0xaf, 0x21, 0xdf, 0xd9, 0x8e, 0x7b, - 0xf4, 0x47, 0x39, 0xe5, 0x85, 0xfc, 0x1d, 0xca, 0xc0, 0xef, 0x3a, 0x9b, 0x75, 0x3f, 0x4e, 0x58, - 0x8e, 0xdf, 0x29, 0x51, 0x33, 0xde, 0x9d, 0x12, 0x85, 0x02, 0xef, 0x7f, 0x87, 0xde, 0xbf, 0x84, - 0x64, 0x68, 0xeb, 0x0a, 0x7a, 0x81, 0xf7, 0x16, 0x28, 0x06, 0x7e, 0x94, 0x09, 0xd4, 0xcd, 0x30, - 0x87, 0xd7, 0x3e, 0xf1, 0xb9, 0x83, 0xf7, 0x55, 0xb1, 0x04, 0x32, 0x96, 0xf3, 0x6f, 0x78, 0x22, - 0x69, 0xd9, 0x7d, 0x10, 0xb7, 0x41, 0x61, 0x7c, 0x89, 0x95, 0xef, 0x47, 0x26, 0x33, 0xc6, 0xc8, - 0xe6, 0x91, 0xa4, 0xe5, 0x3c, 0xc7, 0x4e, 0x38, 0xf4, 0x3f, 0x0c, 0xfb, 0x0e, 0x22, 0x86, 0x7d, - 0xc8, 0x37, 0xdc, 0xf9, 0x39, 0x0d, 0x56, 0x07, 0x44, 0x13, 0xcf, 0x40, 0x21, 0xf6, 0x8b, 0xb0, - 0x91, 0x38, 0x49, 0xf1, 0x3b, 0xb8, 0xfe, 0xd1, 0x52, 0xda, 0x57, 0x17, 0x2f, 0xc0, 0xab, 0xc4, - 0xf5, 0xbc, 0x39, 0xd7, 0x18, 0x2f, 0xa8, 0xef, 0x3c, 0x53, 0x10, 0x68, 0x9f, 0x00, 0x10, 0xb9, - 0x9a, 0xd6, 0xe6, 0xda, 0x42, 0xb2, 0xfe, 0xc1, 0x12, 0x32, 0xd0, 0xfb, 0x1a, 0xe4, 0xa3, 0xa7, - 0x74, 0x7d, 0xae, 0x27, 0xc2, 0xd6, 0x3f, 0x5c, 0xc6, 0x06, 0x92, 0x67, 0xa0, 0x10, 0x3b, 0x45, - 0x1b, 0x0b, 0xbb, 0x7c, 0x7a, 0x41, 0xa8, 0x8b, 0xf6, 0xa8, 0xaf, 0x1a, 0xec, 0xcf, 0xc5, 0xaa, - 0x3e, 0xfd, 0x84, 0x6a, 0x72, 0x23, 0xd4, 0x33, 0x3f, 0x3c, 0x5e, 0xb7, 0x84, 0xde, 0xf0, 0xe6, - 0xbe, 0x21, 0xdc, 0xde, 0x37, 0x84, 0x7f, 0xef, 0x1b, 0xc2, 0x2f, 0x0f, 0x8d, 0xd4, 0xed, 0x43, - 0x23, 0xf5, 0xcf, 0x43, 0x23, 0x75, 0x71, 0xa8, 0xe9, 0x74, 0xc2, 0xc6, 0x6d, 0x05, 0x1b, 0x92, - 0xc5, 0xc8, 0x84, 0x6f, 0x6c, 0xbe, 0xda, 0xe7, 0xcb, 0x7d, 0x13, 0xab, 0x48, 0x9a, 0x49, 0xe1, - 0x36, 0xe4, 0x9f, 0x29, 0xe3, 0x2c, 0xff, 0xec, 0xf8, 0xec, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x77, 0x92, 0x41, 0x7c, 0x14, 0x09, 0x00, 0x00, + // 912 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0xae, 0xdb, 0xb4, 0xa8, 0x2f, 0xdd, 0xdd, 0xc6, 0xa4, 0x34, 0x75, 0xb7, 0xd9, 0x36, 0xfc, + 0xd8, 0x25, 0x4b, 0x63, 0xb6, 0x48, 0x7b, 0xc8, 0xad, 0x85, 0x15, 0x54, 0x28, 0xbb, 0xc5, 0xb4, + 0x20, 0xed, 0x25, 0x9a, 0xd8, 0x83, 0x63, 0x51, 0x7b, 0x2c, 0xcf, 0x4c, 0x94, 0xde, 0x10, 0x47, + 0x4e, 0x9c, 0xf8, 0x1f, 0x10, 0x97, 0x1e, 0xf8, 0x03, 0x38, 0xee, 0x71, 0x05, 0x42, 0xe2, 0xb4, + 0x42, 0xad, 0x44, 0xff, 0x0d, 0xe4, 0xb1, 0xc7, 0xf6, 0x38, 0xd9, 0x2c, 0xea, 0x85, 0xbd, 0x44, + 0xce, 0xf7, 0xbd, 0xf7, 0xe5, 0x7d, 0x9f, 0x27, 0xcf, 0x86, 0x35, 0x8e, 0xc7, 0xd8, 0xe6, 0x8c, + 0x44, 0xe6, 0xe8, 0x81, 0xc9, 0xc6, 0x9d, 0x30, 0x22, 0x8c, 0xe8, 0x2b, 0x19, 0xdc, 0x19, 0x3d, + 0x30, 0x6a, 0xc8, 0xf7, 0x02, 0x62, 0x8a, 0xcf, 0xa4, 0xc0, 0x58, 0xb7, 0x09, 0xf5, 0x09, 0x35, + 0x7d, 0xea, 0xc6, 0x8d, 0x3e, 0x75, 0x53, 0xa2, 0xa1, 0x0a, 0x9e, 0x85, 0x98, 0xa6, 0xcc, 0x96, + 0xc2, 0xd8, 0x43, 0xe4, 0x05, 0x7d, 0x1f, 0x33, 0x94, 0xd2, 0x75, 0x97, 0xb8, 0x44, 0x5c, 0x9a, + 0xf1, 0x55, 0x8a, 0x6e, 0x24, 0xbf, 0xd3, 0x4f, 0x88, 0xe4, 0x4b, 0x42, 0xb5, 0x7e, 0xd1, 0xe0, + 0x56, 0x8f, 0xba, 0x27, 0xa1, 0x83, 0x18, 0x3e, 0x42, 0x11, 0xf2, 0xa9, 0xfe, 0x10, 0x96, 0x11, + 0x67, 0x43, 0x12, 0x79, 0xec, 0xac, 0xa1, 0x6d, 0x6b, 0xf7, 0x96, 0x0f, 0x1a, 0xbf, 0xff, 0xba, + 0x5b, 0x4f, 0x1b, 0xf7, 0x1d, 0x27, 0xc2, 0x94, 0x7e, 0xc9, 0x22, 0x2f, 0x70, 0xad, 0xbc, 0x54, + 0xdf, 0x83, 0xa5, 0x50, 0x28, 0x34, 0xe6, 0xb7, 0xb5, 0x7b, 0xd5, 0xbd, 0x7a, 0xa7, 0x18, 0x40, + 0x27, 0x51, 0x3f, 0xa8, 0x3c, 0x7b, 0x71, 0x67, 0xce, 0x4a, 0x2b, 0xbb, 0x1f, 0x7c, 0x7f, 0x75, + 0xde, 0xce, 0x35, 0x7e, 0xb8, 0x3a, 0x6f, 0x6f, 0xe4, 0x16, 0x4b, 0x93, 0xb5, 0x36, 0x60, 0xbd, + 0x04, 0x59, 0x98, 0x86, 0x24, 0xa0, 0xb8, 0xf5, 0xdb, 0x3c, 0xd4, 0x7a, 0xd4, 0x7d, 0x24, 0x5a, + 0xf1, 0x11, 0x3a, 0x3b, 0x25, 0xc8, 0xd1, 0x3f, 0x84, 0x25, 0xea, 0xb9, 0x01, 0x8e, 0x5e, 0xe9, + 0x23, 0xad, 0xd3, 0x2d, 0xa8, 0xf3, 0xc0, 0x1b, 0xe1, 0x88, 0xa2, 0xd3, 0x3e, 0xb2, 0x6d, 0xc2, + 0x03, 0xd6, 0xf7, 0x9c, 0xd4, 0xd2, 0xb6, 0x6a, 0xe9, 0x44, 0x56, 0xee, 0x27, 0x85, 0x87, 0x8e, + 0xa5, 0xf3, 0x09, 0x4c, 0xff, 0x1c, 0x6a, 0xb9, 0x66, 0x98, 0x8c, 0xd6, 0x58, 0x10, 0x82, 0xcd, + 0x97, 0x08, 0xa6, 0x06, 0xac, 0x55, 0x5e, 0x42, 0xf4, 0xfb, 0x50, 0x1b, 0xe1, 0xc8, 0xfb, 0xc6, + 0xb3, 0x11, 0xf3, 0x48, 0xd0, 0x77, 0x10, 0x43, 0x8d, 0x4a, 0xec, 0xce, 0x5a, 0x2d, 0x12, 0x9f, + 0x20, 0x86, 0xba, 0xf7, 0xe3, 0x78, 0x53, 0x6b, 0x71, 0xb6, 0x9b, 0x4a, 0xb6, 0x6a, 0x58, 0xad, + 0x4d, 0xd8, 0x98, 0x00, 0xb3, 0x7c, 0x7f, 0x9e, 0x87, 0x1b, 0x3d, 0xea, 0xf6, 0x3c, 0x37, 0x42, + 0x0c, 0x9f, 0x3c, 0xda, 0x7f, 0x7d, 0xb2, 0xf5, 0xc5, 0x4c, 0x71, 0x16, 0x33, 0xb3, 0xed, 0xc9, + 0xb2, 0x2c, 0x5b, 0xbf, 0x84, 0xe8, 0xb7, 0x61, 0x39, 0x1e, 0x15, 0x31, 0x1e, 0xe1, 0x34, 0xd3, + 0x1c, 0xe8, 0xde, 0x2d, 0x85, 0xb9, 0xae, 0x84, 0x99, 0x27, 0xd3, 0x5a, 0x87, 0x35, 0x05, 0xc8, + 0x42, 0xfc, 0x49, 0x83, 0x9b, 0x3d, 0xea, 0x7e, 0x45, 0x18, 0x3e, 0x0c, 0x06, 0x84, 0x07, 0xd7, + 0x39, 0xa1, 0x26, 0xbc, 0xe1, 0x25, 0xcd, 0x69, 0x70, 0x6b, 0xaa, 0xcf, 0x54, 0xd9, 0x92, 0x55, + 0xdd, 0x9d, 0xd2, 0xdc, 0x35, 0x8e, 0x4d, 0x75, 0x8a, 0x56, 0x03, 0xde, 0x52, 0x91, 0x6c, 0xe4, + 0x17, 0xc9, 0x82, 0x88, 0xa9, 0x27, 0x9c, 0x5d, 0x77, 0xe6, 0x37, 0x61, 0x91, 0x8d, 0xe5, 0xad, + 0x5e, 0xb6, 0x2a, 0x6c, 0x7c, 0xe8, 0xe8, 0x6b, 0xb0, 0xc4, 0x13, 0x74, 0x41, 0xa0, 0x8b, 0x5c, + 0xc0, 0x07, 0x50, 0x25, 0x03, 0x8a, 0xa3, 0x11, 0x76, 0xfa, 0x6c, 0x2c, 0x6e, 0x43, 0x75, 0x6f, + 0x47, 0xf5, 0x28, 0x47, 0x79, 0x22, 0x0a, 0xc5, 0x3d, 0xb4, 0x40, 0x76, 0x1d, 0x8f, 0xbb, 0xef, + 0x97, 0x2c, 0xab, 0x3b, 0xa5, 0x68, 0x26, 0xdd, 0x29, 0x45, 0x28, 0xf3, 0xfe, 0x47, 0xee, 0xfd, + 0x53, 0x44, 0x8f, 0x22, 0xcf, 0xc6, 0xd7, 0xf0, 0xde, 0x86, 0x5a, 0xe6, 0x27, 0x59, 0xd8, 0x59, + 0x0e, 0xb7, 0x24, 0xf1, 0x71, 0x8c, 0x1f, 0x3a, 0x7a, 0x1d, 0x16, 0xc3, 0xf8, 0x67, 0x44, 0x22, + 0x15, 0x2b, 0xf9, 0xa2, 0xef, 0xc0, 0xca, 0xe0, 0x94, 0xd8, 0xdf, 0xf6, 0x03, 0xee, 0x0f, 0x70, + 0x24, 0x22, 0xa9, 0x58, 0x55, 0x81, 0x3d, 0x16, 0xd0, 0x7f, 0x30, 0x2c, 0x1d, 0x14, 0x0c, 0x4b, + 0x28, 0x33, 0xfc, 0xa7, 0x06, 0xab, 0x29, 0x27, 0x26, 0xea, 0x61, 0x86, 0xfe, 0x2f, 0xc7, 0x49, + 0xe3, 0x10, 0x7b, 0xee, 0x90, 0x49, 0xc7, 0x02, 0xfb, 0x4c, 0x40, 0xdd, 0x76, 0xc9, 0xb1, 0x31, + 0xe1, 0x38, 0xb3, 0xd0, 0x32, 0xa0, 0x51, 0xc6, 0xa4, 0xe7, 0xbd, 0x7f, 0x2a, 0xb0, 0xd0, 0xa3, + 0xae, 0x7e, 0x0c, 0x2b, 0xca, 0x53, 0x70, 0xab, 0xb4, 0x3d, 0xd4, 0xe7, 0x8e, 0xf1, 0xee, 0x4c, + 0x5a, 0xaa, 0xeb, 0x4f, 0xe1, 0x66, 0xe9, 0x91, 0x74, 0x67, 0xa2, 0x51, 0x2d, 0x30, 0xee, 0xbe, + 0xa2, 0x20, 0xd3, 0x7e, 0x0c, 0x50, 0x58, 0xc7, 0x9b, 0x13, 0x6d, 0x39, 0x69, 0xbc, 0x3d, 0x83, + 0xcc, 0xf4, 0xbe, 0x80, 0x6a, 0x71, 0x33, 0xdd, 0x9e, 0xe8, 0x29, 0xb0, 0xc6, 0x3b, 0xb3, 0xd8, + 0x4c, 0xf2, 0x18, 0x56, 0x94, 0xcd, 0xb1, 0x35, 0xb5, 0x4b, 0xd2, 0x53, 0x42, 0x9d, 0xf6, 0xbf, + 0x94, 0xaa, 0xd9, 0x7f, 0x72, 0xba, 0xaa, 0xa4, 0x5f, 0xa2, 0x5a, 0x3e, 0xfc, 0xfa, 0xd7, 0x70, + 0x43, 0x3d, 0xf8, 0xcd, 0xa9, 0x7d, 0x19, 0x6f, 0xbc, 0x37, 0x9b, 0x97, 0xc2, 0xc6, 0xe2, 0x77, + 0x57, 0xe7, 0x6d, 0xed, 0xe0, 0xe8, 0xd9, 0x45, 0x53, 0x7b, 0x7e, 0xd1, 0xd4, 0xfe, 0xbe, 0x68, + 0x6a, 0x3f, 0x5e, 0x36, 0xe7, 0x9e, 0x5f, 0x36, 0xe7, 0xfe, 0xba, 0x6c, 0xce, 0x3d, 0x7d, 0xe8, + 0x7a, 0x6c, 0xc8, 0x07, 0x1d, 0x9b, 0xf8, 0x66, 0xc8, 0xe9, 0x50, 0x1c, 0x73, 0x71, 0xb5, 0x2b, + 0x2e, 0x77, 0x03, 0xe2, 0x60, 0x73, 0x6c, 0xe6, 0x27, 0x5c, 0xbc, 0x12, 0x0e, 0x96, 0xc4, 0x3b, + 0xdc, 0x47, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x35, 0xfc, 0xc3, 0xe2, 0x80, 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -754,6 +866,8 @@ type MsgClient interface { VoteOutbound(ctx context.Context, in *MsgVoteOutbound, opts ...grpc.CallOption) (*MsgVoteOutboundResponse, error) // VoteGasPrice defines a message for universal validators to vote on the gas price VoteGasPrice(ctx context.Context, in *MsgVoteGasPrice, opts ...grpc.CallOption) (*MsgVoteGasPriceResponse, error) + // VoteChainMeta defines a message for universal validators to vote on chain metadata (gas price + block height) + VoteChainMeta(ctx context.Context, in *MsgVoteChainMeta, opts ...grpc.CallOption) (*MsgVoteChainMetaResponse, error) } type msgClient struct { @@ -818,6 +932,15 @@ func (c *msgClient) VoteGasPrice(ctx context.Context, in *MsgVoteGasPrice, opts return out, nil } +func (c *msgClient) VoteChainMeta(ctx context.Context, in *MsgVoteChainMeta, opts ...grpc.CallOption) (*MsgVoteChainMetaResponse, error) { + out := new(MsgVoteChainMetaResponse) + err := c.cc.Invoke(ctx, "/uexecutor.v1.Msg/VoteChainMeta", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // UpdateParams defines a governance operation for updating the parameters. @@ -834,6 +957,8 @@ type MsgServer interface { VoteOutbound(context.Context, *MsgVoteOutbound) (*MsgVoteOutboundResponse, error) // VoteGasPrice defines a message for universal validators to vote on the gas price VoteGasPrice(context.Context, *MsgVoteGasPrice) (*MsgVoteGasPriceResponse, error) + // VoteChainMeta defines a message for universal validators to vote on chain metadata (gas price + block height) + VoteChainMeta(context.Context, *MsgVoteChainMeta) (*MsgVoteChainMetaResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -858,6 +983,9 @@ func (*UnimplementedMsgServer) VoteOutbound(ctx context.Context, req *MsgVoteOut func (*UnimplementedMsgServer) VoteGasPrice(ctx context.Context, req *MsgVoteGasPrice) (*MsgVoteGasPriceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method VoteGasPrice not implemented") } +func (*UnimplementedMsgServer) VoteChainMeta(ctx context.Context, req *MsgVoteChainMeta) (*MsgVoteChainMetaResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteChainMeta not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -971,6 +1099,24 @@ func _Msg_VoteGasPrice_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Msg_VoteChainMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVoteChainMeta) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).VoteChainMeta(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/uexecutor.v1.Msg/VoteChainMeta", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).VoteChainMeta(ctx, req.(*MsgVoteChainMeta)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "uexecutor.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -999,6 +1145,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "VoteGasPrice", Handler: _Msg_VoteGasPrice_Handler, }, + { + MethodName: "VoteChainMeta", + Handler: _Msg_VoteChainMeta_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/tx.proto", @@ -1449,6 +1599,76 @@ func (m *MsgVoteGasPriceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *MsgVoteChainMeta) 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 *MsgVoteChainMeta) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteChainMeta) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ChainHeight != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ChainHeight)) + i-- + dAtA[i] = 0x20 + } + if m.Price != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Price)) + i-- + dAtA[i] = 0x18 + } + if len(m.ObservedChainId) > 0 { + i -= len(m.ObservedChainId) + copy(dAtA[i:], m.ObservedChainId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ObservedChainId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgVoteChainMetaResponse) 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 *MsgVoteChainMetaResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteChainMetaResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -1644,6 +1864,38 @@ func (m *MsgVoteGasPriceResponse) Size() (n int) { return n } +func (m *MsgVoteChainMeta) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ObservedChainId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Price != 0 { + n += 1 + sovTx(uint64(m.Price)) + } + if m.ChainHeight != 0 { + n += 1 + sovTx(uint64(m.ChainHeight)) + } + return n +} + +func (m *MsgVoteChainMetaResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2889,6 +3141,208 @@ func (m *MsgVoteGasPriceResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgVoteChainMeta) 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 ErrIntOverflowTx + } + 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: MsgVoteChainMeta: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteChainMeta: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObservedChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ObservedChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) + } + m.Price = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Price |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainHeight", wireType) + } + m.ChainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ChainHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVoteChainMetaResponse) 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 ErrIntOverflowTx + } + 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: MsgVoteChainMetaResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteChainMetaResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/uexecutor/types/tx_type.go b/x/uexecutor/types/tx_type.go index a4bef026..f951d6d8 100644 --- a/x/uexecutor/types/tx_type.go +++ b/x/uexecutor/types/tx_type.go @@ -12,7 +12,7 @@ func SolidityTxTypeToProto(txTypeUint8 uint8) TxType { case 3: return TxType_FUNDS_AND_PAYLOAD case 4: - return TxType_PAYLOAD + return TxType_RESCUE_FUNDS case 5: return TxType_INBOUND_REVERT default: diff --git a/x/uexecutor/types/types.pb.go b/x/uexecutor/types/types.pb.go index 41fbf44e..0fd6ad0b 100644 --- a/x/uexecutor/types/types.pb.go +++ b/x/uexecutor/types/types.pb.go @@ -140,6 +140,7 @@ const ( TxType_FUNDS_AND_PAYLOAD TxType = 4 TxType_PAYLOAD TxType = 5 TxType_INBOUND_REVERT TxType = 6 + TxType_RESCUE_FUNDS TxType = 7 ) var TxType_name = map[int32]string{ @@ -150,6 +151,7 @@ var TxType_name = map[int32]string{ 4: "FUNDS_AND_PAYLOAD", 5: "PAYLOAD", 6: "INBOUND_REVERT", + 7: "RESCUE_FUNDS", } var TxType_value = map[string]int32{ @@ -160,6 +162,7 @@ var TxType_value = map[string]int32{ "FUNDS_AND_PAYLOAD": 4, "PAYLOAD": 5, "INBOUND_REVERT": 6, + "RESCUE_FUNDS": 7, } func (x TxType) String() string { @@ -740,6 +743,7 @@ type OutboundObservation struct { BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` TxHash string `protobuf:"bytes,3,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` ErrorMsg string `protobuf:"bytes,4,opt,name=error_msg,json=errorMsg,proto3" json:"error_msg,omitempty"` + GasFeeUsed string `protobuf:"bytes,5,opt,name=gas_fee_used,json=gasFeeUsed,proto3" json:"gas_fee_used,omitempty"` } func (m *OutboundObservation) Reset() { *m = OutboundObservation{} } @@ -803,6 +807,13 @@ func (m *OutboundObservation) GetErrorMsg() string { return "" } +func (m *OutboundObservation) GetGasFeeUsed() string { + if m != nil { + return m.GasFeeUsed + } + return "" +} + type OriginatingPcTx struct { TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` LogIndex string `protobuf:"bytes,2,opt,name=log_index,json=logIndex,proto3" json:"log_index,omitempty"` @@ -871,6 +882,11 @@ type OutboundTx struct { OutboundStatus Status `protobuf:"varint,13,opt,name=outbound_status,json=outboundStatus,proto3,enum=uexecutor.v1.Status" json:"outbound_status,omitempty"` RevertInstructions *RevertInstructions `protobuf:"bytes,14,opt,name=revert_instructions,json=revertInstructions,proto3" json:"revert_instructions,omitempty"` PcRevertExecution *PCTx `protobuf:"bytes,15,opt,name=pc_revert_execution,json=pcRevertExecution,proto3" json:"pc_revert_execution,omitempty"` + GasPrice string `protobuf:"bytes,16,opt,name=gas_price,json=gasPrice,proto3" json:"gas_price,omitempty"` + GasFee string `protobuf:"bytes,17,opt,name=gas_fee,json=gasFee,proto3" json:"gas_fee,omitempty"` + PcRefundExecution *PCTx `protobuf:"bytes,18,opt,name=pc_refund_execution,json=pcRefundExecution,proto3" json:"pc_refund_execution,omitempty"` + RefundSwapError string `protobuf:"bytes,19,opt,name=refund_swap_error,json=refundSwapError,proto3" json:"refund_swap_error,omitempty"` + GasToken string `protobuf:"bytes,20,opt,name=gas_token,json=gasToken,proto3" json:"gas_token,omitempty"` } func (m *OutboundTx) Reset() { *m = OutboundTx{} } @@ -1010,12 +1026,46 @@ func (m *OutboundTx) GetPcRevertExecution() *PCTx { return nil } +func (m *OutboundTx) GetGasPrice() string { + if m != nil { + return m.GasPrice + } + return "" +} + +func (m *OutboundTx) GetGasFee() string { + if m != nil { + return m.GasFee + } + return "" +} + +func (m *OutboundTx) GetPcRefundExecution() *PCTx { + if m != nil { + return m.PcRefundExecution + } + return nil +} + +func (m *OutboundTx) GetRefundSwapError() string { + if m != nil { + return m.RefundSwapError + } + return "" +} + +func (m *OutboundTx) GetGasToken() string { + if m != nil { + return m.GasToken + } + return "" +} + type UniversalTx struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - InboundTx *Inbound `protobuf:"bytes,2,opt,name=inbound_tx,json=inboundTx,proto3" json:"inbound_tx,omitempty"` - PcTx []*PCTx `protobuf:"bytes,3,rep,name=pc_tx,json=pcTx,proto3" json:"pc_tx,omitempty"` - OutboundTx []*OutboundTx `protobuf:"bytes,4,rep,name=outbound_tx,json=outboundTx,proto3" json:"outbound_tx,omitempty"` - UniversalStatus UniversalTxStatus `protobuf:"varint,5,opt,name=universal_status,json=universalStatus,proto3,enum=uexecutor.v1.UniversalTxStatus" json:"universal_status,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + InboundTx *Inbound `protobuf:"bytes,2,opt,name=inbound_tx,json=inboundTx,proto3" json:"inbound_tx,omitempty"` + PcTx []*PCTx `protobuf:"bytes,3,rep,name=pc_tx,json=pcTx,proto3" json:"pc_tx,omitempty"` + OutboundTx []*OutboundTx `protobuf:"bytes,4,rep,name=outbound_tx,json=outboundTx,proto3" json:"outbound_tx,omitempty"` } func (m *UniversalTx) Reset() { *m = UniversalTx{} } @@ -1078,13 +1128,6 @@ func (m *UniversalTx) GetOutboundTx() []*OutboundTx { return nil } -func (m *UniversalTx) GetUniversalStatus() UniversalTxStatus { - if m != nil { - return m.UniversalStatus - } - return UniversalTxStatus_UNIVERSAL_TX_STATUS_UNSPECIFIED -} - type InboundLegacy struct { SourceChain string `protobuf:"bytes,1,opt,name=source_chain,json=sourceChain,proto3" json:"source_chain,omitempty"` TxHash string `protobuf:"bytes,2,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` @@ -1370,115 +1413,121 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/types.proto", fileDescriptor_fab6d3ca71d1e2a5) } var fileDescriptor_fab6d3ca71d1e2a5 = []byte{ - // 1717 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4b, 0x6f, 0xdb, 0xd8, - 0x15, 0x36, 0xa9, 0xf7, 0x91, 0x63, 0x51, 0xd7, 0x4e, 0xc2, 0x24, 0x63, 0xd9, 0xd1, 0xcc, 0x34, - 0x86, 0x8b, 0xd8, 0x1d, 0xb7, 0x1d, 0xa0, 0x02, 0x8a, 0x42, 0x96, 0x69, 0x8f, 0x5a, 0x8f, 0xac, - 0x52, 0x92, 0x91, 0xe9, 0x86, 0xa0, 0xc9, 0x1b, 0x9a, 0xa8, 0x44, 0x0a, 0x7c, 0xa8, 0xf4, 0xa2, - 0xab, 0xee, 0x8a, 0x2e, 0xba, 0xcc, 0x32, 0xcb, 0xa2, 0x5d, 0xb4, 0x05, 0xfa, 0x23, 0x66, 0x39, - 0xdd, 0x15, 0xe8, 0xa6, 0x48, 0x16, 0x2d, 0xd0, 0x3f, 0x51, 0xdc, 0x07, 0x45, 0x52, 0x8f, 0xc9, - 0x14, 0x59, 0x14, 0xe8, 0x26, 0xe6, 0x79, 0xdc, 0x73, 0xbf, 0x73, 0xbe, 0x73, 0xce, 0x75, 0x0c, - 0x72, 0x88, 0x23, 0x6c, 0x84, 0x81, 0xeb, 0x1d, 0xcf, 0x3e, 0x39, 0x0e, 0xee, 0xa6, 0xd8, 0x3f, - 0x9a, 0x7a, 0x6e, 0xe0, 0xa2, 0xcd, 0xb9, 0xe5, 0x68, 0xf6, 0xc9, 0xe3, 0x1d, 0xcb, 0xb5, 0x5c, - 0x6a, 0x38, 0x26, 0x5f, 0xcc, 0xe7, 0x71, 0x5d, 0x9f, 0xd8, 0x8e, 0x7b, 0x4c, 0xff, 0x65, 0xaa, - 0xe6, 0x39, 0x14, 0xfb, 0xba, 0xa7, 0x4f, 0x7c, 0xb4, 0x0b, 0xe0, 0xbb, 0x13, 0xac, 0xcd, 0xf4, - 0x71, 0x88, 0x65, 0x71, 0x5f, 0x38, 0x28, 0xab, 0x15, 0xa2, 0xb9, 0x26, 0x8a, 0xd6, 0xee, 0xab, - 0xd7, 0x7b, 0x1b, 0xff, 0x7a, 0xbd, 0x27, 0xfc, 0xfa, 0x9f, 0x7f, 0x3a, 0x94, 0x12, 0x18, 0x53, - 0x7a, 0xba, 0xf9, 0x77, 0x11, 0xa4, 0x91, 0x63, 0xcf, 0xb0, 0xe7, 0xeb, 0xe3, 0xbe, 0x7e, 0x37, - 0x76, 0x75, 0x13, 0x6d, 0x81, 0x18, 0xb8, 0xb2, 0xb0, 0x2f, 0x1c, 0x54, 0x54, 0x31, 0x70, 0xd1, - 0x0e, 0x14, 0x92, 0xe8, 0x15, 0x95, 0x09, 0x08, 0x41, 0xde, 0xd4, 0x03, 0x5d, 0xce, 0x51, 0x25, - 0xfd, 0x46, 0x4f, 0xa0, 0x62, 0xe9, 0xbe, 0x36, 0xb6, 0x27, 0x76, 0x20, 0xe7, 0xa9, 0xa1, 0x6c, - 0xe9, 0xfe, 0x25, 0x91, 0xd1, 0xc7, 0x50, 0x9b, 0xe8, 0x91, 0xf6, 0x12, 0x63, 0x6d, 0x8a, 0x3d, - 0xcd, 0xd2, 0x7d, 0xb9, 0x40, 0x5d, 0x36, 0x27, 0x7a, 0x74, 0x8e, 0x71, 0x1f, 0x7b, 0x17, 0xba, - 0x8f, 0x3e, 0x05, 0x99, 0xb8, 0x4d, 0x3d, 0xdb, 0xf5, 0xec, 0xe0, 0x2e, 0xe3, 0x5f, 0xa4, 0xfe, - 0x3b, 0x13, 0x3d, 0xea, 0x73, 0x73, 0x72, 0x6e, 0x07, 0x0a, 0x8e, 0xeb, 0x18, 0x58, 0x2e, 0x31, - 0x94, 0x54, 0x40, 0x8f, 0xa1, 0x6c, 0x62, 0xdd, 0x1c, 0xdb, 0x0e, 0x96, 0xcb, 0x0c, 0x50, 0x2c, - 0xa3, 0xef, 0x43, 0x71, 0xa6, 0x11, 0x32, 0xe4, 0xca, 0xbe, 0x70, 0xb0, 0x75, 0xd2, 0x38, 0x4a, - 0x93, 0x71, 0x74, 0x8d, 0x3d, 0xfb, 0xa5, 0x6d, 0xe8, 0x81, 0xed, 0x3a, 0xc3, 0xbb, 0x29, 0x56, - 0x0b, 0x33, 0xf2, 0xa3, 0x75, 0x90, 0x2e, 0xe9, 0x93, 0xa4, 0xa4, 0x61, 0x5c, 0x47, 0x6d, 0xca, - 0x0a, 0xd9, 0xfc, 0x8d, 0x00, 0xd2, 0xe7, 0xb6, 0xe5, 0xd1, 0x10, 0x71, 0x75, 0x3f, 0x80, 0xca, - 0x24, 0xd6, 0xf1, 0x22, 0x27, 0x8a, 0x24, 0x0b, 0x71, 0x5d, 0x16, 0xb9, 0x6c, 0x16, 0x6b, 0xe1, - 0xcc, 0x63, 0xce, 0xe1, 0xbc, 0x12, 0x00, 0xcd, 0xc9, 0x6e, 0x1b, 0x86, 0x1b, 0x3a, 0x41, 0xd7, - 0x44, 0xcf, 0xa0, 0x66, 0xdc, 0xea, 0xb6, 0xa3, 0x39, 0xfa, 0x04, 0xfb, 0x53, 0xdd, 0xc0, 0x1c, - 0xd6, 0x16, 0x55, 0xf7, 0x62, 0x2d, 0x7a, 0x04, 0x65, 0xe6, 0x68, 0x9b, 0x1c, 0x5e, 0x89, 0xca, - 0x5d, 0x93, 0xc0, 0x76, 0x7f, 0xe1, 0x60, 0x8f, 0xa3, 0x63, 0xc2, 0x37, 0xa8, 0x94, 0xce, 0x50, - 0x34, 0x0d, 0x40, 0x2a, 0x9e, 0x61, 0x2f, 0xe8, 0x3a, 0x7e, 0xe0, 0x85, 0x06, 0xc1, 0xed, 0xa3, - 0x8f, 0x61, 0xeb, 0x65, 0xe8, 0x98, 0x9a, 0x87, 0x0d, 0x7b, 0x6a, 0x63, 0x27, 0xe0, 0xc0, 0xee, - 0x11, 0xad, 0x1a, 0x2b, 0x5b, 0xdf, 0x8a, 0xaf, 0xd8, 0x4d, 0xae, 0xf0, 0x68, 0x34, 0xcd, 0x4e, - 0x85, 0x6b, 0xfe, 0x3b, 0x07, 0xa5, 0xae, 0x73, 0xe3, 0x86, 0x8e, 0x89, 0x9e, 0xc2, 0xa6, 0xef, - 0x86, 0x9e, 0x81, 0x35, 0x9a, 0x02, 0x0f, 0x5c, 0x65, 0xba, 0x0e, 0x51, 0xa1, 0x87, 0x50, 0x0a, - 0x22, 0xed, 0x56, 0xf7, 0x6f, 0x79, 0xb6, 0xc5, 0x20, 0xfa, 0x4c, 0xf7, 0x6f, 0xd1, 0x03, 0x28, - 0xfa, 0xd8, 0x31, 0xe7, 0xd9, 0x72, 0x89, 0x30, 0x9b, 0x20, 0x65, 0xdd, 0x9f, 0x28, 0xc8, 0x29, - 0x7d, 0x42, 0x92, 0xe5, 0x5d, 0xcf, 0x25, 0x32, 0xc0, 0xba, 0xef, 0xe3, 0x40, 0xd3, 0x4d, 0xd3, - 0xe3, 0x1d, 0x5e, 0xa1, 0x9a, 0xb6, 0x69, 0x7a, 0x64, 0xa4, 0xc6, 0xae, 0xa5, 0xd9, 0x8e, 0x89, - 0x23, 0xde, 0xda, 0xe5, 0xb1, 0x6b, 0x75, 0x89, 0x8c, 0x9e, 0x53, 0x88, 0xb4, 0x85, 0xcb, 0xb4, - 0x85, 0x77, 0xb2, 0x2d, 0x3c, 0x8c, 0x68, 0xe3, 0x16, 0x03, 0xfa, 0x13, 0xfd, 0x04, 0xea, 0x4b, - 0x4d, 0x4a, 0x7b, 0xbf, 0xba, 0xd8, 0xfb, 0x8b, 0x3b, 0x41, 0x95, 0xc2, 0xc5, 0x2d, 0xf1, 0x6d, - 0xa8, 0xcf, 0x52, 0x13, 0xa2, 0xd1, 0x65, 0x00, 0x14, 0xa0, 0x94, 0x36, 0x9c, 0x91, 0xc5, 0xf0, - 0x53, 0xd8, 0x5e, 0xc1, 0x88, 0x5c, 0xa5, 0x77, 0xef, 0x67, 0xef, 0x5e, 0x6e, 0x04, 0x15, 0x79, - 0xcb, 0xcd, 0xb1, 0x03, 0x05, 0xdb, 0xef, 0x28, 0x6d, 0x79, 0x93, 0xee, 0x3c, 0x26, 0xb4, 0xca, - 0x71, 0xcb, 0x35, 0xbf, 0x14, 0x20, 0xdf, 0xef, 0x0c, 0xa3, 0x34, 0x8f, 0xc2, 0x1a, 0x1e, 0xc5, - 0x0c, 0x8f, 0x8f, 0x80, 0x2c, 0x2d, 0x2d, 0xf4, 0xb1, 0x49, 0x19, 0xce, 0xab, 0x25, 0x4b, 0xf7, - 0x47, 0x3e, 0xa6, 0x6d, 0x73, 0x33, 0x76, 0x8d, 0x9f, 0x6b, 0xb7, 0xd8, 0xb6, 0x6e, 0x19, 0xcb, - 0x79, 0xb5, 0x4a, 0x75, 0x9f, 0x51, 0x15, 0x8d, 0x1a, 0xe8, 0x41, 0x18, 0x6f, 0x2b, 0x2e, 0x11, - 0x22, 0xb1, 0xe7, 0xb9, 0x9e, 0x36, 0xf1, 0xad, 0x98, 0x48, 0xaa, 0xf8, 0xdc, 0xb7, 0x5a, 0x1f, - 0xa4, 0x27, 0xa5, 0x96, 0x5a, 0xd3, 0x86, 0x16, 0x44, 0xcd, 0x3f, 0x0b, 0xb0, 0x7d, 0x15, 0x06, - 0xb4, 0x73, 0xaf, 0x6e, 0x7c, 0xec, 0xcd, 0xd8, 0xb2, 0x90, 0xa1, 0xe4, 0x87, 0x86, 0x81, 0x7d, - 0x9f, 0x66, 0x56, 0x56, 0x63, 0x71, 0x09, 0xa7, 0xb8, 0x8c, 0x33, 0x55, 0x96, 0x5c, 0xa6, 0x2c, - 0x19, 0xa0, 0xf9, 0x05, 0xa0, 0xcf, 0x62, 0x90, 0x8d, 0x04, 0xa4, 0xcb, 0xa1, 0x69, 0x6e, 0x82, - 0xad, 0x39, 0x81, 0xda, 0x95, 0x67, 0x5b, 0xb6, 0xa3, 0x07, 0xb6, 0x63, 0xf5, 0x8d, 0xaf, 0x23, - 0x22, 0xd3, 0xe3, 0x62, 0xb6, 0xc7, 0x5b, 0x1f, 0xad, 0x58, 0x20, 0x6e, 0x12, 0x59, 0x63, 0x25, - 0xfa, 0x63, 0x01, 0x20, 0x2e, 0xd1, 0x30, 0x22, 0xcd, 0x69, 0x62, 0x3f, 0xa0, 0x3e, 0xae, 0x93, - 0x99, 0x71, 0x29, 0x65, 0x60, 0x83, 0x9e, 0x99, 0x5b, 0x71, 0xfd, 0xdc, 0xe6, 0x32, 0x73, 0x7b, - 0x04, 0xdb, 0x38, 0x0a, 0xb0, 0xe7, 0x90, 0x35, 0x96, 0x0c, 0x30, 0x2b, 0x58, 0x3d, 0x36, 0xb5, - 0xe7, 0x83, 0x7c, 0x00, 0xd2, 0xd4, 0x33, 0x4e, 0xbe, 0x93, 0x76, 0x66, 0x9b, 0x60, 0x8b, 0xea, - 0x13, 0xcf, 0xa4, 0x2f, 0x8b, 0x99, 0xbe, 0x94, 0xa1, 0x14, 0x0f, 0x2d, 0xeb, 0x9f, 0x58, 0xcc, - 0xbe, 0xbb, 0xe5, 0x85, 0x77, 0x37, 0xb5, 0x24, 0x2a, 0xdf, 0x60, 0x49, 0x9c, 0x40, 0x81, 0x96, - 0x94, 0xce, 0x72, 0xf5, 0x64, 0x37, 0xeb, 0xbc, 0xc0, 0xa9, 0x9a, 0x9f, 0x12, 0x66, 0x4f, 0xa1, - 0xca, 0xb8, 0xc7, 0x26, 0x39, 0xc9, 0xc6, 0xfa, 0xe9, 0xc2, 0xc9, 0xe5, 0x06, 0x56, 0x21, 0x3e, - 0x35, 0x8c, 0xc8, 0x6f, 0x1d, 0xb6, 0x49, 0x87, 0xb9, 0xa2, 0x8a, 0xb6, 0x89, 0x7e, 0x08, 0xb5, - 0x79, 0x63, 0xf1, 0x81, 0xba, 0xb7, 0x0a, 0xfe, 0x80, 0xda, 0xd4, 0xad, 0xd8, 0x99, 0xc9, 0xeb, - 0x36, 0xce, 0xd6, 0x7b, 0x6c, 0x9c, 0x53, 0xd8, 0x9e, 0x1a, 0x1a, 0x8f, 0xca, 0xce, 0x93, 0x37, - 0xbc, 0x46, 0x43, 0xa2, 0x6c, 0x48, 0xb2, 0x79, 0xd4, 0xfa, 0xd4, 0x60, 0xa1, 0x95, 0xd8, 0x39, - 0xb5, 0x9f, 0x7e, 0x27, 0x42, 0x75, 0xbe, 0x66, 0xe7, 0xf9, 0x0b, 0xf3, 0xfc, 0xbf, 0x07, 0x60, - 0xb3, 0xc7, 0x8a, 0x94, 0x54, 0xa4, 0x97, 0xdc, 0xcf, 0x5e, 0xc2, 0x1f, 0x33, 0xb5, 0xc2, 0x1d, - 0x87, 0x11, 0x7a, 0x16, 0xb3, 0x97, 0xdb, 0xcf, 0xad, 0x41, 0xc5, 0x28, 0xfb, 0x01, 0x54, 0xe7, - 0xe5, 0x0d, 0x22, 0x39, 0x4f, 0xdd, 0xe5, 0xd5, 0x94, 0x0d, 0x23, 0x15, 0xdc, 0x64, 0xb8, 0x7e, - 0x0c, 0xc9, 0x6b, 0x10, 0x53, 0x53, 0xa0, 0xd4, 0xec, 0xad, 0x79, 0x45, 0x86, 0x11, 0x67, 0xa9, - 0x36, 0x3f, 0xc8, 0x14, 0xad, 0x0f, 0xd3, 0x8b, 0xef, 0xc1, 0xaa, 0x5f, 0x11, 0x82, 0xa8, 0xf9, - 0x87, 0x1c, 0xdc, 0xe3, 0xb9, 0x5e, 0x62, 0x4b, 0x37, 0xee, 0xfe, 0x4f, 0x9e, 0xef, 0xd6, 0xe2, - 0xf3, 0xfd, 0x74, 0x25, 0xbf, 0x6c, 0x40, 0x59, 0xe6, 0xff, 0xfb, 0xb7, 0xbc, 0xd5, 0x78, 0xf5, - 0x7a, 0x4f, 0x88, 0x29, 0xab, 0x27, 0x94, 0xf1, 0x26, 0x6c, 0xfe, 0x55, 0x00, 0x29, 0xe9, 0x1c, - 0x4e, 0xd8, 0x7f, 0xb5, 0x90, 0xd7, 0x52, 0x97, 0xa1, 0x28, 0xb7, 0x9e, 0xa2, 0xfc, 0xd7, 0x50, - 0x54, 0x58, 0xa0, 0xa8, 0xd5, 0x4c, 0xe7, 0x73, 0x7f, 0xc5, 0xb3, 0x16, 0x44, 0xcd, 0xdf, 0x8b, - 0x50, 0x4f, 0x75, 0x33, 0x4f, 0xaa, 0x95, 0x19, 0x51, 0x81, 0x16, 0xff, 0xc9, 0x4a, 0x0a, 0x39, - 0x79, 0xab, 0x06, 0x55, 0x7c, 0xc7, 0xa0, 0xfe, 0x28, 0x3b, 0xa8, 0xb9, 0x55, 0x14, 0x2f, 0x96, - 0xfb, 0x9d, 0xe3, 0x9a, 0x7f, 0x8f, 0x71, 0x15, 0xde, 0x31, 0xae, 0x87, 0x17, 0x20, 0x2d, 0xfe, - 0xdf, 0x09, 0x3d, 0x00, 0xe4, 0xdb, 0x96, 0x83, 0xcd, 0xb4, 0x45, 0xda, 0x40, 0x4f, 0xe0, 0x61, - 0x98, 0x5c, 0x9b, 0x31, 0x0a, 0x87, 0xbf, 0xca, 0x56, 0x9d, 0x6f, 0xf6, 0x0f, 0x61, 0x6f, 0xd4, - 0xeb, 0x5e, 0x2b, 0xea, 0xa0, 0x7d, 0xa9, 0x0d, 0x5f, 0x68, 0x83, 0x61, 0x7b, 0x38, 0x1a, 0x68, - 0xa3, 0xde, 0xa0, 0xaf, 0x74, 0xba, 0xe7, 0x5d, 0xe5, 0x4c, 0xda, 0x40, 0xdb, 0x50, 0xeb, 0xf6, - 0x4e, 0xaf, 0x46, 0xbd, 0x33, 0x6d, 0x30, 0xea, 0x74, 0x94, 0xc1, 0x40, 0x12, 0xd0, 0x2e, 0x3c, - 0xea, 0x2b, 0xbd, 0xb3, 0x6e, 0xef, 0x42, 0x8b, 0x8d, 0xca, 0x0b, 0xa5, 0x33, 0x1a, 0x76, 0xaf, - 0x7a, 0x92, 0x88, 0x1e, 0xc2, 0x76, 0xbf, 0xc3, 0x35, 0x4a, 0x72, 0x2e, 0x47, 0xc0, 0xa7, 0x0d, - 0xe7, 0xed, 0xee, 0xa5, 0x72, 0x26, 0xe5, 0xd1, 0x7d, 0xa8, 0xf7, 0x3b, 0x5a, 0x1c, 0x52, 0x55, - 0xae, 0x15, 0x75, 0x28, 0x15, 0xd0, 0x0e, 0x48, 0x57, 0xa3, 0x21, 0x8b, 0xcf, 0x8d, 0x52, 0x31, - 0xa3, 0x8d, 0x43, 0x97, 0x08, 0xce, 0xb9, 0x96, 0xc7, 0x2d, 0xa3, 0x4d, 0x28, 0x77, 0xda, 0xbd, - 0x8e, 0x42, 0xa4, 0xca, 0xe1, 0x29, 0x14, 0x79, 0xe6, 0x35, 0xa8, 0x66, 0xb3, 0xac, 0x42, 0x29, - 0xbe, 0x40, 0x20, 0xa7, 0xae, 0x4e, 0x07, 0x8a, 0x7a, 0xad, 0x9c, 0x49, 0x22, 0x91, 0x18, 0x20, - 0xe5, 0x4c, 0xca, 0x1d, 0xfe, 0x12, 0x8a, 0x6c, 0x8b, 0x20, 0x04, 0x5b, 0xa9, 0x18, 0xda, 0xf0, - 0x85, 0xb4, 0x81, 0x4a, 0x90, 0xbb, 0x68, 0x93, 0x02, 0x6d, 0x43, 0xed, 0xa2, 0x3d, 0xd0, 0xda, - 0x04, 0x78, 0xfb, 0x8b, 0xcb, 0xab, 0x36, 0x89, 0x54, 0x81, 0xc2, 0xf9, 0xa8, 0x77, 0x46, 0x0a, - 0x71, 0x1f, 0xea, 0xf4, 0x33, 0xe3, 0x91, 0xa7, 0x30, 0xb8, 0x50, 0x20, 0x17, 0xc4, 0xc5, 0xe5, - 0x15, 0x29, 0x1e, 0xfe, 0x45, 0x80, 0xed, 0x15, 0xcb, 0x0c, 0x3d, 0x85, 0xdd, 0xd8, 0xf7, 0x52, - 0xb9, 0x68, 0x77, 0xbe, 0xd0, 0x96, 0xb0, 0x3d, 0x00, 0xb4, 0xe0, 0xc2, 0xa0, 0xca, 0xb0, 0xb3, - 0xa0, 0x67, 0x20, 0x45, 0xf4, 0x11, 0xec, 0xaf, 0xb2, 0x64, 0x30, 0xe7, 0x50, 0x13, 0x1a, 0xcb, - 0x71, 0xb3, 0x79, 0x9d, 0xf6, 0xbf, 0x7c, 0xd3, 0x10, 0xbe, 0x7a, 0xd3, 0x10, 0xfe, 0xf1, 0xa6, - 0x21, 0xfc, 0xf6, 0x6d, 0x63, 0xe3, 0xab, 0xb7, 0x8d, 0x8d, 0xbf, 0xbd, 0x6d, 0x6c, 0xfc, 0xec, - 0x53, 0xcb, 0x0e, 0x6e, 0xc3, 0x9b, 0x23, 0xc3, 0x9d, 0x1c, 0x4f, 0x43, 0xff, 0x96, 0xee, 0x33, - 0xfa, 0xf5, 0x9c, 0x7e, 0x3e, 0x77, 0x5c, 0x13, 0x1f, 0x47, 0xc7, 0xc9, 0x84, 0xd0, 0x3f, 0xfa, - 0xdc, 0x14, 0xe9, 0x9f, 0x6f, 0xbe, 0xfb, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x67, 0xec, - 0x6e, 0x11, 0x12, 0x00, 0x00, + // 1819 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4f, 0x6f, 0xdb, 0xd8, + 0x11, 0x37, 0xf5, 0x5f, 0x23, 0xc7, 0xa2, 0x9e, 0x94, 0x84, 0x49, 0xd6, 0xb2, 0xa3, 0xdd, 0x6d, + 0x0c, 0x17, 0xb1, 0xbb, 0x69, 0xbb, 0x40, 0x05, 0x14, 0x85, 0x2c, 0xd3, 0x5e, 0xb5, 0x5e, 0x59, + 0xa5, 0x24, 0x23, 0xdb, 0x0b, 0xf1, 0x4c, 0xbe, 0xd0, 0xc4, 0x5a, 0xa4, 0x40, 0x52, 0x0a, 0x7d, + 0xee, 0xad, 0x28, 0xd0, 0x1e, 0x73, 0xcc, 0xb9, 0xbd, 0xf4, 0xd0, 0x0f, 0xb1, 0xc7, 0x2d, 0x7a, + 0x29, 0xd0, 0x1e, 0x8a, 0xe4, 0xd0, 0x02, 0xbd, 0xf5, 0x13, 0x14, 0xef, 0x0f, 0x45, 0x52, 0x96, + 0xb2, 0x29, 0x7a, 0x28, 0xb0, 0x97, 0xf8, 0xcd, 0xbc, 0x79, 0xf3, 0x7e, 0x33, 0xbf, 0x99, 0x79, + 0x8c, 0x40, 0x99, 0x91, 0x90, 0x18, 0xb3, 0xc0, 0xf5, 0x0e, 0xe7, 0x9f, 0x1c, 0x06, 0x37, 0x53, + 0xe2, 0x1f, 0x4c, 0x3d, 0x37, 0x70, 0xd1, 0xe6, 0x62, 0xe7, 0x60, 0xfe, 0xc9, 0xc3, 0x86, 0xe5, + 0x5a, 0x2e, 0xdb, 0x38, 0xa4, 0x2b, 0x6e, 0xf3, 0xb0, 0x86, 0x27, 0xb6, 0xe3, 0x1e, 0xb2, 0x7f, + 0xb9, 0xaa, 0x75, 0x02, 0x85, 0x01, 0xf6, 0xf0, 0xc4, 0x47, 0xdb, 0x00, 0xbe, 0x3b, 0x21, 0xfa, + 0x1c, 0x5f, 0xcf, 0x88, 0x92, 0xd9, 0x95, 0xf6, 0x4a, 0x5a, 0x99, 0x6a, 0x2e, 0xa8, 0xa2, 0xbd, + 0xfd, 0xea, 0xf5, 0xce, 0xc6, 0x3f, 0x5f, 0xef, 0x48, 0xbf, 0xfa, 0xc7, 0x1f, 0xf6, 0xe5, 0x18, + 0xc6, 0x94, 0x9d, 0x6e, 0xfd, 0x35, 0x03, 0xf2, 0xd8, 0xb1, 0xe7, 0xc4, 0xf3, 0xf1, 0xf5, 0x00, + 0xdf, 0x5c, 0xbb, 0xd8, 0x44, 0x5b, 0x90, 0x09, 0x5c, 0x45, 0xda, 0x95, 0xf6, 0xca, 0x5a, 0x26, + 0x70, 0x51, 0x03, 0xf2, 0xb1, 0xf7, 0xb2, 0xc6, 0x05, 0x84, 0x20, 0x67, 0xe2, 0x00, 0x2b, 0x59, + 0xa6, 0x64, 0x6b, 0xf4, 0x08, 0xca, 0x16, 0xf6, 0xf5, 0x6b, 0x7b, 0x62, 0x07, 0x4a, 0x8e, 0x6d, + 0x94, 0x2c, 0xec, 0x9f, 0x51, 0x19, 0x7d, 0x0c, 0xd5, 0x09, 0x0e, 0xf5, 0x17, 0x84, 0xe8, 0x53, + 0xe2, 0xe9, 0x16, 0xf6, 0x95, 0x3c, 0x33, 0xd9, 0x9c, 0xe0, 0xf0, 0x84, 0x90, 0x01, 0xf1, 0x4e, + 0xb1, 0x8f, 0x3e, 0x05, 0x85, 0x9a, 0x4d, 0x3d, 0xdb, 0xf5, 0xec, 0xe0, 0x26, 0x65, 0x5f, 0x60, + 0xf6, 0x8d, 0x09, 0x0e, 0x07, 0x62, 0x3b, 0x3e, 0xd7, 0x80, 0xbc, 0xe3, 0x3a, 0x06, 0x51, 0x8a, + 0x1c, 0x25, 0x13, 0xd0, 0x43, 0x28, 0x99, 0x04, 0x9b, 0xd7, 0xb6, 0x43, 0x94, 0x12, 0x07, 0x14, + 0xc9, 0xe8, 0x87, 0x50, 0x98, 0xeb, 0x94, 0x0c, 0xa5, 0xbc, 0x2b, 0xed, 0x6d, 0x3d, 0x6b, 0x1e, + 0x24, 0xc9, 0x38, 0xb8, 0x20, 0x9e, 0xfd, 0xc2, 0x36, 0x70, 0x60, 0xbb, 0xce, 0xe8, 0x66, 0x4a, + 0xb4, 0xfc, 0x9c, 0xfe, 0x69, 0xef, 0x25, 0x53, 0xfa, 0x28, 0x4e, 0xe9, 0x2c, 0xca, 0xa3, 0x3e, + 0xe5, 0x89, 0x6c, 0xfd, 0x5a, 0x02, 0xf9, 0x73, 0xdb, 0xf2, 0x98, 0x8b, 0x28, 0xbb, 0x1f, 0x40, + 0x79, 0x12, 0xe9, 0x44, 0x92, 0x63, 0x45, 0x1c, 0x45, 0x66, 0x5d, 0x14, 0xd9, 0x74, 0x14, 0x6b, + 0xe1, 0x2c, 0x7c, 0x2e, 0xe0, 0xbc, 0x92, 0x00, 0x2d, 0xc8, 0xee, 0x18, 0x86, 0x3b, 0x73, 0x82, + 0x9e, 0x89, 0x9e, 0x40, 0xd5, 0xb8, 0xc2, 0xb6, 0xa3, 0x3b, 0x78, 0x42, 0xfc, 0x29, 0x36, 0x88, + 0x80, 0xb5, 0xc5, 0xd4, 0xfd, 0x48, 0x8b, 0x1e, 0x40, 0x89, 0x1b, 0xda, 0xa6, 0x80, 0x57, 0x64, + 0x72, 0xcf, 0xa4, 0xb0, 0xdd, 0x97, 0x0e, 0xf1, 0x04, 0x3a, 0x2e, 0xbc, 0x47, 0xa6, 0x30, 0x47, + 0xd1, 0x32, 0x00, 0x69, 0x64, 0x4e, 0xbc, 0xa0, 0xe7, 0xf8, 0x81, 0x37, 0x33, 0x28, 0x6e, 0x1f, + 0x7d, 0x0c, 0x5b, 0x2f, 0x66, 0x8e, 0xa9, 0x7b, 0xc4, 0xb0, 0xa7, 0x36, 0x71, 0x02, 0x01, 0xec, + 0x0e, 0xd5, 0x6a, 0x91, 0xb2, 0xfd, 0x9d, 0xe8, 0x8a, 0xed, 0xf8, 0x0a, 0x8f, 0x79, 0xd3, 0xed, + 0x84, 0xbb, 0xd6, 0xbf, 0xb2, 0x50, 0xec, 0x39, 0x97, 0xee, 0xcc, 0x31, 0xd1, 0x63, 0xd8, 0xf4, + 0xdd, 0x99, 0x67, 0x10, 0x9d, 0x85, 0x20, 0x1c, 0x57, 0xb8, 0xae, 0x4b, 0x55, 0xe8, 0x3e, 0x14, + 0x83, 0x50, 0xbf, 0xc2, 0xfe, 0x95, 0x88, 0xb6, 0x10, 0x84, 0x9f, 0x61, 0xff, 0x0a, 0xdd, 0x83, + 0x82, 0x4f, 0x1c, 0x73, 0x11, 0xad, 0x90, 0x28, 0xb3, 0x31, 0x52, 0x5e, 0xfd, 0xb1, 0x82, 0x9e, + 0xc2, 0x13, 0x1a, 0xac, 0xa8, 0x7a, 0x21, 0xd1, 0x06, 0xc6, 0xbe, 0x4f, 0x02, 0x1d, 0x9b, 0xa6, + 0x27, 0x2a, 0xbc, 0xcc, 0x34, 0x1d, 0xd3, 0xf4, 0x68, 0x4b, 0x5d, 0xbb, 0x96, 0x6e, 0x3b, 0x26, + 0x09, 0x45, 0x69, 0x97, 0xae, 0x5d, 0xab, 0x47, 0x65, 0xf4, 0x94, 0x41, 0x64, 0x25, 0x5c, 0x62, + 0x25, 0xdc, 0x48, 0x97, 0xf0, 0x28, 0x64, 0x85, 0x5b, 0x08, 0xd8, 0x5f, 0xf4, 0x33, 0xa8, 0xdd, + 0x2a, 0x52, 0x56, 0xfb, 0x95, 0xe5, 0xda, 0x5f, 0x9e, 0x09, 0x9a, 0x3c, 0x5b, 0x9e, 0x12, 0xdf, + 0x85, 0xda, 0x3c, 0xd1, 0x21, 0x3a, 0x1b, 0x06, 0xc0, 0x00, 0xca, 0xc9, 0x8d, 0x63, 0x3a, 0x18, + 0x7e, 0x0e, 0xf5, 0x15, 0x8c, 0x28, 0x15, 0x76, 0xf7, 0x6e, 0xfa, 0xee, 0xdb, 0x85, 0xa0, 0x21, + 0xef, 0x76, 0x71, 0x34, 0x20, 0x6f, 0xfb, 0x5d, 0xb5, 0xa3, 0x6c, 0xb2, 0x99, 0xc7, 0x85, 0x76, + 0x29, 0x2a, 0xb9, 0xd6, 0x57, 0x12, 0xe4, 0x06, 0xdd, 0x51, 0x98, 0xe4, 0x51, 0x5a, 0xc3, 0x63, + 0x26, 0xc5, 0xe3, 0x03, 0xa0, 0x43, 0x4b, 0x9f, 0xf9, 0xc4, 0x64, 0x0c, 0xe7, 0xb4, 0xa2, 0x85, + 0xfd, 0xb1, 0x4f, 0x58, 0xd9, 0x5c, 0x5e, 0xbb, 0xc6, 0x97, 0xfa, 0x15, 0xb1, 0xad, 0x2b, 0xce, + 0x72, 0x4e, 0xab, 0x30, 0xdd, 0x67, 0x4c, 0xc5, 0xbc, 0x06, 0x38, 0x98, 0x45, 0xd3, 0x4a, 0x48, + 0x94, 0x48, 0xe2, 0x79, 0xae, 0xa7, 0x4f, 0x7c, 0x2b, 0x22, 0x92, 0x29, 0x3e, 0xf7, 0xad, 0xf6, + 0x07, 0xc9, 0x4e, 0xa9, 0x26, 0xc6, 0xb4, 0xa1, 0x07, 0x61, 0xeb, 0xcf, 0x12, 0xd4, 0xcf, 0x67, + 0x01, 0xab, 0xdc, 0xf3, 0x4b, 0x9f, 0x78, 0x73, 0x3e, 0x2c, 0x14, 0x28, 0xfa, 0x33, 0xc3, 0x20, + 0xbe, 0xcf, 0x22, 0x2b, 0x69, 0x91, 0x78, 0x0b, 0x67, 0xe6, 0x36, 0xce, 0x44, 0x5a, 0xb2, 0xa9, + 0xb4, 0xa4, 0x80, 0xe6, 0xd2, 0x40, 0xd1, 0x2e, 0x6c, 0xd2, 0xdc, 0xd0, 0xa1, 0xcc, 0xf2, 0xc3, + 0x6b, 0x19, 0x2c, 0xec, 0x9f, 0x10, 0x42, 0x53, 0xd4, 0x7e, 0x12, 0x85, 0xd1, 0x8c, 0xc3, 0x70, + 0x05, 0x78, 0xdd, 0x8d, 0xd1, 0xb7, 0x26, 0x50, 0x3d, 0xf7, 0x6c, 0xcb, 0x76, 0x70, 0x60, 0x3b, + 0xd6, 0xc0, 0x78, 0x17, 0x55, 0xa9, 0x2e, 0xc8, 0xa4, 0xbb, 0xa0, 0xfd, 0xd1, 0x8a, 0x11, 0xe3, + 0xc6, 0x9e, 0x75, 0x9e, 0xc4, 0x7f, 0x17, 0x00, 0xa2, 0x24, 0x8e, 0x42, 0x5a, 0xbe, 0x26, 0xf1, + 0x03, 0x66, 0xe3, 0x3a, 0xa9, 0x29, 0x20, 0x27, 0x36, 0xf8, 0x28, 0x48, 0x75, 0x76, 0x66, 0x7d, + 0x67, 0x67, 0x53, 0x9d, 0x7d, 0x00, 0x75, 0x12, 0x06, 0xc4, 0x73, 0xe8, 0xa0, 0x8b, 0x5b, 0x9c, + 0xa7, 0xb4, 0x16, 0x6d, 0x75, 0x16, 0xad, 0xbe, 0x07, 0xf2, 0xd4, 0x33, 0x9e, 0x7d, 0x2f, 0x69, + 0xcc, 0xf3, 0xbb, 0xc5, 0xf4, 0xb1, 0x65, 0x5c, 0xb9, 0x85, 0x54, 0xe5, 0x2a, 0x50, 0x8c, 0xda, + 0x9a, 0x57, 0x58, 0x24, 0xa6, 0x5f, 0xe6, 0xd2, 0xd2, 0xcb, 0x9c, 0x18, 0x23, 0xe5, 0xf7, 0x18, + 0x23, 0xcf, 0x20, 0xcf, 0x52, 0xca, 0xba, 0xbd, 0xf2, 0x6c, 0x3b, 0x6d, 0xbc, 0xc4, 0xa9, 0x96, + 0x9b, 0x52, 0x66, 0x8f, 0xa0, 0xc2, 0xb9, 0x27, 0x26, 0x3d, 0xc9, 0x1b, 0xff, 0xf1, 0xd2, 0xc9, + 0xdb, 0x25, 0xae, 0x41, 0x74, 0x6a, 0x14, 0xd2, 0xef, 0x12, 0xdb, 0x64, 0xed, 0x5e, 0xd6, 0x32, + 0xb6, 0x89, 0x7e, 0x0c, 0xd5, 0x45, 0x61, 0x89, 0x96, 0xbb, 0xb3, 0x0a, 0xfe, 0x90, 0xed, 0x69, + 0x5b, 0x91, 0x31, 0x97, 0xd7, 0xcd, 0xa4, 0xad, 0xff, 0x61, 0x26, 0x1d, 0x41, 0x7d, 0x6a, 0xe8, + 0xc2, 0x2b, 0x3f, 0x4f, 0x5f, 0xf9, 0x2a, 0x73, 0x89, 0xd2, 0x2e, 0xe9, 0x6c, 0xd2, 0x6a, 0x53, + 0x83, 0xbb, 0x56, 0x23, 0xe3, 0x88, 0xa9, 0xa9, 0x67, 0x1b, 0x44, 0x91, 0x17, 0x4c, 0x0d, 0xa8, + 0x4c, 0x1b, 0x44, 0xb4, 0x9f, 0x52, 0xe3, 0xcc, 0xf3, 0xce, 0x5b, 0xdc, 0xcc, 0xde, 0xcb, 0xf8, + 0x66, 0xf4, 0xee, 0x9b, 0xa9, 0x75, 0x7c, 0xf3, 0x3e, 0xd4, 0x84, 0x03, 0xff, 0x25, 0x9e, 0xea, + 0xac, 0xe7, 0x95, 0x3a, 0xbb, 0xa6, 0xca, 0x37, 0x86, 0x2f, 0xf1, 0x54, 0xa5, 0xea, 0x08, 0x65, + 0xe0, 0x7e, 0x49, 0x1c, 0xa5, 0xb1, 0x40, 0x39, 0xa2, 0x72, 0x62, 0x08, 0xff, 0x4d, 0x82, 0xca, + 0xe2, 0x2d, 0x59, 0x50, 0x28, 0x2d, 0x28, 0xfc, 0x01, 0x80, 0xcd, 0x5f, 0x64, 0x5a, 0x15, 0x19, + 0x86, 0xf6, 0x6e, 0x1a, 0xad, 0x78, 0xb1, 0xb5, 0xb2, 0x30, 0x1c, 0x85, 0xe8, 0x49, 0x54, 0x80, + 0xd9, 0xdd, 0xec, 0x9a, 0xf0, 0x78, 0xd5, 0xfd, 0x08, 0x2a, 0x8b, 0x0a, 0x09, 0x42, 0x25, 0xc7, + 0xcc, 0x95, 0xd5, 0x55, 0x37, 0x0a, 0x35, 0x70, 0x17, 0xeb, 0xf6, 0x87, 0xc9, 0x89, 0x7c, 0x6f, + 0xd5, 0xb7, 0x4b, 0x10, 0xb6, 0x7e, 0x9f, 0x85, 0x3b, 0x02, 0xdf, 0x19, 0xb1, 0xb0, 0x71, 0xf3, + 0x2d, 0xf9, 0xae, 0x68, 0x2f, 0x7f, 0x57, 0x3c, 0x5e, 0xc9, 0x09, 0x9f, 0x0b, 0x3c, 0xf2, 0xff, + 0xff, 0x47, 0x46, 0xbb, 0xf9, 0xea, 0xf5, 0x8e, 0x14, 0x51, 0x56, 0x8b, 0x29, 0x13, 0x85, 0xd3, + 0xfa, 0x93, 0x04, 0x72, 0xcc, 0xb6, 0x20, 0xec, 0xbf, 0x7a, 0x07, 0xd6, 0x52, 0x97, 0xa2, 0x28, + 0xbb, 0x9e, 0xa2, 0xdc, 0x3b, 0x28, 0xca, 0x2f, 0x51, 0xd4, 0x6e, 0x25, 0xe3, 0xb9, 0xbb, 0xe2, + 0x35, 0x0d, 0xc2, 0xd6, 0xef, 0x32, 0x50, 0x4b, 0x34, 0x98, 0x08, 0xaa, 0x9d, 0x6a, 0x2b, 0x89, + 0x25, 0xff, 0xd1, 0x4a, 0x0a, 0x05, 0x79, 0xab, 0x9a, 0x2b, 0xf3, 0x0d, 0xcd, 0xf5, 0x93, 0x74, + 0x73, 0x65, 0x57, 0x51, 0xbc, 0x9c, 0xee, 0x64, 0x8b, 0xa1, 0x9f, 0x42, 0x4c, 0x78, 0x34, 0xc0, + 0x73, 0xac, 0xdc, 0x76, 0xd6, 0x14, 0xca, 0x28, 0x14, 0xb3, 0xbc, 0xba, 0x38, 0xc8, 0x15, 0xac, + 0x5d, 0xa5, 0x6f, 0x68, 0xd7, 0xfd, 0x53, 0x90, 0x97, 0xff, 0x53, 0x87, 0xee, 0x01, 0xf2, 0x6d, + 0xcb, 0x21, 0x66, 0x72, 0x47, 0xde, 0x40, 0x8f, 0xe0, 0xfe, 0x2c, 0xbe, 0x36, 0xb5, 0x29, 0xed, + 0xff, 0x32, 0x9d, 0x75, 0xf1, 0xa0, 0x7c, 0x08, 0x3b, 0xe3, 0x7e, 0xef, 0x42, 0xd5, 0x86, 0x9d, + 0x33, 0x7d, 0xf4, 0x5c, 0x1f, 0x8e, 0x3a, 0xa3, 0xf1, 0x50, 0x1f, 0xf7, 0x87, 0x03, 0xb5, 0xdb, + 0x3b, 0xe9, 0xa9, 0xc7, 0xf2, 0x06, 0xaa, 0x43, 0xb5, 0xd7, 0x3f, 0x3a, 0x1f, 0xf7, 0x8f, 0xf5, + 0xe1, 0xb8, 0xdb, 0x55, 0x87, 0x43, 0x59, 0x42, 0xdb, 0xf0, 0x60, 0xa0, 0xf6, 0x8f, 0x7b, 0xfd, + 0x53, 0x3d, 0xda, 0x54, 0x9f, 0xab, 0xdd, 0xf1, 0xa8, 0x77, 0xde, 0x97, 0x33, 0xe8, 0x3e, 0xd4, + 0x07, 0x5d, 0xa1, 0x51, 0xe3, 0x73, 0x59, 0x0a, 0x3e, 0xb9, 0x71, 0xd2, 0xe9, 0x9d, 0xa9, 0xc7, + 0x72, 0x0e, 0xdd, 0x85, 0xda, 0xa0, 0xab, 0x47, 0x2e, 0x35, 0xf5, 0x42, 0xd5, 0x46, 0x72, 0x1e, + 0x35, 0x40, 0x3e, 0x1f, 0x8f, 0xb8, 0x7f, 0xb1, 0x29, 0x17, 0x52, 0xda, 0xc8, 0x75, 0x91, 0xe2, + 0x5c, 0x68, 0x85, 0xdf, 0x12, 0xda, 0x84, 0x52, 0xb7, 0xd3, 0xef, 0xaa, 0x54, 0x2a, 0xef, 0x1f, + 0x41, 0x41, 0x44, 0x5e, 0x85, 0x4a, 0x3a, 0xca, 0x0a, 0x14, 0xa3, 0x0b, 0x24, 0x7a, 0xea, 0xfc, + 0x68, 0xa8, 0x6a, 0x17, 0xea, 0xb1, 0x9c, 0xa1, 0x12, 0x07, 0xa4, 0x1e, 0xcb, 0xd9, 0xfd, 0xdf, + 0x48, 0x50, 0xe0, 0x63, 0x04, 0x21, 0xd8, 0x4a, 0x38, 0xd1, 0x47, 0xcf, 0xe5, 0x0d, 0x54, 0x84, + 0xec, 0x69, 0x87, 0x66, 0xa8, 0x0e, 0xd5, 0xd3, 0xce, 0x50, 0xef, 0x50, 0xe4, 0x9d, 0x2f, 0xce, + 0xce, 0x3b, 0xd4, 0x55, 0x19, 0xf2, 0x27, 0xe3, 0xfe, 0x31, 0xcd, 0xc4, 0x5d, 0xa8, 0xb1, 0x65, + 0xca, 0x22, 0xc7, 0x70, 0x08, 0x21, 0x4f, 0x2f, 0x88, 0xb2, 0x2b, 0x52, 0x52, 0x40, 0x32, 0x6c, + 0x6a, 0xea, 0xb0, 0x3b, 0x56, 0x75, 0xee, 0xa9, 0xb8, 0xff, 0x47, 0x09, 0xea, 0x2b, 0xe6, 0x1b, + 0x7a, 0x0c, 0xdb, 0xd1, 0xe9, 0x33, 0xf5, 0xb4, 0xd3, 0xfd, 0x42, 0xbf, 0x85, 0xf6, 0x1e, 0xa0, + 0x25, 0x13, 0x0e, 0x5e, 0x81, 0xc6, 0x92, 0x9e, 0x5f, 0x96, 0x41, 0x1f, 0xc1, 0xee, 0xaa, 0x9d, + 0x54, 0x14, 0x59, 0xd4, 0x82, 0xe6, 0x6d, 0xbf, 0xe9, 0x48, 0x8f, 0x06, 0x5f, 0xbd, 0x69, 0x4a, + 0x5f, 0xbf, 0x69, 0x4a, 0x7f, 0x7f, 0xd3, 0x94, 0x7e, 0xfb, 0xb6, 0xb9, 0xf1, 0xf5, 0xdb, 0xe6, + 0xc6, 0x5f, 0xde, 0x36, 0x37, 0x7e, 0xf1, 0xa9, 0x65, 0x07, 0x57, 0xb3, 0xcb, 0x03, 0xc3, 0x9d, + 0x1c, 0x4e, 0x67, 0xfe, 0x15, 0x1b, 0x71, 0x6c, 0xf5, 0x94, 0x2d, 0x9f, 0x3a, 0xae, 0x49, 0x0e, + 0xc3, 0xc3, 0xb8, 0x69, 0xd8, 0x0f, 0x54, 0x97, 0x05, 0xf6, 0x53, 0xd3, 0xf7, 0xff, 0x13, 0x00, + 0x00, 0xff, 0xff, 0x08, 0xef, 0x51, 0x5f, 0xbd, 0x12, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -1764,6 +1813,9 @@ func (this *OutboundObservation) Equal(that interface{}) bool { if this.ErrorMsg != that1.ErrorMsg { return false } + if this.GasFeeUsed != that1.GasFeeUsed { + return false + } return true } func (this *OriginatingPcTx) Equal(that interface{}) bool { @@ -1857,6 +1909,21 @@ func (this *OutboundTx) Equal(that interface{}) bool { if !this.PcRevertExecution.Equal(that1.PcRevertExecution) { return false } + if this.GasPrice != that1.GasPrice { + return false + } + if this.GasFee != that1.GasFee { + return false + } + if !this.PcRefundExecution.Equal(that1.PcRefundExecution) { + return false + } + if this.RefundSwapError != that1.RefundSwapError { + return false + } + if this.GasToken != that1.GasToken { + return false + } return true } func (this *UniversalTx) Equal(that interface{}) bool { @@ -1900,9 +1967,6 @@ func (this *UniversalTx) Equal(that interface{}) bool { return false } } - if this.UniversalStatus != that1.UniversalStatus { - return false - } return true } func (this *InboundLegacy) Equal(that interface{}) bool { @@ -2464,6 +2528,13 @@ func (m *OutboundObservation) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.GasFeeUsed) > 0 { + i -= len(m.GasFeeUsed) + copy(dAtA[i:], m.GasFeeUsed) + i = encodeVarintTypes(dAtA, i, uint64(len(m.GasFeeUsed))) + i-- + dAtA[i] = 0x2a + } if len(m.ErrorMsg) > 0 { i -= len(m.ErrorMsg) copy(dAtA[i:], m.ErrorMsg) @@ -2553,6 +2624,56 @@ func (m *OutboundTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.GasToken) > 0 { + i -= len(m.GasToken) + copy(dAtA[i:], m.GasToken) + i = encodeVarintTypes(dAtA, i, uint64(len(m.GasToken))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa2 + } + if len(m.RefundSwapError) > 0 { + i -= len(m.RefundSwapError) + copy(dAtA[i:], m.RefundSwapError) + i = encodeVarintTypes(dAtA, i, uint64(len(m.RefundSwapError))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x9a + } + if m.PcRefundExecution != nil { + { + size, err := m.PcRefundExecution.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x92 + } + if len(m.GasFee) > 0 { + i -= len(m.GasFee) + copy(dAtA[i:], m.GasFee) + i = encodeVarintTypes(dAtA, i, uint64(len(m.GasFee))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + if len(m.GasPrice) > 0 { + i -= len(m.GasPrice) + copy(dAtA[i:], m.GasPrice) + i = encodeVarintTypes(dAtA, i, uint64(len(m.GasPrice))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } if m.PcRevertExecution != nil { { size, err := m.PcRevertExecution.MarshalToSizedBuffer(dAtA[:i]) @@ -2697,11 +2818,6 @@ func (m *UniversalTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.UniversalStatus != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.UniversalStatus)) - i-- - dAtA[i] = 0x28 - } if len(m.OutboundTx) > 0 { for iNdEx := len(m.OutboundTx) - 1; iNdEx >= 0; iNdEx-- { { @@ -3200,6 +3316,10 @@ func (m *OutboundObservation) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } + l = len(m.GasFeeUsed) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } return n } @@ -3284,6 +3404,26 @@ func (m *OutboundTx) Size() (n int) { l = m.PcRevertExecution.Size() n += 1 + l + sovTypes(uint64(l)) } + l = len(m.GasPrice) + if l > 0 { + n += 2 + l + sovTypes(uint64(l)) + } + l = len(m.GasFee) + if l > 0 { + n += 2 + l + sovTypes(uint64(l)) + } + if m.PcRefundExecution != nil { + l = m.PcRefundExecution.Size() + n += 2 + l + sovTypes(uint64(l)) + } + l = len(m.RefundSwapError) + if l > 0 { + n += 2 + l + sovTypes(uint64(l)) + } + l = len(m.GasToken) + if l > 0 { + n += 2 + l + sovTypes(uint64(l)) + } return n } @@ -3313,9 +3453,6 @@ func (m *UniversalTx) Size() (n int) { n += 1 + l + sovTypes(uint64(l)) } } - if m.UniversalStatus != 0 { - n += 1 + sovTypes(uint64(m.UniversalStatus)) - } return n } @@ -4962,6 +5099,38 @@ func (m *OutboundObservation) Unmarshal(dAtA []byte) error { } m.ErrorMsg = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GasFeeUsed", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + 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 ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GasFeeUsed = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -5596,6 +5765,170 @@ func (m *OutboundTx) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GasPrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + 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 ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GasPrice = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GasFee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + 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 ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GasFee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PcRefundExecution", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PcRefundExecution == nil { + m.PcRefundExecution = &PCTx{} + } + if err := m.PcRefundExecution.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RefundSwapError", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + 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 ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RefundSwapError = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GasToken", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + 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 ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GasToken = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -5782,25 +6115,6 @@ func (m *UniversalTx) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field UniversalStatus", wireType) - } - m.UniversalStatus = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.UniversalStatus |= UniversalTxStatus(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) diff --git a/x/uexecutor/types/universal_tx.go b/x/uexecutor/types/universal_tx.go index f25a38a5..683b6a81 100644 --- a/x/uexecutor/types/universal_tx.go +++ b/x/uexecutor/types/universal_tx.go @@ -52,10 +52,5 @@ func (p UniversalTx) ValidateBasic() error { } } - // Validate universal_status (must be a valid enum) - if _, ok := UniversalTxStatus_name[int32(p.UniversalStatus)]; !ok { - return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid universal_status: %v", p.UniversalStatus) - } - return nil } diff --git a/x/uexecutor/types/universal_tx_test.go b/x/uexecutor/types/universal_tx_test.go index 1c90beee..31ec83d7 100644 --- a/x/uexecutor/types/universal_tx_test.go +++ b/x/uexecutor/types/universal_tx_test.go @@ -48,7 +48,6 @@ func TestUniversalTx_ValidateBasic(t *testing.T) { OutboundStatus: types.Status_PENDING, }, }, - UniversalStatus: types.UniversalTxStatus_PC_EXECUTED_SUCCESS, } tests := []struct { @@ -96,16 +95,6 @@ func TestUniversalTx_ValidateBasic(t *testing.T) { expectError: true, errContains: "invalid outbound_tx", }, - { - name: "invalid universal_status", - universal: func() types.UniversalTx { - utx := validUniversal - utx.UniversalStatus = types.UniversalTxStatus(99) // not in enum - return utx - }(), - expectError: true, - errContains: "invalid universal_status", - }, } for _, tc := range tests {