From bb5747a568844162cd93d68b9ded59c8b73f5121 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 12:51:01 +0530 Subject: [PATCH 01/75] feat: added chain_meta proto changes --- proto/uexecutor/v1/chain_meta.proto | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 proto/uexecutor/v1/chain_meta.proto diff --git a/proto/uexecutor/v1/chain_meta.proto b/proto/uexecutor/v1/chain_meta.proto new file mode 100644 index 00000000..8a10ec03 --- /dev/null +++ b/proto/uexecutor/v1/chain_meta.proto @@ -0,0 +1,21 @@ +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 observed_ats = 5; // Timestamps when each observation was made + uint64 median_index = 6; // Index of the median price in 'prices' +} From cc4d8c66d809fdcea9cc8a128c22539c92cb7775 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 12:51:13 +0530 Subject: [PATCH 02/75] feat: added MsgVoteChainMeta proto changes --- proto/uexecutor/v1/tx.proto | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/proto/uexecutor/v1/tx.proto b/proto/uexecutor/v1/tx.proto index 7eb065aa..b8413f11 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,18 @@ 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 + uint64 observed_at = 5; // Timestamp when the observation was made (unix seconds) +} + +// MsgVoteChainMetaResponse defines the response for MsgVoteChainMeta +message MsgVoteChainMetaResponse {} From 7082f4e1ca15750e4697fd988a37228ec38bbb26 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 12:51:31 +0530 Subject: [PATCH 03/75] refactor: added generated protobuf --- api/uexecutor/v1/chain_meta.pulsar.go | 1338 ++++++++++++++++++++++ api/uexecutor/v1/tx.pulsar.go | 1467 ++++++++++++++++++++++--- api/uexecutor/v1/tx_grpc.pb.go | 39 + 3 files changed, 2677 insertions(+), 167 deletions(-) create mode 100644 api/uexecutor/v1/chain_meta.pulsar.go diff --git a/api/uexecutor/v1/chain_meta.pulsar.go b/api/uexecutor/v1/chain_meta.pulsar.go new file mode 100644 index 00000000..3bd7eff7 --- /dev/null +++ b/api/uexecutor/v1/chain_meta.pulsar.go @@ -0,0 +1,1338 @@ +// 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 ObservedAts 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_observed_ats protoreflect.FieldDescriptor + fd_ChainMeta_median_index 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_observed_ats = md_ChainMeta.Fields().ByName("observed_ats") + fd_ChainMeta_median_index = md_ChainMeta.Fields().ByName("median_index") +} + +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.ObservedAts) != 0 { + value := protoreflect.ValueOfList(&_ChainMeta_5_list{list: &x.ObservedAts}) + if !f(fd_ChainMeta_observed_ats, value) { + return + } + } + if x.MedianIndex != uint64(0) { + value := protoreflect.ValueOfUint64(x.MedianIndex) + if !f(fd_ChainMeta_median_index, 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.observed_ats": + return len(x.ObservedAts) != 0 + case "uexecutor.v1.ChainMeta.median_index": + return x.MedianIndex != 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.observed_ats": + x.ObservedAts = nil + case "uexecutor.v1.ChainMeta.median_index": + x.MedianIndex = 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.observed_ats": + if len(x.ObservedAts) == 0 { + return protoreflect.ValueOfList(&_ChainMeta_5_list{}) + } + listValue := &_ChainMeta_5_list{list: &x.ObservedAts} + return protoreflect.ValueOfList(listValue) + case "uexecutor.v1.ChainMeta.median_index": + value := x.MedianIndex + 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.observed_ats": + lv := value.List() + clv := lv.(*_ChainMeta_5_list) + x.ObservedAts = *clv.list + case "uexecutor.v1.ChainMeta.median_index": + x.MedianIndex = 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.observed_ats": + if x.ObservedAts == nil { + x.ObservedAts = []uint64{} + } + value := &_ChainMeta_5_list{list: &x.ObservedAts} + 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")) + 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.observed_ats": + list := []uint64{} + return protoreflect.ValueOfList(&_ChainMeta_5_list{list: &list}) + case "uexecutor.v1.ChainMeta.median_index": + 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.ObservedAts) > 0 { + l = 0 + for _, e := range x.ObservedAts { + 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.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.MedianIndex != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.MedianIndex)) + i-- + dAtA[i] = 0x30 + } + if len(x.ObservedAts) > 0 { + var pksize2 int + for _, num := range x.ObservedAts { + pksize2 += runtime.Sov(uint64(num)) + } + i -= pksize2 + j1 := i + for _, num := range x.ObservedAts { + 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.ObservedAts = append(x.ObservedAts, 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.ObservedAts) == 0 { + x.ObservedAts = 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.ObservedAts = append(x.ObservedAts, v) + } + } else { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ObservedAts", 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 + } + } + 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 + ObservedAts []uint64 `protobuf:"varint,5,rep,packed,name=observed_ats,json=observedAts,proto3" json:"observed_ats,omitempty"` // Timestamps when each observation was made + MedianIndex uint64 `protobuf:"varint,6,opt,name=median_index,json=medianIndex,proto3" json:"median_index,omitempty"` // Index of the median price in 'prices' +} + +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) GetObservedAts() []uint64 { + if x != nil { + return x.ObservedAts + } + return nil +} + +func (x *ChainMeta) GetMedianIndex() uint64 { + if x != nil { + return x.MedianIndex + } + 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, 0xf7, 0x01, 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, 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0b, 0x6f, + 0x62, 0x73, 0x65, 0x72, 0x76, 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, 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/tx.pulsar.go b/api/uexecutor/v1/tx.pulsar.go index 619f27bd..2a936b32 100644 --- a/api/uexecutor/v1/tx.pulsar.go +++ b/api/uexecutor/v1/tx.pulsar.go @@ -5641,6 +5641,990 @@ 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 + fd_MsgVoteChainMeta_observed_at 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") + fd_MsgVoteChainMeta_observed_at = md_MsgVoteChainMeta.Fields().ByName("observed_at") +} + +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 + } + } + if x.ObservedAt != uint64(0) { + value := protoreflect.ValueOfUint64(x.ObservedAt) + if !f(fd_MsgVoteChainMeta_observed_at, 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) + case "uexecutor.v1.MsgVoteChainMeta.observed_at": + return x.ObservedAt != 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) + case "uexecutor.v1.MsgVoteChainMeta.observed_at": + x.ObservedAt = 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) + case "uexecutor.v1.MsgVoteChainMeta.observed_at": + value := x.ObservedAt + 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() + case "uexecutor.v1.MsgVoteChainMeta.observed_at": + x.ObservedAt = 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")) + case "uexecutor.v1.MsgVoteChainMeta.observed_at": + panic(fmt.Errorf("field observed_at 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)) + case "uexecutor.v1.MsgVoteChainMeta.observed_at": + 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.ObservedAt != 0 { + n += 1 + runtime.Sov(uint64(x.ObservedAt)) + } + 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.ObservedAt != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.ObservedAt)) + i-- + dAtA[i] = 0x28 + } + 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 + } + } + case 5: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ObservedAt", wireType) + } + x.ObservedAt = 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.ObservedAt |= 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 +7147,101 @@ 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 + ObservedAt uint64 `protobuf:"varint,5,opt,name=observed_at,json=observedAt,proto3" json:"observed_at,omitempty"` // Timestamp when the observation was made (unix seconds) +} + +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 +} + +func (x *MsgVoteChainMeta) GetObservedAt() uint64 { + if x != nil { + return x.ObservedAt + } + 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 +7251,177 @@ 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, - 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, + 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, 0xf6, 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, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x6f, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x64, 0x41, 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, 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 +7436,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 +7450,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 +7494,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 +7640,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 +7671,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", From 166f9697280508e6dceb59f6868d031c92475f77 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 12:53:57 +0530 Subject: [PATCH 04/75] feat: added chain_meta keys and keeper storage --- x/uexecutor/keeper/keeper.go | 11 +++++++++++ x/uexecutor/types/keys.go | 3 +++ 2 files changed, 14 insertions(+) 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/types/keys.go b/x/uexecutor/types/keys.go index d2c7c880..cc8ced32 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 ( From ddaefd00b6d01d04c4444bb8925b860e36cdeb6a Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 12:55:36 +0530 Subject: [PATCH 05/75] feat: added vote_chain_meta types --- x/uexecutor/types/chain_meta.go | 19 +++++++++ x/uexecutor/types/msg_vote_chain_meta.go | 50 ++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 x/uexecutor/types/chain_meta.go create mode 100644 x/uexecutor/types/msg_vote_chain_meta.go 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/msg_vote_chain_meta.go b/x/uexecutor/types/msg_vote_chain_meta.go new file mode 100644 index 00000000..ef7f9fb6 --- /dev/null +++ b/x/uexecutor/types/msg_vote_chain_meta.go @@ -0,0 +1,50 @@ +package types + +import ( + "cosmossdk.io/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, observedAt uint64, +) *MsgVoteChainMeta { + return &MsgVoteChainMeta{ + Signer: sender.String(), + ObservedChainId: observedChainId, + Price: price, + ChainHeight: chainHeight, + ObservedAt: observedAt, + } +} + +// 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") + } + return nil +} From 1fddca9c0cdcee541b71a1e46a87d9272fb1cd8a Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 12:56:37 +0530 Subject: [PATCH 06/75] feat: added helper method in evm to update chain meta in UniversalCore --- x/uexecutor/keeper/evm.go | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/x/uexecutor/keeper/evm.go b/x/uexecutor/keeper/evm.go index 292de1e7..956ba68f 100644 --- a/x/uexecutor/keeper/evm.go +++ b/x/uexecutor/keeper/evm.go @@ -316,6 +316,51 @@ func (k Keeper) CallUniversalCoreSetGasPrice( ) } +// Calls UniversalCore Contract to set chain metadata (gas price + chain height + observed timestamp) +func (k Keeper) CallUniversalCoreSetChainMeta( + ctx sdk.Context, + chainNamespace string, + price *big.Int, + chainHeight *big.Int, + observedAt *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, + observedAt, + ) +} + // Calls Handler Contract to deposit prc20 tokens func (k Keeper) CallPRC20DepositAutoSwap( ctx sdk.Context, From b97e4ce937f6d34bf8f6da9ffeeb34d5145880f3 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 15:42:08 +0530 Subject: [PATCH 07/75] feat: added validation in vote_chain_meta types --- x/uexecutor/types/msg_vote_chain_meta.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/x/uexecutor/types/msg_vote_chain_meta.go b/x/uexecutor/types/msg_vote_chain_meta.go index ef7f9fb6..775fea99 100644 --- a/x/uexecutor/types/msg_vote_chain_meta.go +++ b/x/uexecutor/types/msg_vote_chain_meta.go @@ -2,6 +2,7 @@ package types import ( "cosmossdk.io/errors" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -46,5 +47,14 @@ 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 } From 47fd82ebbd0b20dd2604af1d24b7c8a46edc7307 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:07:51 +0530 Subject: [PATCH 08/75] feat: added changes in abi for chain meta changes --- x/uexecutor/types/abi.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/x/uexecutor/types/abi.go b/x/uexecutor/types/abi.go index 05a652a6..c484d446 100644 --- a/x/uexecutor/types/abi.go +++ b/x/uexecutor/types/abi.go @@ -299,6 +299,39 @@ 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" }, + { "name": "observedAt", "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" } ]` From a50a5373ebdf325667b84b50640d5a408a907dcb Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:10:05 +0530 Subject: [PATCH 09/75] feat: added implementation of voteChainMeta msg --- x/uexecutor/keeper/chain_meta.go | 134 +++++++++++++++++++++++++++++++ x/uexecutor/keeper/msg_server.go | 32 ++++++++ 2 files changed, 166 insertions(+) create mode 100644 x/uexecutor/keeper/chain_meta.go diff --git a/x/uexecutor/keeper/chain_meta.go b/x/uexecutor/keeper/chain_meta.go new file mode 100644 index 00000000..f64d8c2d --- /dev/null +++ b/x/uexecutor/keeper/chain_meta.go @@ -0,0 +1,134 @@ +package keeper + +import ( + "context" + "errors" + + "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" +) + +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 + observed timestamp). +// It accumulates votes, computes the median price, and calls setChainMeta on the UniversalCore contract. +func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAddress, observedChainId string, price, blockNumber, observedAt uint64) error { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + 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 + newEntry := types.ChainMeta{ + ObservedChainId: observedChainId, + Signers: []string{universalValidator.String()}, + Prices: []uint64{price}, + ChainHeights: []uint64{blockNumber}, + ObservedAts: []uint64{observedAt}, + MedianIndex: 0, + } + + if err := k.SetChainMeta(ctx, observedChainId, newEntry); err != nil { + return sdkerrors.Wrap(err, "failed to set initial chain meta entry") + } + + // EVM call with single price + priceBig := math.NewUint(price).BigInt() + chainHeightBig := math.NewUint(blockNumber).BigInt() + observedAtBig := math.NewUint(observedAt).BigInt() + if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, priceBig, chainHeightBig, observedAtBig); evmErr != nil { + // Non-fatal: log the error. The EVM call may fail if the contract hasn't been upgraded yet + // (old bytecode only has setGasPrice). State is still persisted. + sdkCtx.Logger().Error("VoteChainMeta: EVM setChainMeta call failed", "chain", observedChainId, "error", evmErr) + } + + return nil + } + + // 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.ObservedAts[i] = observedAt + 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.ObservedAts = append(entry.ObservedAts, observedAt) + } + + // Recompute median on price + medianIdx := computeMedianIndex(entry.Prices) + entry.MedianIndex = uint64(medianIdx) + + if err := k.SetChainMeta(ctx, observedChainId, entry); err != nil { + return sdkerrors.Wrap(err, "failed to set updated chain meta entry") + } + + medianPrice := math.NewUint(entry.Prices[medianIdx]).BigInt() + medianChainHeight := math.NewUint(entry.ChainHeights[medianIdx]).BigInt() + medianObservedAt := math.NewUint(entry.ObservedAts[medianIdx]).BigInt() + if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, medianPrice, medianChainHeight, medianObservedAt); evmErr != nil { + // Non-fatal: log. Same forward-compat reason as above. + sdkCtx.Logger().Error("VoteChainMeta: EVM setChainMeta call failed", "chain", observedChainId, "error", evmErr) + } + + return nil +} + +// 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; observedAts is set to 0 since the timestamp was not tracked before. +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 + } + + observedAts := make([]uint64, len(gp.Prices)) + // observedAts unknown at migration time — leave as 0 + + cm := types.ChainMeta{ + ObservedChainId: gp.ObservedChainId, + Signers: gp.Signers, + Prices: gp.Prices, + ChainHeights: gp.BlockNums, + ObservedAts: observedAts, + MedianIndex: gp.MedianIndex, + } + + if err := k.ChainMetas.Set(ctx, chainID, cm); err != nil { + return true, err + } + + return false, nil + }) +} diff --git a/x/uexecutor/keeper/msg_server.go b/x/uexecutor/keeper/msg_server.go index 5ef96f65..ce2d4f4c 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, msg.ObservedAt) + if err != nil { + return nil, err + } + return &types.MsgVoteChainMetaResponse{}, nil +} From f53cedfa49a32c5f2899efa73f10a9b6e929630c Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:10:30 +0530 Subject: [PATCH 10/75] refactor: added generated protobuf --- x/uexecutor/types/chain_meta.pb.go | 803 +++++++++++++++++++++++++++++ x/uexecutor/types/tx.pb.go | 598 +++++++++++++++++++-- 2 files changed, 1347 insertions(+), 54 deletions(-) create mode 100644 x/uexecutor/types/chain_meta.pb.go diff --git a/x/uexecutor/types/chain_meta.pb.go b/x/uexecutor/types/chain_meta.pb.go new file mode 100644 index 00000000..af8df41f --- /dev/null +++ b/x/uexecutor/types/chain_meta.pb.go @@ -0,0 +1,803 @@ +// 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"` + ObservedAts []uint64 `protobuf:"varint,5,rep,packed,name=observed_ats,json=observedAts,proto3" json:"observed_ats,omitempty"` + MedianIndex uint64 `protobuf:"varint,6,opt,name=median_index,json=medianIndex,proto3" json:"median_index,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) GetObservedAts() []uint64 { + if m != nil { + return m.ObservedAts + } + return nil +} + +func (m *ChainMeta) GetMedianIndex() uint64 { + if m != nil { + return m.MedianIndex + } + 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{ + // 324 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2d, 0x4d, 0xad, 0x48, + 0x4d, 0x2e, 0x2d, 0xc9, 0x2f, 0xd2, 0x2f, 0x33, 0xd4, 0x4f, 0xce, 0x48, 0xcc, 0xcc, 0x8b, 0xcf, + 0x4d, 0x2d, 0x49, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x81, 0x4b, 0xeb, 0x95, 0x19, + 0x4a, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x25, 0xf4, 0x41, 0x2c, 0x88, 0x1a, 0x29, 0xc1, 0xc4, + 0xdc, 0xcc, 0xbc, 0x7c, 0x7d, 0x30, 0x09, 0x11, 0x52, 0xfa, 0xce, 0xc8, 0xc5, 0xe9, 0x0c, 0x32, + 0xcb, 0x37, 0xb5, 0x24, 0x51, 0x48, 0x8b, 0x4b, 0x30, 0x3f, 0xa9, 0x38, 0xb5, 0xa8, 0x2c, 0x35, + 0x25, 0x1e, 0x62, 0x43, 0x66, 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3f, 0x4c, 0x02, + 0xac, 0xda, 0x33, 0x45, 0x48, 0x82, 0x8b, 0xbd, 0x38, 0x33, 0x3d, 0x2f, 0xb5, 0xa8, 0x58, 0x82, + 0x49, 0x81, 0x59, 0x83, 0x33, 0x08, 0xc6, 0x15, 0x12, 0xe3, 0x62, 0x2b, 0x28, 0xca, 0x4c, 0x4e, + 0x2d, 0x96, 0x60, 0x56, 0x60, 0xd6, 0x60, 0x09, 0x82, 0xf2, 0x84, 0x94, 0xb9, 0x78, 0x21, 0x86, + 0x66, 0xa4, 0x66, 0xa6, 0x67, 0x94, 0x14, 0x4b, 0xb0, 0x80, 0xa5, 0x79, 0xc0, 0x82, 0x1e, 0x10, + 0x31, 0x21, 0x45, 0x2e, 0x1e, 0xb8, 0x13, 0x12, 0x4b, 0x8a, 0x25, 0x58, 0xc1, 0x6a, 0xb8, 0x61, + 0x62, 0x8e, 0x10, 0x25, 0xb9, 0xa9, 0x29, 0x99, 0x89, 0x79, 0xf1, 0x99, 0x79, 0x29, 0xa9, 0x15, + 0x12, 0x6c, 0x0a, 0x8c, 0x20, 0x25, 0x10, 0x31, 0x4f, 0x90, 0x90, 0x95, 0xe2, 0x8c, 0x05, 0xf2, + 0x0c, 0x2f, 0x16, 0xc8, 0x33, 0x76, 0x3d, 0xdf, 0xa0, 0x25, 0x82, 0x08, 0x39, 0x44, 0xb0, 0x39, + 0x05, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, + 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x59, 0x7a, 0x66, 0x49, + 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x41, 0x69, 0x71, 0x06, 0x58, 0x13, 0x98, 0xa5, + 0x0b, 0x66, 0xea, 0xe6, 0xe5, 0xa7, 0xa4, 0xea, 0x57, 0xe8, 0x23, 0x8c, 0x2d, 0xa9, 0x2c, 0x48, + 0x2d, 0x4e, 0x62, 0x03, 0x07, 0xa9, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x91, 0x64, 0xde, 0x80, + 0xaa, 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.ObservedAts) != len(that1.ObservedAts) { + return false + } + for i := range this.ObservedAts { + if this.ObservedAts[i] != that1.ObservedAts[i] { + return false + } + } + if this.MedianIndex != that1.MedianIndex { + 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.MedianIndex != 0 { + i = encodeVarintChainMeta(dAtA, i, uint64(m.MedianIndex)) + i-- + dAtA[i] = 0x30 + } + if len(m.ObservedAts) > 0 { + dAtA2 := make([]byte, len(m.ObservedAts)*10) + var j1 int + for _, num := range m.ObservedAts { + 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.ObservedAts) > 0 { + l = 0 + for _, e := range m.ObservedAts { + l += sovChainMeta(uint64(e)) + } + n += 1 + sovChainMeta(uint64(l)) + l + } + if m.MedianIndex != 0 { + n += 1 + sovChainMeta(uint64(m.MedianIndex)) + } + 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.ObservedAts = append(m.ObservedAts, 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.ObservedAts) == 0 { + m.ObservedAts = 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.ObservedAts = append(m.ObservedAts, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field ObservedAts", 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 + } + } + 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/tx.pb.go b/x/uexecutor/types/tx.pb.go index 348a8d59..075e0d32 100644 --- a/x/uexecutor/types/tx.pb.go +++ b/x/uexecutor/types/tx.pb.go @@ -654,6 +654,120 @@ 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"` + ObservedAt uint64 `protobuf:"varint,5,opt,name=observed_at,json=observedAt,proto3" json:"observed_at,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 +} + +func (m *MsgVoteChainMeta) GetObservedAt() uint64 { + if m != nil { + return m.ObservedAt + } + 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 +781,72 @@ 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, + // 926 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0xae, 0xdb, 0xa4, 0xa8, 0x2f, 0xdd, 0xdd, 0xc6, 0xa4, 0xd4, 0x75, 0xb7, 0x69, 0x1b, 0x7e, + 0xec, 0x92, 0xa5, 0x31, 0x5b, 0xa4, 0x3d, 0xe4, 0xd6, 0xc2, 0x0a, 0x2a, 0x94, 0xdd, 0x62, 0x5a, + 0x90, 0xf6, 0x12, 0x4d, 0xec, 0xc1, 0xb1, 0xa8, 0x3d, 0x96, 0x67, 0x1c, 0xa5, 0x37, 0xc4, 0x91, + 0x13, 0x27, 0xfe, 0x07, 0xc4, 0xa5, 0x07, 0xfe, 0x00, 0x8e, 0x7b, 0x5c, 0xc1, 0x85, 0xd3, 0x0a, + 0xb5, 0x12, 0xfd, 0x0f, 0x38, 0x23, 0x8f, 0xed, 0xb1, 0xc7, 0xc9, 0xa6, 0xa8, 0x17, 0xf6, 0x12, + 0x39, 0xdf, 0xf7, 0xde, 0x97, 0xf7, 0x7d, 0xf6, 0x3c, 0x07, 0x56, 0x23, 0x3c, 0xc6, 0x56, 0xc4, + 0x48, 0x68, 0x8c, 0x1e, 0x1a, 0x6c, 0xdc, 0x09, 0x42, 0xc2, 0x88, 0xba, 0x2c, 0xe0, 0xce, 0xe8, + 0xa1, 0x5e, 0x47, 0x9e, 0xeb, 0x13, 0x83, 0x7f, 0x26, 0x05, 0xfa, 0x9a, 0x45, 0xa8, 0x47, 0xa8, + 0xe1, 0x51, 0x27, 0x6e, 0xf4, 0xa8, 0x93, 0x12, 0x9a, 0x2c, 0x78, 0x16, 0x60, 0x9a, 0x32, 0x9b, + 0x12, 0x63, 0x0d, 0x91, 0xeb, 0xf7, 0x3d, 0xcc, 0x50, 0x4a, 0x37, 0x1c, 0xe2, 0x10, 0x7e, 0x69, + 0xc4, 0x57, 0x29, 0xba, 0x9e, 0xfc, 0x4e, 0x3f, 0x21, 0x92, 0x2f, 0x09, 0xd5, 0xfa, 0x45, 0x81, + 0x3b, 0x3d, 0xea, 0x9c, 0x04, 0x36, 0x62, 0xf8, 0x08, 0x85, 0xc8, 0xa3, 0xea, 0x23, 0x58, 0x42, + 0x11, 0x1b, 0x92, 0xd0, 0x65, 0x67, 0x9a, 0xb2, 0xad, 0xdc, 0x5f, 0x3a, 0xd0, 0x7e, 0xff, 0x75, + 0xb7, 0x91, 0x36, 0xee, 0xdb, 0x76, 0x88, 0x29, 0xfd, 0x92, 0x85, 0xae, 0xef, 0x98, 0x79, 0xa9, + 0xba, 0x07, 0x8b, 0x01, 0x57, 0xd0, 0xe6, 0xb7, 0x95, 0xfb, 0xb5, 0xbd, 0x46, 0xa7, 0x18, 0x40, + 0x27, 0x51, 0x3f, 0xa8, 0x3c, 0x7f, 0xb9, 0x35, 0x67, 0xa6, 0x95, 0xdd, 0x0f, 0xbe, 0xbf, 0x3a, + 0x6f, 0xe7, 0x1a, 0x3f, 0x5c, 0x9d, 0xb7, 0xd7, 0x73, 0x8b, 0xa5, 0xc9, 0x5a, 0xeb, 0xb0, 0x56, + 0x82, 0x4c, 0x4c, 0x03, 0xe2, 0x53, 0xdc, 0xfa, 0x6d, 0x1e, 0xea, 0x3d, 0xea, 0x3c, 0xe6, 0xad, + 0xf8, 0x08, 0x9d, 0x9d, 0x12, 0x64, 0xab, 0x1f, 0xc2, 0x22, 0x75, 0x1d, 0x1f, 0x87, 0xd7, 0xfa, + 0x48, 0xeb, 0x54, 0x13, 0x1a, 0x91, 0xef, 0x8e, 0x70, 0x48, 0xd1, 0x69, 0x1f, 0x59, 0x16, 0x89, + 0x7c, 0xd6, 0x77, 0xed, 0xd4, 0xd2, 0xb6, 0x6c, 0xe9, 0x24, 0xab, 0xdc, 0x4f, 0x0a, 0x0f, 0x6d, + 0x53, 0x8d, 0x26, 0x30, 0xf5, 0x73, 0xa8, 0xe7, 0x9a, 0x41, 0x32, 0x9a, 0xb6, 0xc0, 0x05, 0x9b, + 0xaf, 0x10, 0x4c, 0x0d, 0x98, 0x2b, 0x51, 0x09, 0x51, 0x1f, 0x40, 0x7d, 0x84, 0x43, 0xf7, 0x1b, + 0xd7, 0x42, 0xcc, 0x25, 0x7e, 0xdf, 0x46, 0x0c, 0x69, 0x95, 0xd8, 0x9d, 0xb9, 0x52, 0x24, 0x3e, + 0x41, 0x0c, 0x75, 0x1f, 0xc4, 0xf1, 0xa6, 0xd6, 0xe2, 0x6c, 0x37, 0xa4, 0x6c, 0xe5, 0xb0, 0x5a, + 0x1b, 0xb0, 0x3e, 0x01, 0x8a, 0x7c, 0x7f, 0x9e, 0x87, 0x5b, 0x3d, 0xea, 0xf4, 0x5c, 0x27, 0x44, + 0x0c, 0x9f, 0x3c, 0xde, 0x7f, 0x7d, 0xb2, 0xf5, 0xf8, 0x4c, 0x71, 0x16, 0x33, 0xb3, 0xed, 0x65, + 0x65, 0x22, 0x5b, 0xaf, 0x84, 0xa8, 0x77, 0x61, 0x29, 0x1e, 0x15, 0xb1, 0x28, 0xc4, 0x69, 0xa6, + 0x39, 0xd0, 0xbd, 0x57, 0x0a, 0x73, 0x4d, 0x0a, 0x33, 0x4f, 0xa6, 0xb5, 0x06, 0xab, 0x12, 0x20, + 0x42, 0xfc, 0x49, 0x81, 0xdb, 0x3d, 0xea, 0x7c, 0x45, 0x18, 0x3e, 0xf4, 0x07, 0x24, 0xf2, 0x6f, + 0xf2, 0x84, 0x1a, 0xf0, 0x86, 0x9b, 0x34, 0xa7, 0xc1, 0xad, 0xca, 0x3e, 0x53, 0x65, 0x33, 0xab, + 0xea, 0xee, 0x94, 0xe6, 0xae, 0x47, 0xd8, 0x90, 0xa7, 0x68, 0x69, 0xf0, 0x96, 0x8c, 0x88, 0x91, + 0x5f, 0x26, 0x0b, 0x22, 0xa6, 0x9e, 0x46, 0xec, 0xa6, 0x33, 0xbf, 0x09, 0x55, 0x36, 0xce, 0x6e, + 0xf5, 0x92, 0x59, 0x61, 0xe3, 0x43, 0x5b, 0x5d, 0x85, 0xc5, 0x28, 0x41, 0x17, 0x38, 0x5a, 0x8d, + 0x38, 0x7c, 0x00, 0x35, 0x32, 0xa0, 0x38, 0x1c, 0x61, 0xbb, 0xcf, 0xc6, 0xfc, 0x36, 0xd4, 0xf6, + 0x76, 0x64, 0x8f, 0xd9, 0x28, 0x4f, 0x79, 0x21, 0xbf, 0x87, 0x26, 0x64, 0x5d, 0xc7, 0xe3, 0xee, + 0xfb, 0x25, 0xcb, 0xf2, 0x4e, 0x29, 0x9a, 0x49, 0x77, 0x4a, 0x11, 0x12, 0xde, 0xff, 0xc8, 0xbd, + 0x7f, 0x8a, 0xe8, 0x51, 0xe8, 0x5a, 0xf8, 0x06, 0xde, 0xdb, 0x50, 0x17, 0x7e, 0x92, 0x85, 0x2d, + 0x72, 0xb8, 0x93, 0x11, 0x1f, 0xc7, 0xf8, 0xa1, 0xad, 0x36, 0xa0, 0x1a, 0xc4, 0x3f, 0xc3, 0x13, + 0xa9, 0x98, 0xc9, 0x17, 0x75, 0x07, 0x96, 0x07, 0xa7, 0xc4, 0xfa, 0xb6, 0xef, 0x47, 0xde, 0x00, + 0x87, 0x3c, 0x92, 0x8a, 0x59, 0xe3, 0xd8, 0x13, 0x0e, 0xfd, 0x07, 0xc3, 0x99, 0x83, 0x82, 0xe1, + 0x0c, 0x12, 0x86, 0xff, 0x51, 0x60, 0x25, 0xe5, 0xf8, 0x44, 0x3d, 0xcc, 0xd0, 0xff, 0xe5, 0x38, + 0x69, 0x1c, 0x62, 0xd7, 0x19, 0xb2, 0xcc, 0x31, 0xc7, 0x3e, 0xe3, 0x90, 0xba, 0x55, 0x78, 0x4c, + 0x10, 0xd3, 0xaa, 0xbc, 0x42, 0x3c, 0x03, 0xfb, 0xac, 0xdb, 0x2e, 0x45, 0xa2, 0x4f, 0x44, 0x22, + 0x3c, 0xb6, 0x74, 0xd0, 0xca, 0x58, 0x16, 0xca, 0xde, 0xdf, 0x15, 0x58, 0xe8, 0x51, 0x47, 0x3d, + 0x86, 0x65, 0xe9, 0x35, 0xb9, 0x59, 0x5a, 0x2f, 0xf2, 0x8b, 0x49, 0x7f, 0x77, 0x26, 0x9d, 0xa9, + 0xab, 0xcf, 0xe0, 0x76, 0xe9, 0x9d, 0xb5, 0x35, 0xd1, 0x28, 0x17, 0xe8, 0xf7, 0xae, 0x29, 0x10, + 0xda, 0x4f, 0x00, 0x0a, 0xfb, 0x7a, 0x63, 0xa2, 0x2d, 0x27, 0xf5, 0xb7, 0x67, 0x90, 0x42, 0xef, + 0x0b, 0xa8, 0x15, 0x57, 0xd7, 0xdd, 0x89, 0x9e, 0x02, 0xab, 0xbf, 0x33, 0x8b, 0x15, 0x92, 0xc7, + 0xb0, 0x2c, 0xad, 0x96, 0xcd, 0xa9, 0x5d, 0x19, 0x3d, 0x25, 0xd4, 0x69, 0x07, 0x37, 0x53, 0x15, + 0x87, 0x76, 0xba, 0x6a, 0x46, 0xbf, 0x42, 0xb5, 0x7c, 0x3a, 0xd4, 0xaf, 0xe1, 0x96, 0x7c, 0x32, + 0x9a, 0x53, 0xfb, 0x04, 0xaf, 0xbf, 0x37, 0x9b, 0xcf, 0x84, 0xf5, 0xea, 0x77, 0x57, 0xe7, 0x6d, + 0xe5, 0xe0, 0xe8, 0xf9, 0x45, 0x53, 0x79, 0x71, 0xd1, 0x54, 0xfe, 0xba, 0x68, 0x2a, 0x3f, 0x5e, + 0x36, 0xe7, 0x5e, 0x5c, 0x36, 0xe7, 0xfe, 0xbc, 0x6c, 0xce, 0x3d, 0x7b, 0xe4, 0xb8, 0x6c, 0x18, + 0x0d, 0x3a, 0x16, 0xf1, 0x8c, 0x20, 0xa2, 0x43, 0x7e, 0x0e, 0xf8, 0xd5, 0x2e, 0xbf, 0xdc, 0xf5, + 0x89, 0x8d, 0x8d, 0xb1, 0x91, 0x3f, 0xe1, 0xfc, 0x3f, 0xe3, 0x60, 0x91, 0xff, 0xc9, 0xfb, 0xe8, + 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x21, 0xaa, 0x85, 0x4a, 0xa1, 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -754,6 +875,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 +941,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 +966,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 +992,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 +1108,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 +1154,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 +1608,81 @@ 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.ObservedAt != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ObservedAt)) + i-- + dAtA[i] = 0x28 + } + 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 +1878,41 @@ 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)) + } + if m.ObservedAt != 0 { + n += 1 + sovTx(uint64(m.ObservedAt)) + } + 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 +3158,227 @@ 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 + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ObservedAt", wireType) + } + m.ObservedAt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ObservedAt |= 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 From 246a7720c2ecd4c565cc103758d4506288018b3a Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:11:03 +0530 Subject: [PATCH 11/75] feat: added migration for uexecutor v4 -> v5 consensus --- x/uexecutor/autocli.go | 26 ++++++++++++++++++++++++++ x/uexecutor/migrations/v5/migrate.go | 13 +++++++++++++ x/uexecutor/module.go | 19 +++++++++++++++++-- 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 x/uexecutor/migrations/v5/migrate.go 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/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 From dce51024283730f614d620cba1736c066a641956 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:11:19 +0530 Subject: [PATCH 12/75] feat: added upgrade handler --- app/upgrades.go | 6 +++-- app/upgrades/chain-meta/upgrade.go | 41 ++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 app/upgrades/chain-meta/upgrade.go 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..73da6a4b --- /dev/null +++ b/app/upgrades/chain-meta/upgrade.go @@ -0,0 +1,41 @@ +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) + sdkCtx.Logger().Info("🔧 Running upgrade:", "name", UpgradeName) + + // RunMigrations triggers uexecutor v4→v5 which calls MigrateGasPricesToChainMeta. + return mm.RunMigrations(ctx, configurator, fromVM) + } +} From 9e65043d72e4f2f2bccf64c34c3cb7810be2240f Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:11:49 +0530 Subject: [PATCH 13/75] tests: added integration tests for vote_chain_meta --- .../uexecutor/vote_chain_meta_test.go | 264 ++++++++++++++++++ test/utils/bytecode.go | 2 +- test/utils/helpers.go | 32 +++ 3 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 test/integration/uexecutor/vote_chain_meta_test.go 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..81ebae13 --- /dev/null +++ b/test/integration/uexecutor/vote_chain_meta_test.go @@ -0,0 +1,264 @@ +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, 1700000000) + 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.ObservedAts, 1) + require.Equal(t, uint64(1700000000), stored.ObservedAts[0]) + }) + + t.Run("multiple validators vote and median calculated", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 4) + + votes := []struct { + uniVal string + price uint64 + height uint64 + observedAt uint64 + }{ + {uvals[0], 300_000_000_000, 12345, 1700000001}, + {uvals[1], 200_000_000_000, 12346, 1700000002}, + {uvals[2], 400_000_000_000, 12347, 1700000003}, + {uvals[3], 250_000_000_000, 12348, 1700000004}, + } + + 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, v.observedAt) + 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.ObservedAts, 4) + + median := stored.Prices[stored.MedianIndex] + // sorted: 200, 250, 300, 400 → median at index 2 → 300 + require.Equal(t, uint64(300_000_000_000), median) + }) + + 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, 1700000000)) + // Update same validator's vote + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 400_000_000_000, 12350, 1700000100)) + + 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]) + require.Equal(t, uint64(1700000100), stored.ObservedAts[0]) + }) + + t.Run("odd number of votes median", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 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, uint64(i+1), uint64(1700000000+i))) + } + + stored, _, _ := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + median := stored.Prices[stored.MedianIndex] + require.Equal(t, uint64(200), median) + }) +} + +func TestMigrateGasPricesToChainMeta(t *testing.T) { + chainId := "eip155:11155111" + + t.Run("migrates gas prices to chain meta", 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) + // observedAts unknown at migration time → all 0 + require.Equal(t, []uint64{0, 0}, cm.ObservedAts) + require.Equal(t, uint64(1), cm.MedianIndex) + }) + + 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}, + ObservedAts: []uint64{1700000099}, + 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, chain height, and observed timestamp. +func TestVoteChainMetaContractState(t *testing.T) { + chainId := "eip155:11155111" + const ( + price = uint64(100_000_000_000) + height = uint64(12345) + observedAt = uint64(1700000000) + ) + + 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, observedAt)) + + // 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) + }) + + t.Run("timestampObservedAtByChainNamespace matches voted observedAt", func(t *testing.T) { + res, err := testApp.EVMKeeper.CallEVM(ctx, ucABI, caller, universalCoreAddr, false, "timestampObservedAtByChainNamespace", chainId) + require.NoError(t, err) + got := new(big.Int).SetBytes(res.Ret) + require.Equal(t, new(big.Int).SetUint64(observedAt), got) + }) +} diff --git a/test/utils/bytecode.go b/test/utils/bytecode.go index 7e8177be..18b36c61 100644 --- a/test/utils/bytecode.go +++ b/test/utils/bytecode.go @@ -6,7 +6,7 @@ const UEA_SVM_BYTECODE = "6080604052348015600e575f80fd5b5060015f55611cf780610020 const UEA_PROXY_BYTECODE = "608060405260043610610028575f3560e01c806323efa7ec14610032578063aaf10f4214610051575b6100306100a8565b005b34801561003d575f80fd5b5061003061004c366004610368565b6100ba565b34801561005c575f80fd5b507f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5460405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100b86100b36102cc565b61034a565b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156101045750825b90505f8267ffffffffffffffff1660011480156101205750303b155b90508115801561012e575080155b15610165576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156101c65784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b5f6101ef7f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5490565b905073ffffffffffffffffffffffffffffffffffffffff81161561023f576040517fae962d4e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b867f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d555083156102c45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f806102f67f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610345576040517fae962d4e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b365f80375f80365f845af43d5f803e808015610364573d5ff35b3d5ffd5b5f60208284031215610378575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461039b575f80fd5b939250505056fea2646970667358221220c4b8f9457567bdcd08b95faef7df86de4e9daead65e2db22018126d9eb77d85864736f6c634300081a0033" -const HANDLER_CONTRACT_BYTECODE = "6080604052600436106102ae575f3560e01c80638456cb5911610165578063c6f1b7e7116100c6578063dcc16b5c1161007c578063f220e73e11610062578063f220e73e14610924578063f8c8765e14610971578063fb46e99d14610990575f80fd5b8063dcc16b5c146108d2578063ec87621c146108f1575f80fd5b8063d17c872c116100ac578063d17c872c14610875578063d547741f14610894578063db9a0daf146108b3575f80fd5b8063c6f1b7e71461080b578063c98018971461083e575f80fd5b8063a861469f1161011b578063b8efe33411610101578063b8efe33414610794578063be0580c0146107c0578063c344869f146107df575f80fd5b8063a861469f14610722578063ad14d38514610766575f80fd5b806391d148541161014b57806391d14854146106805780639be7fdb2146106f0578063a217fddf1461070f575f80fd5b80638456cb591461064d578063870152b714610661575f80fd5b80634eb7d1a11161020f5780636d4008a8116101c557806378a88127116101ab57806378a88127146105b55780637efbce04146105d457806380f5db8c14610621575f80fd5b80636d4008a81461056b578063780ad82714610596575f80fd5b80635c975abb116101f55780635c975abb146104f75780636341c64d1461052d57806364f10e501461054c575f80fd5b80634eb7d1a11461049757806357724c41146104d8575f80fd5b80632f2ff15d116102645780633f4ba83a1161024a5780633f4ba83a146103f157806346c72fdd146104055780634b1d2eeb14610456575f80fd5b80632f2ff15d146103b357806336568abe146103d2575f80fd5b80630ac6eb77116102945780630ac6eb771461030e5780631a4e49d41461032d578063248a9ca314610366575f80fd5b806301ffc9a7146102b95780630379eae8146102ed575f80fd5b366102b557005b5f80fd5b3480156102c4575f80fd5b506102d86102d3366004612be8565b6109a5565b60405190151581526020015b60405180910390f35b3480156102f8575f80fd5b5061030c610307366004612d23565b610a3d565b005b348015610319575f80fd5b5061030c610328366004612d93565b610a9d565b348015610338575f80fd5b50610358610347366004612dca565b5f6020819052908152604090205481565b6040519081526020016102e4565b348015610371575f80fd5b50610358610380366004612dca565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b3480156103be575f80fd5b5061030c6103cd366004612de1565b610b8a565b3480156103dd575f80fd5b5061030c6103ec366004612de1565b610bd3565b3480156103fc575f80fd5b5061030c610c31565b348015610410575f80fd5b50600a546104319073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102e4565b348015610461575f80fd5b50610431610470366004612dca565b60016020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156104a2575f80fd5b506104316104b1366004612dca565b60026020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e3575f80fd5b5061030c6104f2366004612e04565b610ca2565b348015610502575f80fd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff166102d8565b348015610538575f80fd5b5061030c610547366004612e2e565b610df7565b348015610557575f80fd5b5061030c610566366004612e49565b610f25565b348015610576575f80fd5b50610358610585366004612e2e565b60056020525f908152604090205481565b3480156105a1575f80fd5b5061030c6105b0366004612e9f565b6110ef565b3480156105c0575f80fd5b5061030c6105cf366004612e49565b611a28565b3480156105df575f80fd5b506104316105ee366004612efe565b8051602081830181018051600d8252928201919093012091525473ffffffffffffffffffffffffffffffffffffffff1681565b34801561062c575f80fd5b506007546104319073ffffffffffffffffffffffffffffffffffffffff1681565b348015610658575f80fd5b5061030c611a8f565b34801561066c575f80fd5b5061035861067b366004612f30565b611afe565b34801561068b575f80fd5b506102d861069a366004612de1565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156106fb575f80fd5b5061030c61070a366004612f7c565b611bf9565b34801561071a575f80fd5b506103585f81565b34801561072d575f80fd5b5061075261073c366004612e2e565b60046020525f908152604090205462ffffff1681565b60405162ffffff90911681526020016102e4565b348015610771575f80fd5b506102d8610780366004612e2e565b60036020525f908152604090205460ff1681565b34801561079f575f80fd5b506008546104319073ffffffffffffffffffffffffffffffffffffffff1681565b3480156107cb575f80fd5b5061030c6107da366004612fc0565b611d12565b3480156107ea575f80fd5b506009546104319073ffffffffffffffffffffffffffffffffffffffff1681565b348015610816575f80fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b348015610849575f80fd5b50610358610858366004612efe565b8051602081830181018051600b8252928201919093012091525481565b348015610880575f80fd5b5061030c61088f366004612ffd565b611ea7565b34801561089f575f80fd5b5061030c6108ae366004612de1565b612048565b3480156108be575f80fd5b5061030c6108cd366004612dca565b61208b565b3480156108dd575f80fd5b5061030c6108ec366004613030565b612127565b3480156108fc575f80fd5b506103587f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b34801561092f575f80fd5b5061043161093e366004612efe565b8051602081830181018051600c8252928201919093012091525473ffffffffffffffffffffffffffffffffffffffff1681565b34801561097c575f80fd5b5061030c61098b36600461308c565b6123c3565b34801561099b575f80fd5b5061035860065481565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610a3757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b80600b83604051610a4e9190613107565b9081526020016040518091039020819055507f6a59d469e3757d6e139cdf95b12740f585d553afac49b90bdbe278502a4427188282604051610a9192919061316b565b60405180910390a15050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610b04576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f42cc79f957a9535dc49c660eec62747fb540bef0dd29cd7f6c0a810816af4cff9101610a91565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610bc3816125b0565b610bcd83836125bd565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610c22576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c2c82826126e2565b505050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610c98576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca06127be565b565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610d09576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610d56576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388811115610d92576040517fc31c0b6e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526005602052604090819020839055517fe3e43e0700c35d0879972f000dc93907848b11360702f11ebbe14479866f806090610deb9084815260200190565b60405180910390a25050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610e5e576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610eab576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fc2d9f94b2a169da07b0305c4fcdf5e7d988c6e4793af0796516c96727a90b70e906020015b60405180910390a150565b610f2d612855565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610f9c575073ffffffffffffffffffffffffffffffffffffffff811630145b15610fd3576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611020576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f03611059576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152602482018490528416906347e7ef24906044016020604051808303815f875af11580156110cb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bcd919061318c565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461115e576040517f53e5172300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611166612855565b61116e6128b1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806111dd575073ffffffffffffffffffffffffffffffffffffffff841630145b15611214576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616611261576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f0361129a576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff86165f9081526003602052604090205460ff166112f8576040517f4e38f95a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8262ffffff165f036113695773ffffffffffffffffffffffffffffffffffffffff86165f9081526004602052604081205462ffffff169350839003611369576040517f3733548a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f0361138b5760065461137e90603c6131d4565b61138890426131eb565b90505b804211156113c5576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600754600a545f9173ffffffffffffffffffffffffffffffffffffffff90811691631698ee8291908116908a161061141557600a5473ffffffffffffffffffffffffffffffffffffffff16611417565b885b600a5473ffffffffffffffffffffffffffffffffffffffff908116908b1610611440578961145a565b600a5473ffffffffffffffffffffffffffffffffffffffff165b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff87166044820152606401602060405180830381865afa1580156114d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f791906131fe565b905073ffffffffffffffffffffffffffffffffffffffff8116611546576040517f76ecffc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825f0361158557600a545f9061157590899073ffffffffffffffffffffffffffffffffffffffff16878a611afe565b90506115818189612932565b9350505b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081523060048201526024810187905273ffffffffffffffffffffffffffffffffffffffff8816906347e7ef24906044016020604051808303815f875af11580156115f5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611619919061318c565b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018890529088169063095ea7b3906044016020604051808303815f875af1158015611690573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b4919061318c565b50604080516101008101825273ffffffffffffffffffffffffffffffffffffffff808a168252600a548116602083015262ffffff8716828401523060608301526080820185905260a0820189905260c082018690525f60e0830181905260085493517f414bf3890000000000000000000000000000000000000000000000000000000081529293909291169063414bf38990611754908590600401613219565b6020604051808303815f875af1158015611770573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061179491906132d7565b9050848110156117d0576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d906024015f604051808303815f87803b158015611839575f80fd5b505af115801561184b573d5f803e3d5ffd5b505050505f8773ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f81146118a5576040519150601f19603f3d011682016040523d82523d5f602084013e6118aa565b606091505b50509050806118e5576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201525f6024820152908b169063095ea7b3906044016020604051808303815f875af115801561195a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197e919061318c565b50600a546040805173ffffffffffffffffffffffffffffffffffffffff8d81168252602082018d9052928316818301526060810185905262ffffff8a166080820152918a1660a0830152517ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e29181900360c00190a150505050611a2060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050505050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16610f25576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16611af6576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca06129c2565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff86811682528581166020830190815282840185815262ffffff878116606086019081525f6080870181815260095498517fc6a5026a0000000000000000000000000000000000000000000000000000000081528851881660048201529551871660248701529351604486015290519091166064840152905183166084830152938492169063c6a5026a9060a4016080604051808303815f875af1158015611bc6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bea91906132ee565b50919998505050505050505050565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08611c23816125b0565b73ffffffffffffffffffffffffffffffffffffffff8216611c70576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600c84604051611c819190613107565b908152604051908190036020018120805473ffffffffffffffffffffffffffffffffffffffff939093167fffffffffffffffffffffffff0000000000000000000000000000000000000000909316929092179091557f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94990611d05908590859061333d565b60405180910390a1505050565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16611d79576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83161580611db0575073ffffffffffffffffffffffffffffffffffffffff8216155b80611dcf575073ffffffffffffffffffffffffffffffffffffffff8116155b15611e06576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316811790935560088054868316908416811790915560098054928616929093168217909255604080519384526020840192909252908201527f95d3bff4dd1ae411fd49ebc9fcc62f464b6b60cd9b4eacd860da89045c8d4c8290606001611d05565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16611f0e576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611f5b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8062ffffff166101f414158015611f7957508062ffffff16610bb814155b8015611f8c57508062ffffff1661271014155b15611fc3576040517f3733548a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000001662ffffff861690811790915591519182527f5734dc08ec8c21bd34e0f102d90ea2d1a9dbdcf23e787dc8744d2d0dd227fc739101610deb565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154612081816125b0565b610bcd83836126e2565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff166120f2576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60068190556040518181527f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b90602001610f1a565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08612151816125b0565b73ffffffffffffffffffffffffffffffffffffffff831661219e576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600754600a545f9173ffffffffffffffffffffffffffffffffffffffff90811691631698ee82918781169116106121d557856121ef565b600a5473ffffffffffffffffffffffffffffffffffffffff165b600a5473ffffffffffffffffffffffffffffffffffffffff80891691161061222f57600a5473ffffffffffffffffffffffffffffffffffffffff16612231565b865b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff86166044820152606401602060405180830381865afa1580156122aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122ce91906131fe565b905073ffffffffffffffffffffffffffffffffffffffff811661231d576040517f76ecffc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600d8660405161232e9190613107565b908152604051908190036020018120805473ffffffffffffffffffffffffffffffffffffffff939093167fffffffffffffffffffffffff0000000000000000000000000000000000000000909316929092179091557f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d906123b490879084908790613374565b60405180910390a15050505050565b5f6123cc612a3b565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156123f85750825b90505f8267ffffffffffffffff1660011480156124145750303b155b905081158015612422575080155b15612459576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156124ba5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6124c2612a63565b6124ca612a73565b6124d45f336125bd565b50600a805473ffffffffffffffffffffffffffffffffffffffff808c167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255600780548b8416908316179055600880548a8416908316179055600980549289169290911691909117905583156125a55784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b6125ba8133612a7b565b50565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff166126d2575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561266e3390565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610a37565b5f915050610a37565b5092915050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff16156126d2575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610a37565b6127c6612b29565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610f1a565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615610ca0576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0161292c576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60029055565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260056020526040812054808203612963575061012c5b835f03612973575f915050610a37565b61271061298082826133b7565b61298a90866131d4565b61299491906133ca565b949350505050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6129ca612855565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833612830565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610a37565b612a6b612b84565b610ca0612bc2565b610ca0612b84565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16612b25576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440160405180910390fd5b5050565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16610ca0576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b8c612bca565b610ca0576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61299c612b84565b5f612bd3612a3b565b5468010000000000000000900460ff16919050565b5f60208284031215612bf8575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114612c27575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112612c6a575f80fd5b813567ffffffffffffffff811115612c8457612c84612c2e565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff82111715612cf057612cf0612c2e565b604052818152838201602001851015612d07575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215612d34575f80fd5b823567ffffffffffffffff811115612d4a575f80fd5b612d5685828601612c5b565b95602094909401359450505050565b73ffffffffffffffffffffffffffffffffffffffff811681146125ba575f80fd5b80151581146125ba575f80fd5b5f8060408385031215612da4575f80fd5b8235612daf81612d65565b91506020830135612dbf81612d86565b809150509250929050565b5f60208284031215612dda575f80fd5b5035919050565b5f8060408385031215612df2575f80fd5b823591506020830135612dbf81612d65565b5f8060408385031215612e15575f80fd5b8235612e2081612d65565b946020939093013593505050565b5f60208284031215612e3e575f80fd5b8135612c2781612d65565b5f805f60608486031215612e5b575f80fd5b8335612e6681612d65565b9250602084013591506040840135612e7d81612d65565b809150509250925092565b803562ffffff81168114612e9a575f80fd5b919050565b5f805f805f8060c08789031215612eb4575f80fd5b8635612ebf81612d65565b9550602087013594506040870135612ed681612d65565b9350612ee460608801612e88565b9598949750929560808101359460a0909101359350915050565b5f60208284031215612f0e575f80fd5b813567ffffffffffffffff811115612f24575f80fd5b61299484828501612c5b565b5f805f8060808587031215612f43575f80fd5b8435612f4e81612d65565b93506020850135612f5e81612d65565b9250612f6c60408601612e88565b9396929550929360600135925050565b5f8060408385031215612f8d575f80fd5b823567ffffffffffffffff811115612fa3575f80fd5b612faf85828601612c5b565b9250506020830135612dbf81612d65565b5f805f60608486031215612fd2575f80fd5b8335612fdd81612d65565b92506020840135612fed81612d65565b91506040840135612e7d81612d65565b5f806040838503121561300e575f80fd5b823561301981612d65565b915061302760208401612e88565b90509250929050565b5f805f60608486031215613042575f80fd5b833567ffffffffffffffff811115613058575f80fd5b61306486828701612c5b565b935050602084013561307581612d65565b915061308360408501612e88565b90509250925092565b5f805f806080858703121561309f575f80fd5b84356130aa81612d65565b935060208501356130ba81612d65565b925060408501356130ca81612d65565b915060608501356130da81612d65565b939692955090935050565b5f5b838110156130ff5781810151838201526020016130e7565b50505f910152565b5f82516131188184602087016130e5565b9190910192915050565b5f81518084526131398160208601602086016130e5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081525f61317d6040830185613122565b90508260208301529392505050565b5f6020828403121561319c575f80fd5b8151612c2781612d86565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082028115828204841417610a3757610a376131a7565b80820180821115610a3757610a376131a7565b5f6020828403121561320e575f80fd5b8151612c2781612d65565b5f6101008201905073ffffffffffffffffffffffffffffffffffffffff835116825273ffffffffffffffffffffffffffffffffffffffff602084015116602083015262ffffff60408401511660408301526060830151613291606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080830151608083015260a083015160a083015260c083015160c083015260e08301516126db60e084018273ffffffffffffffffffffffffffffffffffffffff169052565b5f602082840312156132e7575f80fd5b5051919050565b5f805f8060808587031215613301575f80fd5b8451602086015190945061331481612d65565b604086015190935063ffffffff8116811461332d575f80fd5b6060959095015193969295505050565b604081525f61334f6040830185613122565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b606081525f6133866060830186613122565b905073ffffffffffffffffffffffffffffffffffffffff8416602083015262ffffff83166040830152949350505050565b81810381811115610a3757610a376131a7565b5f826133fd577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b50049056fea2646970667358221220be7683826e35c7cef49a08ea8ce84884a78fea00c3f7eced428fd855051f979864736f6c634300081a0033" +const HANDLER_CONTRACT_BYTECODE = "608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c908162bc574b146138ee5750806301ffc9a71461384d5780630379eae8146137f05780630ac6eb77146137445780631a4e49d41461371b5780631a873ce4146136e8578063240028e81461369e578063248a9ca31461364c5780632f2ff15d146135ef57806336568abe146135855780633f4ba83a1461347c5780634b1d2eeb1461343c5780634d20d0f8146134095780634eb7d1a1146133c957806355840b7d1461337a57806357724c41146132795780635b549182146132465780635c975abb146132055780636435967b146129d357806364f10e501461294e57806368c70c9e146129035780636d4008a8146128be578063780ad8271461215357806378a88127146120d857806381fbadad146120ba5780638377e2301461208657806383b94a5214611fd05780638456cb5914611ea557806391d1485414611e2e5780639be7fdb214611d43578063a217fddf14611d27578063a5172ddb14611cdc578063a861469f14611c92578063ad14d38514611c48578063af90f35114611b6a578063b5d8349f14611b09578063be0580c014611963578063c6f1b7e714611912578063d17c872c146117c3578063d547741f1461175c578063db9a0daf14611699578063dbc1b46414611638578063dcc16b5c146113d5578063dd19e7551461113d578063e201db9b1461080f578063e798646614610730578063ec87621c146106f5578063f8c8765e146103c3578063fa064472146102d2578063fb46e99d146102b45763fc6b5de80361000f57346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602061029e8161028b36600487016139e3565b8160405193828580945193849201613b07565b8101601281520301902054604051908152f35b80fd5b50346102b157806003193601126102b1576020600654604051908152f35b50346102b15760806003193601126102b15760043567ffffffffffffffff81116103bf576103a96103287f5e41bf0052b493123a63e4e0d9095ed4324108e489d58c9a0948b2be366ac8c69236906004016139e3565b602435604435606435908161038a6020604051868851918381818c0194610350818388613b07565b8101600b815203019020558460405183818b5161036e818388613b07565b8101601181520301902055604051809381928a51928391613b07565b8101601281520301902055604051948594608086526080860190613b28565b926020850152604084015260608301520390a180f35b5080fd5b50346102b15760806003193601126102b1576103dd613a29565b6103e5613a4c565b6103ed613a6f565b6064359173ffffffffffffffffffffffffffffffffffffffff83168093036106f1577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff8116801590816106e9575b60011490816106df575b1590816106d6575b506106ae579173ffffffffffffffffffffffffffffffffffffffff80949392838860017fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000859716177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610659575b506104d9614253565b6104e1614253565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561050d614253565b61051633613da7565b50167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a55167fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff000000000000000000000000000000000000000060085416176008557fffffffffffffffffffffffff000000000000000000000000000000000000000060095416176009556105c55780f35b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f6104d0565b6004877ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b9050155f610461565b303b159150610459565b87915061044f565b8480fd5b50346102b157806003193601126102b15760206040517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50346102b15760406003193601126102b15761074a613a29565b73ffffffffffffffffffffffffffffffffffffffff610767613a92565b91610770613c99565b169081156107e75760207f16ef4de07b0452a43221c91064fb645963a8e2e60bd8a7514da58d56e315c42291838552601082526107db81604087209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b6004837fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b5060e06003193601126102b157610824613a29565b9061082d613a4c565b91610836613aa1565b9160c4359173ffffffffffffffffffffffffffffffffffffffff83169160a4359190608435606435858703610de35773ffffffffffffffffffffffffffffffffffffffff600e541633036111155761088c6140a8565b6108946140fb565b8492889973ffffffffffffffffffffffffffffffffffffffff86169586156107e75773ffffffffffffffffffffffffffffffffffffffff82169788156110ed5789156110ed5734156110c55784156110c55762ffffff6108f48787613c5d565b9c1615611084575b1561102f575b854211611007576109bd60208d73ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a5416948b861090815f146110005786915b15610ff857905b604051958694859384937f1698ee820000000000000000000000000000000000000000000000000000000085526004850191604091949373ffffffffffffffffffffffffffffffffffffffff62ffffff9281606087019816865216602085015216910152565b03915afa908115610fed579073ffffffffffffffffffffffffffffffffffffffff918591610fbe575b501615610f9657803b15610de35782600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af18015610dd857908391610f81575b50600a546008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015234602482015292602092849260449284929091165af18015610dd857610f64575b50600a5473ffffffffffffffffffffffffffffffffffffffff169a6040519b610ac78d61391e565b8c528660208d015262ffffff16948560408d01523060608d015260808c01528960a08c01523460c08c01528160e08c01528160085473ffffffffffffffffffffffffffffffffffffffff169b6040519c8d917fdb3e219800000000000000000000000000000000000000000000000000000000835260048301610bb09173ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b815a9361010492602095f19a8b15610f5957829b610f21575b5081602073ffffffffffffffffffffffffffffffffffffffff600a5416604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015610dd857610f04575b506040517f42966c68000000000000000000000000000000000000000000000000000000008152836004820152602081602481868b5af18015610dd857610ed7575b508184610e14575b505089340397348911610de7578a3403610d12575b5050977f8c8071a0a45857f27eaa04a47ecdc04f0549d2150a7a1cb5eaa7111b6cf85f8d9260809260409a8b5193845260208401528a8301526060820152a460017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005582519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff600a5416803b15610de35782809160248c60405194859384927f2e1a7d4d00000000000000000000000000000000000000000000000000000000845260048401525af18015610dd8579183918b93610dbe575b5081809381925af1610d8a613c6a565b5015610d965780610ca3565b807f90b8ec180000000000000000000000000000000000000000000000000000000060049252fd5b610dcb9193508290613968565b6103bf578189915f610d7a565b6040513d85823e3d90fd5b8280fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602080830191825273ffffffffffffffffffffffffffffffffffffffff9490941660248301526044808301889052825290610e74606482613968565b519082895af115610ecb5780513d610ec25750843b155b610e96575f81610c8e565b80857f5274afe70000000000000000000000000000000000000000000000000000000060249352600452fd5b60011415610e8b565b604051903d90823e3d90fd5b610ef89060203d602011610efd575b610ef08183613968565b810190613b6b565b610c86565b503d610ee6565b610f1c9060203d602011610efd57610ef08183613968565b610c44565b909a506020813d602011610f51575b81610f3d60209383613968565b81010312610f4d5751995f610bc9565b5f80fd5b3d9150610f30565b6040513d84823e3d90fd5b610f7c9060203d602011610efd57610ef08183613968565b610a9f565b81610f8b91613968565b6103bf57815f610a34565b6004837f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b610fe0915060203d602011610fe6575b610fd88183613968565b810190613c31565b5f6109e6565b503d610fce565b6040513d86823e3d90fd5b508590610957565b8091610950565b6004837f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9450600654603c810290808204603c1490151715611057576110519042613c5d565b94610902565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8784526004602052604084205462ffffff169c508c6108fc576004847f3733548a000000000000000000000000000000000000000000000000000000008152fd5b6004847f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004847fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b6004837fbce361b0000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760406003193601126102b157611157613a29565b6024359081156113cb575b73ffffffffffffffffffffffffffffffffffffffff166040517fa0c50b690000000000000000000000000000000000000000000000000000000081528381600481855afa908115610fed57849161134e575b506040519173ffffffffffffffffffffffffffffffffffffffff825193602081818601966111e381838a613b07565b8101600c815203019020541692831561132657602061120d91604051809381928751928391613b07565b8101600b815203019020549081156112fe5784820294828604036112d1579460206004949596604051958680927ff97c007a0000000000000000000000000000000000000000000000000000000082525afa908115610ecb579061129d575b6112999350604051958695865260208601526040850152606084015260a0608084015260a0830190613b28565b0390f35b506020833d6020116112c9575b816112b760209383613968565b81010312610f4d57611299925161126c565b3d91506112aa565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6004867fe661aed0000000000000000000000000000000000000000000000000000000008152fd5b6004867fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b90503d8085833e61135f8183613968565b8101906020818303126106f15780519067ffffffffffffffff82116113c7570181601f820112156106f1578051611395816139a9565b926113a36040519485613968565b818452602082840101116113c7576113c19160208085019101613b07565b5f6111b4565b8580fd5b600f549150611162565b50346102b15760606003193601126102b15760043567ffffffffffffffff81116103bf576114079036906004016139e3565b61140f613a4c565b611417613aa1565b90611420613c99565b73ffffffffffffffffffffffffffffffffffffffff8116801561161057826114f29260209273ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541691821091825f146116095780925b1561160157506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015610fed5773ffffffffffffffffffffffffffffffffffffffff9185916115e2575b50169081156115ba57916115a89162ffffff7f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d9460405160208186516115628183858b01613b07565b8101600d815203019020837fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051948594606086526060860190613b28565b9260208501521660408301520390a180f35b6004847f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b6115fb915060203d602011610fe657610fd88183613968565b5f611519565b905090610957565b8192611486565b6004857fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602073ffffffffffffffffffffffffffffffffffffffff6116858261028b36600488016139e3565b8101600c8152030190205416604051908152f35b50346102b15760206003193601126102b1576004358180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611734576020817f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b92600655604051908152a180f35b6004827f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760406003193601126102b1576117bf60043561177c613a4c565b906117ba6117b5825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613d21565b613fa0565b5080f35b50346102b15760406003193601126102b1576117dd613a29565b6024359062ffffff8216809203610de3578280527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156118ea5773ffffffffffffffffffffffffffffffffffffffff1680156107e7576101f4821415806118de575b806118d2575b6118aa578252600460205260408220907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000082541617905580f35b6004837f3733548a000000000000000000000000000000000000000000000000000000008152fd5b50612710821415611870565b50610bb882141561186a565b6004837f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102b157806003193601126102b157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102b15760606003193601126102b15761197d613a29565b611985613a4c565b61198d613a6f565b918380527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040842073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611ae15773ffffffffffffffffffffffffffffffffffffffff1680158015611ac3575b8015611aa5575b6110ed5773ffffffffffffffffffffffffffffffffffffffff929183917fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff00000000000000000000000000000000000000006008541617600855167fffffffffffffffffffffffff0000000000000000000000000000000000000000600954161760095580f35b5073ffffffffffffffffffffffffffffffffffffffff831615611a08565b5073ffffffffffffffffffffffffffffffffffffffff821615611a01565b6004847f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602073ffffffffffffffffffffffffffffffffffffffff611b568261028b36600488016139e3565b8101600d8152030190205416604051908152f35b50346102b15760206003193601126102b157611b84613a29565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156117345773ffffffffffffffffffffffffffffffffffffffff168015611c20577fffffffffffffffffffffffff0000000000000000000000000000000000000000600e541617600e5580f35b6004827fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b15760ff604060209273ffffffffffffffffffffffffffffffffffffffff611c7e613a29565b168152600384522054166040519015158152f35b50346102b15760206003193601126102b15762ffffff604060209273ffffffffffffffffffffffffffffffffffffffff611cca613a29565b16815260048452205416604051908152f35b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b1576020611d148161028b36600487016139e3565b8101600b81520301902054604051908152f35b50346102b157806003193601126102b157602090604051908152f35b50346102b15760406003193601126102b15760043567ffffffffffffffff81116103bf57611d759036906004016139e3565b73ffffffffffffffffffffffffffffffffffffffff611d92613a4c565b611d9a613c99565b1680156107e7577f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94991611e22916040516020818451611ddc8183858901613b07565b8101600c815203019020817fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051928392604084526040840190613b28565b9060208301520390a180f35b50346102b15760406003193601126102b15773ffffffffffffffffffffffffffffffffffffffff6040611e5f613a4c565b9260043581527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020522091165f52602052602060ff60405f2054166040519015158152f35b50346102b157806003193601126102b1578080527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040812073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611fa857611f126140a8565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b807f49e27cff0000000000000000000000000000000000000000000000000000000060049252fd5b50346102b15760206003193601126102b157611fea613a29565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156117345773ffffffffffffffffffffffffffffffffffffffff168015611c20577fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102b157806003193601126102b157602073ffffffffffffffffffffffffffffffffffffffff600e5416604051908152f35b50346102b157806003193601126102b1576020600f54604051908152f35b50346102b1576120e736613ab3565b9083809394527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156118ea57612150929361214b6140a8565b613b83565b80f35b50346102b15760c06003193601126102b15761216d613a29565b60243590612179613a6f565b906064359262ffffff8416908185036113c75760843560a4359373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303612896576121d86140a8565b6121e06140fb565b6121eb868483614172565b8473ffffffffffffffffffffffffffffffffffffffff821697888a52600360205260ff60408b2054161561286e57941561282d575b156127d8575b8442116127b0576020846122e3928a73ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541690818d10805f146127a95781935b501561160157506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156127125773ffffffffffffffffffffffffffffffffffffffff91899161278a575b50161561276257801561273a576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018390526020816044818b8b5af180156127125761271d575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018390526020816044818b8b5af18015612712576126f5575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a541693604051946123ee8661391e565b8886526020808701918252929091166040808701828152306060890190815260808901998a5260a0890188815260c08a0188815260e08b018f815260085495517f414bf3890000000000000000000000000000000000000000000000000000000081529b5173ffffffffffffffffffffffffffffffffffffffff90811660048e01529751881660248d0152935162ffffff1660448c01529151861660648b0152995160848a0152985160a4890152975160c48801529651821660e48701529585916101049183918c91165af192831561268e5787936126c1575b5082106126995773ffffffffffffffffffffffffffffffffffffffff60085416604051907f095ea7b300000000000000000000000000000000000000000000000000000000825260048201528660248201526020816044818a8a5af1801561268e57612671575b508573ffffffffffffffffffffffffffffffffffffffff600a5416803b156103bf578180916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528960048401525af18015610f595761265c575b5080808085885af16125a3613c6a565b501561263457927ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e2949273ffffffffffffffffffffffffffffffffffffffff9260c09584600a54169060405196875260208701526040860152606085015260808401521660a0820152a160017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6004867f90b8ec18000000000000000000000000000000000000000000000000000000008152fd5b8161266691613968565b6113c757855f612593565b6126899060203d602011610efd57610ef08183613968565b61252f565b6040513d89823e3d90fd5b6004867f8199f5f3000000000000000000000000000000000000000000000000000000008152fd5b9092506020813d6020116126ed575b816126dd60209383613968565b81010312610f4d5751915f6124c8565b3d91506126d0565b61270d9060203d602011610efd57610ef08183613968565b6123c2565b6040513d8a823e3d90fd5b6127359060203d602011610efd57610ef08183613968565b61235f565b6004877f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004877f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b6127a3915060203d602011610fe657610fd88183613968565b5f61230a565b8293612276565b6004887f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9350600654603c810290808204603c1490151715612800576127fa9042613c5d565b93612226565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8789526004602052604089205462ffffff16945084612220576004897f3733548a000000000000000000000000000000000000000000000000000000008152fd5b60048a7f4e38f95a000000000000000000000000000000000000000000000000000000008152fd5b6004887f53e51723000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b157604060209173ffffffffffffffffffffffffffffffffffffffff6128f2613a29565b168152600583522054604051908152f35b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602061293b8161028b36600487016139e3565b8101601181520301902054604051908152f35b50346102b15761295d36613ab3565b9073ffffffffffffffffffffffffffffffffffffffff9392937f00000000000000000000000000000000000000000000000000000000000000001633036129ab57612150929361214b6140a8565b6004837f53e51723000000000000000000000000000000000000000000000000000000008152fd5b5034610f4d5760c0600319360112610f4d576129ed613a29565b6024356129f8613a6f565b6064358015918215809203610f4d5760843562ffffff811690818103610f4d5760a43573ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036131dd57612a606140a8565b612a686140fb565b612a7384888a614172565b5f9515612b925750506040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101869052919050602082806044810103818a73ffffffffffffffffffffffffffffffffffffffff8b165af190811561268e577ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49460609473ffffffffffffffffffffffffffffffffffffffff948594612b73575b505b6040519788526020880152604087015216941692a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b612b8b9060203d602011610efd57610ef08183613968565b505f612b35565b809192939550156131b55773ffffffffffffffffffffffffffffffffffffffff871691825f52600360205260ff60405f2054161561318d57921561314b575b600654603c810290808204603c149015171561311e57612bf19042613c5d565b8042116130f657612ca960208573ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a541680881090815f146130ef578d915b156130e7576040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015612fe25773ffffffffffffffffffffffffffffffffffffffff915f916130c8575b5016156130a0576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018890526020816044815f885af18015612fe257613083575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018890526020816044815f885af18015612fe257613066575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169460405195612dae8761391e565b858752602087015216604085015230606085015260808401528560a08401528060c08401525f60e08401526020612e9861010473ffffffffffffffffffffffffffffffffffffffff60085416955f60405197889485937f414bf389000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1928315612fe2575f93613032575b50821061300a5760205f91604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015612fe257612fed575b5073ffffffffffffffffffffffffffffffffffffffff600a5416803b15610f4d575f80916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528760048401525af18015612fe257612fcd575b508580808084875af1612f85613c6a565b50156126345773ffffffffffffffffffffffffffffffffffffffff7ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e493606093829390612b37565b612fda9196505f90613968565b5f945f612f74565b6040513d5f823e3d90fd5b6130059060203d602011610efd57610ef08183613968565b612f11565b7f8199f5f3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d60201161305e575b8161304e60209383613968565b81010312610f4d5751915f612ea8565b3d9150613041565b61307e9060203d602011610efd57610ef08183613968565b612d82565b61309b9060203d602011610efd57610ef08183613968565b612d1f565b7f76ecffc0000000000000000000000000000000000000000000000000000000005f5260045ffd5b6130e1915060203d602011610fe657610fd88183613968565b5f612cd0565b508c90610957565b8091612c3e565b7f1ab7da6b000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9150805f52600460205262ffffff60405f2054169182612bd1577f3733548a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e38f95a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f22c50cbf000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f53e51723000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d575f600319360112610f4d57602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610f4d575f600319360112610f4d57602073ffffffffffffffffffffffffffffffffffffffff60075416604051908152f35b34610f4d576040600319360112610f4d57613292613a29565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040902054602435919060ff16156133525773ffffffffffffffffffffffffffffffffffffffff16801561332a576113888211613302575f52600560205260405f20555f80f35b7fc31c0b6e000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f49e27cff000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d576020600319360112610f4d57335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff161561335257600435600f55005b34610f4d576020600319360112610f4d576004355f526002602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610f4d575f600319360112610f4d57602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b34610f4d576020600319360112610f4d576004355f526001602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610f4d575f600319360112610f4d57335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff1615613352577fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff81161561355d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d576040600319360112610f4d5761359e613a4c565b3373ffffffffffffffffffffffffffffffffffffffff8216036135c75761001a90600435613fa0565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d576040600319360112610f4d5761001a60043561360e613a4c565b906136476117b5825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613e8e565b34610f4d576020600319360112610f4d5760206136966004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b34610f4d576020600319360112610f4d5773ffffffffffffffffffffffffffffffffffffffff6136cc613a29565b165f526010602052602060ff60405f2054166040519015158152f35b34610f4d575f600319360112610f4d57602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b34610f4d576020600319360112610f4d576004355f525f602052602060405f2054604051908152f35b34610f4d576040600319360112610f4d5761375d613a29565b613765613a92565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156133525773ffffffffffffffffffffffffffffffffffffffff61001a92165f52600360205260405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b34610f4d576040600319360112610f4d5760043567ffffffffffffffff8111610f4d576138219036906004016139e3565b60206138366040519283815193849201613b07565b810190600b82526020816024359303019020555f80f35b34610f4d576020600319360112610f4d576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610f4d57807f7965db0b00000000000000000000000000000000000000000000000000000000602092149081156138c4575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014826138b9565b34610f4d575f600319360112610f4d5760209073ffffffffffffffffffffffffffffffffffffffff600854168152f35b610100810190811067ffffffffffffffff82111761393b57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761393b57604052565b67ffffffffffffffff811161393b57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f82011215610f4d578035906139fa826139a9565b92613a086040519485613968565b82845260208383010111610f4d57815f926020809301838601378301015290565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610f4d57565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610f4d57565b6044359073ffffffffffffffffffffffffffffffffffffffff82168203610f4d57565b602435908115158203610f4d57565b6044359062ffffff82168203610f4d57565b6003196060910112610f4d5760043573ffffffffffffffffffffffffffffffffffffffff81168103610f4d57906024359060443573ffffffffffffffffffffffffffffffffffffffff81168103610f4d5790565b5f5b838110613b185750505f910152565b8181015183820152602001613b09565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093613b6481518092818752878088019101613b07565b0116010190565b90816020910312610f4d57518015158103610f4d5790565b90602091613c0493613b96818484614172565b5f73ffffffffffffffffffffffffffffffffffffffff6040518097819682957f47e7ef24000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0393165af18015612fe257613c165750565b613c2e9060203d602011610efd57610ef08183613968565b50565b90816020910312610f4d575173ffffffffffffffffffffffffffffffffffffffff81168103610f4d5790565b9190820180921161311e57565b3d15613c94573d90613c7b826139a9565b91613c896040519384613968565b82523d5f602084013e565b606090565b335f9081527f06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a602052604090205460ff1615613cd157565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0860245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615613d785750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613e895773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f14613f9a57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f14613f9a57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166140d357565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00541461414a5760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919073ffffffffffffffffffffffffffffffffffffffff161561332a5773ffffffffffffffffffffffffffffffffffffffff16801561332a5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168114908115614249575b5061422157156141f957565b7f1f2a2005000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f82d5d76a000000000000000000000000000000000000000000000000000000005f5260045ffd5b905030145f6141ed565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561428257565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea26469706673582212203646e3ee15c982505d4331c1a1af22a6dce9040f03c82da9a65983e246eeb0a764736f6c634300081a0033" const PRC20_CREATION_BYTECODE = "608060405234801561000f575f80fd5b50600436106101a5575f3560e01c806374be2150116100e8578063c701262611610093578063eddeb1231161006e578063eddeb12314610457578063f687d12a1461046a578063f97c007a1461047d578063fc5fecd514610486575f80fd5b8063c7012626146103cb578063d9eeebed146103de578063dd62ed3e14610412575f80fd5b8063b84c8246116100c3578063b84c82461461037e578063c47f002714610391578063c6f1b7e7146103a4575f80fd5b806374be21501461033c57806395d89b4114610363578063a9059cbb1461036b575f80fd5b806323b872dd1161015357806347e7ef241161012e57806347e7ef24146102a1578063609c92b8146102b4578063701cd43b146102e857806370a0823114610307575f80fd5b806323b872dd14610266578063313ce5671461027957806342966c681461028e575f80fd5b8063091d278811610183578063091d278814610224578063095ea7b31461023b57806318160ddd1461025e575f80fd5b8063044d9371146101a957806306fdde03146101fa57806307e2bd8d1461020f575b5f80fd5b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610202610499565b6040516101f1919061143c565b61022261021d366004611479565b610529565b005b61022d60015481565b6040519081526020016101f1565b61024e610249366004611494565b6105ef565b60405190151581526020016101f1565b60065461022d565b61024e6102743660046114be565b6106ae565b60055460405160ff90911681526020016101f1565b61024e61029c3660046114fc565b61079b565b61024e6102af366004611494565b6107ae565b6102db7f000000000000000000000000000000000000000000000000000000000000000081565b6040516101f19190611513565b5f546101d09073ffffffffffffffffffffffffffffffffffffffff1681565b61022d610315366004611479565b73ffffffffffffffffffffffffffffffffffffffff165f9081526007602052604090205490565b61022d7f000000000000000000000000000000000000000000000000000000000000000081565b610202610879565b61024e610379366004611494565b610888565b61022261038c36600461157f565b61089d565b61022261039f36600461157f565b61091c565b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b61024e6103d936600461166f565b610997565b6103e6610af9565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016101f1565b61022d6104203660046116e1565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260086020908152604080832093909416825291909152205490565b6102226104653660046114fc565b610d04565b6102226104783660046114fc565b610da8565b61022d60025481565b6103e66104943660046114fc565b610e4c565b6060600380546104a890611718565b80601f01602080910402602001604051908101604052809291908181526020018280546104d490611718565b801561051f5780601f106104f65761010080835404028352916020019161051f565b820191905f5260205f20905b81548152906001019060200180831161050257829003601f168201915b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610576576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f412d5a95dc32cbb6bd9319bccf1bc1febeda71e734893a440f1f6853252fe99f906020015b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff831661063d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f81815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060015b92915050565b5f6106ba848484611055565b73ffffffffffffffffffffffffffffffffffffffff84165f90815260086020908152604080832033845290915290205482811015610724576040517f10bad14700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85165f81815260086020908152604080832033808552908352928190208786039081905590519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3506001949350505050565b5f6107a6338361119c565b506001919050565b5f6107b983836112ed565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060601b1660208201527f67fc7bdaed5b0ec550d8706b87d60568ab70c6b781263c70101d54cd1564aab390603401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526108689186908690611769565b60405180910390a150600192915050565b6060600480546104a890611718565b5f610894338484611055565b50600192915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461090c576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600461091882826117ef565b5050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461098b576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361091882826117ef565b5f805f6109a2610af9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018390529294509092505f918416906323b872dd906064016020604051808303815f875af1158015610a42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a669190611906565b905080610a9f576040517f0a7cd6d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610aa9338661119c565b7f9ffbffc04a397460ee1dbe8c9503e098090567d6b7f4b3c02a8617d800b6d9553388888886600254604051610ae496959493929190611925565b60405180910390a15060019695505050505050565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610bf8576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610c84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca891906119c0565b9050805f03610ce3576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254600154610cf39083611a04565b610cfd9190611a1b565b9150509091565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d73576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028190556040518181527fef13af88e424b5d15f49c77758542c1938b08b8b95b91ed0751f98ba99000d8f906020016105e4565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e17576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018190556040518181527fff5788270f43bfc1ca41c503606d2594aa3023a1a7547de403a3e2f146a4a80a906020016105e4565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610efc91906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610f4b576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610fd7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffb91906119c0565b9050805f03611036576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546110438583611a04565b61104d9190611a1b565b915050915091565b73ffffffffffffffffffffffffffffffffffffffff8316158061108c575073ffffffffffffffffffffffffffffffffffffffff8216155b156110c3576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526007602052604090205481811015611122576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8085165f8181526007602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061118e9086815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611222576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526007602052604090205481811015611281576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f8181526007602090815260408083208686039055600680548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff821661133a576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611373576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600680548201905573ffffffffffffffffffffffffffffffffffffffff82165f818152600760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b5f81518084525f5b818110156113ff576020818501810151868301820152016113e3565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61144e60208301846113db565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611476575f80fd5b50565b5f60208284031215611489575f80fd5b813561144e81611455565b5f80604083850312156114a5575f80fd5b82356114b081611455565b946020939093013593505050565b5f805f606084860312156114d0575f80fd5b83356114db81611455565b925060208401356114eb81611455565b929592945050506040919091013590565b5f6020828403121561150c575f80fd5b5035919050565b602081016003831061154c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91905290565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f6020828403121561158f575f80fd5b813567ffffffffffffffff8111156115a5575f80fd5b8201601f810184136115b5575f80fd5b803567ffffffffffffffff8111156115cf576115cf611552565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561163b5761163b611552565b604052818152828201602001861015611652575f80fd5b816020840160208301375f91810160200191909152949350505050565b5f805f60408486031215611681575f80fd5b833567ffffffffffffffff811115611697575f80fd5b8401601f810186136116a7575f80fd5b803567ffffffffffffffff8111156116bd575f80fd5b8660208284010111156116ce575f80fd5b6020918201979096509401359392505050565b5f80604083850312156116f2575f80fd5b82356116fd81611455565b9150602083013561170d81611455565b809150509250929050565b600181811c9082168061172c57607f821691505b602082108103611763577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b606081525f61177b60608301866113db565b73ffffffffffffffffffffffffffffffffffffffff9490941660208301525060400152919050565b601f8211156117ea57805f5260205f20601f840160051c810160208510156117c85750805b601f840160051c820191505b818110156117e7575f81556001016117d4565b50505b505050565b815167ffffffffffffffff81111561180957611809611552565b61181d816118178454611718565b846117a3565b6020601f82116001811461186e575f83156118385750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556117e7565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156118bb578785015182556020948501946001909201910161189b565b50848210156118f757868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215611916575f80fd5b8151801515811461144e575f80fd5b73ffffffffffffffffffffffffffffffffffffffff8716815260a060208201528460a0820152848660c08301375f60c086830101525f60c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8801168301019050846040830152836060830152826080830152979650505050505050565b5f602082840312156119b5575f80fd5b815161144e81611455565b5f602082840312156119d0575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176106a8576106a86119d7565b808201808211156106a8576106a86119d756fea26469706673582212206be692aa215f21df823c52c689a11caa03254730bfade7b8b36788d6a72ba61764736f6c634300081a0033" diff --git a/test/utils/helpers.go b/test/utils/helpers.go index 5a485e3c..037d376e 100644 --- a/test/utils/helpers.go +++ b/test/utils/helpers.go @@ -106,3 +106,35 @@ 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, + observedAt uint64, +) error { + t.Helper() + + msg := &uexecutortypes.MsgVoteChainMeta{ + Signer: coreValAddr, + ObservedChainId: chainID, + Price: price, + ChainHeight: blockNumber, + ObservedAt: observedAt, + } + + execMsg := authz.NewMsgExec( + sdk.MustAccAddressFromBech32(universalAddr), + []sdk.Msg{msg}, + ) + + _, err := app.AuthzKeeper.Exec(ctx, &execMsg) + return err +} From 28eaa4658c0c8d4c3465ac6201286a990b68dd16 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:12:06 +0530 Subject: [PATCH 14/75] feat: added chain meta queries in query server --- proto/uexecutor/v1/query.proto | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) 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 {} From 4ee9724900e0e4fedf400ede1a732abc0ad22ca3 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:12:14 +0530 Subject: [PATCH 15/75] refactor: added generated protobuf --- api/uexecutor/v1/query.pulsar.go | 2532 ++++++++++++++++++++++++++--- api/uexecutor/v1/query_grpc.pb.go | 78 + 2 files changed, 2403 insertions(+), 207 deletions(-) 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", From ae4f7f9d576e0c2942da9c850034fb06407abe94 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:12:32 +0530 Subject: [PATCH 16/75] feat: added chain meta query server implementation --- x/uexecutor/keeper/query_server.go | 79 +++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/x/uexecutor/keeper/query_server.go b/x/uexecutor/keeper/query_server.go index 1dbf79ed..d9e50aa9 100755 --- a/x/uexecutor/keeper/query_server.go +++ b/x/uexecutor/keeper/query_server.go @@ -179,6 +179,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 +187,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 +207,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 +222,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 +237,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, + } +} From c5627b5d4333c68c4c150640bf2a4b4878ebd792 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:12:38 +0530 Subject: [PATCH 17/75] refactor: added generated protobuf --- x/uexecutor/types/query.pb.go | 1071 +++++++++++++++++++++++++++--- x/uexecutor/types/query.pb.gw.go | 184 +++++ 2 files changed, 1147 insertions(+), 108 deletions(-) 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 ) From 1b3236a6a24cbb5398856056ce9155d9e8101806 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 12 Mar 2026 16:12:50 +0530 Subject: [PATCH 18/75] tests: added integration tests for chain meta queries --- .../uexecutor/query_chain_meta_test.go | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 test/integration/uexecutor/query_chain_meta_test.go 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..2e63dbc5 --- /dev/null +++ b/test/integration/uexecutor/query_chain_meta_test.go @@ -0,0 +1,156 @@ +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, 1700000000)) + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[1], sdk.AccAddress(coreVal1).String(), chainId, 200_000_000_000, 12346, 1700000001)) + + 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.ObservedAts, 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}, + ObservedAts: []uint64{0}, + MedianIndex: 0, + })) + require.NoError(t, testApp.UexecutorKeeper.SetChainMeta(ctx, chainId2, uexecutortypes.ChainMeta{ + ObservedChainId: chainId2, + Signers: []string{"cosmos1def"}, + Prices: []uint64{200}, + ChainHeights: []uint64{2}, + ObservedAts: []uint64{0}, + 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}, + ObservedAts: []uint64{17000000, 17000001}, + 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}, + ObservedAts: []uint64{0}, + 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) + }) +} From 766dc91ac20c4ba00756a60b66a7f5c2aa933a3a Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 15:20:51 +0530 Subject: [PATCH 19/75] feat: added abi of uniswap quoter v2 --- x/uexecutor/types/abi.go | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/x/uexecutor/types/abi.go b/x/uexecutor/types/abi.go index c484d446..b318f58c 100644 --- a/x/uexecutor/types/abi.go +++ b/x/uexecutor/types/abi.go @@ -332,9 +332,58 @@ const UNIVERSAL_CORE_ABI = `[ "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" } ]` +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", @@ -724,6 +773,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)) } @@ -801,3 +854,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 +} From 9586e9b3e8e176dd9d587667236bb559b9dd0963 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 15:21:58 +0530 Subject: [PATCH 20/75] feat: added evm getter methods for uniswap quoter --- x/uexecutor/keeper/evm.go | 129 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 5 deletions(-) diff --git a/x/uexecutor/keeper/evm.go b/x/uexecutor/keeper/evm.go index 956ba68f..39fbe003 100644 --- a/x/uexecutor/keeper/evm.go +++ b/x/uexecutor/keeper/evm.go @@ -361,11 +361,130 @@ func (k Keeper) CallUniversalCoreSetChainMeta( ) } -// Calls Handler Contract to deposit prc20 tokens +// 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 uint32 + fee, ok := results[0].(uint32) + if !ok { + return nil, fmt.Errorf("unexpected type for defaultFeeTier: %T", results[0]) + } + + return new(big.Int).SetUint64(uint64(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) @@ -402,8 +521,8 @@ func (k Keeper) CallPRC20DepositAutoSwap( prc20Address, amount, to, - big.NewInt(0), - big.NewInt(0), - big.NewInt(0), + fee, + minPCOut, + big.NewInt(0), // deadline = 0 → contract uses its default ) } From 9858c04c18be4547a8a1c92b7b7742714c8c8c54 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 15:22:40 +0530 Subject: [PATCH 21/75] feat: added fetching of minPC on chain side for inbound gas --- x/uexecutor/keeper/execute_inbound_gas.go | 48 ++++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/x/uexecutor/keeper/execute_inbound_gas.go b/x/uexecutor/keeper/execute_inbound_gas.go index f1388e8e..3d28d083 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() + } + } } } } From 84a2daeef4d5a4b38b1efdae787d95f18349c20c Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 15:22:46 +0530 Subject: [PATCH 22/75] feat: added fetching of minPC on chain side for inbound gas and payload --- .../keeper/execute_inbound_gas_and_payload.go | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/x/uexecutor/keeper/execute_inbound_gas_and_payload.go b/x/uexecutor/keeper/execute_inbound_gas_and_payload.go index b6b52fc1..9a9f4420 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() + } + } } } } @@ -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{ @@ -177,7 +217,7 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive return nil } - // --- Step 6: execute payload + // --- Step 7: execute payload // ueaAddr is already resolved and validated in step 3 receipt, err = k.ExecutePayloadV2( ctx, From 83c4cdc08b66bc1df4e74c682125dae141af6b36 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 17:26:39 +0530 Subject: [PATCH 23/75] feat: added gas_price and gas_fee in Outbound proto --- proto/uexecutor/v1/types.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proto/uexecutor/v1/types.proto b/proto/uexecutor/v1/types.proto index 63a552fd..58fb1d06 100644 --- a/proto/uexecutor/v1/types.proto +++ b/proto/uexecutor/v1/types.proto @@ -167,6 +167,8 @@ 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 } message UniversalTx { From 281bae659f576cd7c09b7f90e32eee0b97f13f0f Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 17:26:51 +0530 Subject: [PATCH 24/75] refactor: added generated protobuf --- api/uexecutor/v1/types.pulsar.go | 423 +++++++++++++++++++++---------- 1 file changed, 287 insertions(+), 136 deletions(-) diff --git a/api/uexecutor/v1/types.pulsar.go b/api/uexecutor/v1/types.pulsar.go index 6f3d4cbd..e41fdf0c 100644 --- a/api/uexecutor/v1/types.pulsar.go +++ b/api/uexecutor/v1/types.pulsar.go @@ -5779,6 +5779,8 @@ 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 ) func init() { @@ -5799,6 +5801,8 @@ 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") } var _ protoreflect.Message = (*fastReflection_OutboundTx)(nil) @@ -5956,6 +5960,18 @@ 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 + } + } } // Has reports whether a field is populated. @@ -6001,6 +6017,10 @@ 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 != "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6047,6 +6067,10 @@ 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 = "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6108,6 +6132,12 @@ 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) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6158,6 +6188,10 @@ 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) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6220,6 +6254,10 @@ 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")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6267,6 +6305,10 @@ 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("") default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.OutboundTx")) @@ -6394,6 +6436,14 @@ 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.unknownFields != nil { n += len(x.unknownFields) } @@ -6423,6 +6473,24 @@ func (x *fastReflection_OutboundTx) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + 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 +7139,70 @@ 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 default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -11194,6 +11326,8 @@ 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 } func (x *OutboundTx) Reset() { @@ -11321,6 +11455,20 @@ 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 "" +} + type UniversalTx struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -11742,7 +11890,7 @@ var file_uexecutor_v1_types_proto_rawDesc = []byte{ 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, + 0x74, 0x78, 0x22, 0xe5, 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, @@ -11784,142 +11932,145 @@ var file_uexecutor_v1_types_proto_rawDesc = []byte{ 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, + 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, + 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, 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, 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, + 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, 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, } var ( From 8ded3f2c2443714291d92464abce36b54af4d9ab Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 17:27:44 +0530 Subject: [PATCH 25/75] feat: updated Outbound event parsing for gasPrice --- x/uexecutor/types/gateway_pc_event_decode.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x/uexecutor/types/gateway_pc_event_decode.go b/x/uexecutor/types/gateway_pc_event_decode.go index 8a2da39b..9cfc1a36 100644 --- a/x/uexecutor/types/gateway_pc_event_decode.go +++ b/x/uexecutor/types/gateway_pc_event_decode.go @@ -24,6 +24,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 +59,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 +67,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 +91,8 @@ 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 } From 7a9be1bc29a14f625a3120b7d896d796746f2abf Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 17:28:21 +0530 Subject: [PATCH 26/75] feat: updated Chain Outbound event --- x/uexecutor/keeper/create_outbound.go | 4 ++++ x/uexecutor/types/events.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/x/uexecutor/keeper/create_outbound.go b/x/uexecutor/keeper/create_outbound.go index 04ba8121..3f9e6f4d 100644 --- a/x/uexecutor/keeper/create_outbound.go +++ b/x/uexecutor/keeper/create_outbound.go @@ -70,7 +70,9 @@ 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(), TxType: event.TxType, PcTx: &types.OriginatingPcTx{ TxHash: receipt.Hash, @@ -201,7 +203,9 @@ func (k Keeper) attachOutboundsToUtx( AssetAddr: outbound.ExternalAssetAddr, Sender: outbound.Sender, Payload: outbound.Payload, + GasFee: outbound.GasFee, GasLimit: outbound.GasLimit, + GasPrice: outbound.GasPrice, TxType: outbound.TxType.String(), PcTxHash: pcTxHash, LogIndex: logIndex, diff --git a/x/uexecutor/types/events.go b/x/uexecutor/types/events.go index 8ad2f911..599c937e 100644 --- a/x/uexecutor/types/events.go +++ b/x/uexecutor/types/events.go @@ -21,7 +21,9 @@ 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"` TxType string `json:"tx_type"` PcTxHash string `json:"pc_tx_hash"` LogIndex string `json:"log_index"` @@ -49,7 +51,9 @@ 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("tx_type", e.TxType), sdk.NewAttribute("pc_tx_hash", e.PcTxHash), sdk.NewAttribute("log_index", e.LogIndex), From a16e40c52742d95b4435325c4e2e69efb0d6f057 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 17:28:36 +0530 Subject: [PATCH 27/75] feat: updated UniversalTxOutboundEventSig --- x/uexecutor/types/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/uexecutor/types/constants.go b/x/uexecutor/types/constants.go index 35d94535..53285709 100644 --- a/x/uexecutor/types/constants.go +++ b/x/uexecutor/types/constants.go @@ -43,5 +43,5 @@ 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() From f11d687b988dc6750ef4ceaa282c294c04482e48 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 17:29:10 +0530 Subject: [PATCH 28/75] tests: updated uvCore and ugPC bytecodes in test --- test/utils/bytecode.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/bytecode.go b/test/utils/bytecode.go index 18b36c61..72bf82bb 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 = "608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c908162bc574b146138ee5750806301ffc9a71461384d5780630379eae8146137f05780630ac6eb77146137445780631a4e49d41461371b5780631a873ce4146136e8578063240028e81461369e578063248a9ca31461364c5780632f2ff15d146135ef57806336568abe146135855780633f4ba83a1461347c5780634b1d2eeb1461343c5780634d20d0f8146134095780634eb7d1a1146133c957806355840b7d1461337a57806357724c41146132795780635b549182146132465780635c975abb146132055780636435967b146129d357806364f10e501461294e57806368c70c9e146129035780636d4008a8146128be578063780ad8271461215357806378a88127146120d857806381fbadad146120ba5780638377e2301461208657806383b94a5214611fd05780638456cb5914611ea557806391d1485414611e2e5780639be7fdb214611d43578063a217fddf14611d27578063a5172ddb14611cdc578063a861469f14611c92578063ad14d38514611c48578063af90f35114611b6a578063b5d8349f14611b09578063be0580c014611963578063c6f1b7e714611912578063d17c872c146117c3578063d547741f1461175c578063db9a0daf14611699578063dbc1b46414611638578063dcc16b5c146113d5578063dd19e7551461113d578063e201db9b1461080f578063e798646614610730578063ec87621c146106f5578063f8c8765e146103c3578063fa064472146102d2578063fb46e99d146102b45763fc6b5de80361000f57346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602061029e8161028b36600487016139e3565b8160405193828580945193849201613b07565b8101601281520301902054604051908152f35b80fd5b50346102b157806003193601126102b1576020600654604051908152f35b50346102b15760806003193601126102b15760043567ffffffffffffffff81116103bf576103a96103287f5e41bf0052b493123a63e4e0d9095ed4324108e489d58c9a0948b2be366ac8c69236906004016139e3565b602435604435606435908161038a6020604051868851918381818c0194610350818388613b07565b8101600b815203019020558460405183818b5161036e818388613b07565b8101601181520301902055604051809381928a51928391613b07565b8101601281520301902055604051948594608086526080860190613b28565b926020850152604084015260608301520390a180f35b5080fd5b50346102b15760806003193601126102b1576103dd613a29565b6103e5613a4c565b6103ed613a6f565b6064359173ffffffffffffffffffffffffffffffffffffffff83168093036106f1577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff8116801590816106e9575b60011490816106df575b1590816106d6575b506106ae579173ffffffffffffffffffffffffffffffffffffffff80949392838860017fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000859716177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610659575b506104d9614253565b6104e1614253565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561050d614253565b61051633613da7565b50167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a55167fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff000000000000000000000000000000000000000060085416176008557fffffffffffffffffffffffff000000000000000000000000000000000000000060095416176009556105c55780f35b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f6104d0565b6004877ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b9050155f610461565b303b159150610459565b87915061044f565b8480fd5b50346102b157806003193601126102b15760206040517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50346102b15760406003193601126102b15761074a613a29565b73ffffffffffffffffffffffffffffffffffffffff610767613a92565b91610770613c99565b169081156107e75760207f16ef4de07b0452a43221c91064fb645963a8e2e60bd8a7514da58d56e315c42291838552601082526107db81604087209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b6004837fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b5060e06003193601126102b157610824613a29565b9061082d613a4c565b91610836613aa1565b9160c4359173ffffffffffffffffffffffffffffffffffffffff83169160a4359190608435606435858703610de35773ffffffffffffffffffffffffffffffffffffffff600e541633036111155761088c6140a8565b6108946140fb565b8492889973ffffffffffffffffffffffffffffffffffffffff86169586156107e75773ffffffffffffffffffffffffffffffffffffffff82169788156110ed5789156110ed5734156110c55784156110c55762ffffff6108f48787613c5d565b9c1615611084575b1561102f575b854211611007576109bd60208d73ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a5416948b861090815f146110005786915b15610ff857905b604051958694859384937f1698ee820000000000000000000000000000000000000000000000000000000085526004850191604091949373ffffffffffffffffffffffffffffffffffffffff62ffffff9281606087019816865216602085015216910152565b03915afa908115610fed579073ffffffffffffffffffffffffffffffffffffffff918591610fbe575b501615610f9657803b15610de35782600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af18015610dd857908391610f81575b50600a546008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015234602482015292602092849260449284929091165af18015610dd857610f64575b50600a5473ffffffffffffffffffffffffffffffffffffffff169a6040519b610ac78d61391e565b8c528660208d015262ffffff16948560408d01523060608d015260808c01528960a08c01523460c08c01528160e08c01528160085473ffffffffffffffffffffffffffffffffffffffff169b6040519c8d917fdb3e219800000000000000000000000000000000000000000000000000000000835260048301610bb09173ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b815a9361010492602095f19a8b15610f5957829b610f21575b5081602073ffffffffffffffffffffffffffffffffffffffff600a5416604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015610dd857610f04575b506040517f42966c68000000000000000000000000000000000000000000000000000000008152836004820152602081602481868b5af18015610dd857610ed7575b508184610e14575b505089340397348911610de7578a3403610d12575b5050977f8c8071a0a45857f27eaa04a47ecdc04f0549d2150a7a1cb5eaa7111b6cf85f8d9260809260409a8b5193845260208401528a8301526060820152a460017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005582519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff600a5416803b15610de35782809160248c60405194859384927f2e1a7d4d00000000000000000000000000000000000000000000000000000000845260048401525af18015610dd8579183918b93610dbe575b5081809381925af1610d8a613c6a565b5015610d965780610ca3565b807f90b8ec180000000000000000000000000000000000000000000000000000000060049252fd5b610dcb9193508290613968565b6103bf578189915f610d7a565b6040513d85823e3d90fd5b8280fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602080830191825273ffffffffffffffffffffffffffffffffffffffff9490941660248301526044808301889052825290610e74606482613968565b519082895af115610ecb5780513d610ec25750843b155b610e96575f81610c8e565b80857f5274afe70000000000000000000000000000000000000000000000000000000060249352600452fd5b60011415610e8b565b604051903d90823e3d90fd5b610ef89060203d602011610efd575b610ef08183613968565b810190613b6b565b610c86565b503d610ee6565b610f1c9060203d602011610efd57610ef08183613968565b610c44565b909a506020813d602011610f51575b81610f3d60209383613968565b81010312610f4d5751995f610bc9565b5f80fd5b3d9150610f30565b6040513d84823e3d90fd5b610f7c9060203d602011610efd57610ef08183613968565b610a9f565b81610f8b91613968565b6103bf57815f610a34565b6004837f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b610fe0915060203d602011610fe6575b610fd88183613968565b810190613c31565b5f6109e6565b503d610fce565b6040513d86823e3d90fd5b508590610957565b8091610950565b6004837f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9450600654603c810290808204603c1490151715611057576110519042613c5d565b94610902565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8784526004602052604084205462ffffff169c508c6108fc576004847f3733548a000000000000000000000000000000000000000000000000000000008152fd5b6004847f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004847fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b6004837fbce361b0000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760406003193601126102b157611157613a29565b6024359081156113cb575b73ffffffffffffffffffffffffffffffffffffffff166040517fa0c50b690000000000000000000000000000000000000000000000000000000081528381600481855afa908115610fed57849161134e575b506040519173ffffffffffffffffffffffffffffffffffffffff825193602081818601966111e381838a613b07565b8101600c815203019020541692831561132657602061120d91604051809381928751928391613b07565b8101600b815203019020549081156112fe5784820294828604036112d1579460206004949596604051958680927ff97c007a0000000000000000000000000000000000000000000000000000000082525afa908115610ecb579061129d575b6112999350604051958695865260208601526040850152606084015260a0608084015260a0830190613b28565b0390f35b506020833d6020116112c9575b816112b760209383613968565b81010312610f4d57611299925161126c565b3d91506112aa565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6004867fe661aed0000000000000000000000000000000000000000000000000000000008152fd5b6004867fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b90503d8085833e61135f8183613968565b8101906020818303126106f15780519067ffffffffffffffff82116113c7570181601f820112156106f1578051611395816139a9565b926113a36040519485613968565b818452602082840101116113c7576113c19160208085019101613b07565b5f6111b4565b8580fd5b600f549150611162565b50346102b15760606003193601126102b15760043567ffffffffffffffff81116103bf576114079036906004016139e3565b61140f613a4c565b611417613aa1565b90611420613c99565b73ffffffffffffffffffffffffffffffffffffffff8116801561161057826114f29260209273ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541691821091825f146116095780925b1561160157506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015610fed5773ffffffffffffffffffffffffffffffffffffffff9185916115e2575b50169081156115ba57916115a89162ffffff7f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d9460405160208186516115628183858b01613b07565b8101600d815203019020837fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051948594606086526060860190613b28565b9260208501521660408301520390a180f35b6004847f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b6115fb915060203d602011610fe657610fd88183613968565b5f611519565b905090610957565b8192611486565b6004857fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602073ffffffffffffffffffffffffffffffffffffffff6116858261028b36600488016139e3565b8101600c8152030190205416604051908152f35b50346102b15760206003193601126102b1576004358180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611734576020817f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b92600655604051908152a180f35b6004827f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760406003193601126102b1576117bf60043561177c613a4c565b906117ba6117b5825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613d21565b613fa0565b5080f35b50346102b15760406003193601126102b1576117dd613a29565b6024359062ffffff8216809203610de3578280527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156118ea5773ffffffffffffffffffffffffffffffffffffffff1680156107e7576101f4821415806118de575b806118d2575b6118aa578252600460205260408220907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000082541617905580f35b6004837f3733548a000000000000000000000000000000000000000000000000000000008152fd5b50612710821415611870565b50610bb882141561186a565b6004837f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102b157806003193601126102b157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102b15760606003193601126102b15761197d613a29565b611985613a4c565b61198d613a6f565b918380527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040842073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611ae15773ffffffffffffffffffffffffffffffffffffffff1680158015611ac3575b8015611aa5575b6110ed5773ffffffffffffffffffffffffffffffffffffffff929183917fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff00000000000000000000000000000000000000006008541617600855167fffffffffffffffffffffffff0000000000000000000000000000000000000000600954161760095580f35b5073ffffffffffffffffffffffffffffffffffffffff831615611a08565b5073ffffffffffffffffffffffffffffffffffffffff821615611a01565b6004847f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602073ffffffffffffffffffffffffffffffffffffffff611b568261028b36600488016139e3565b8101600d8152030190205416604051908152f35b50346102b15760206003193601126102b157611b84613a29565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156117345773ffffffffffffffffffffffffffffffffffffffff168015611c20577fffffffffffffffffffffffff0000000000000000000000000000000000000000600e541617600e5580f35b6004827fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b15760ff604060209273ffffffffffffffffffffffffffffffffffffffff611c7e613a29565b168152600384522054166040519015158152f35b50346102b15760206003193601126102b15762ffffff604060209273ffffffffffffffffffffffffffffffffffffffff611cca613a29565b16815260048452205416604051908152f35b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b1576020611d148161028b36600487016139e3565b8101600b81520301902054604051908152f35b50346102b157806003193601126102b157602090604051908152f35b50346102b15760406003193601126102b15760043567ffffffffffffffff81116103bf57611d759036906004016139e3565b73ffffffffffffffffffffffffffffffffffffffff611d92613a4c565b611d9a613c99565b1680156107e7577f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94991611e22916040516020818451611ddc8183858901613b07565b8101600c815203019020817fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051928392604084526040840190613b28565b9060208301520390a180f35b50346102b15760406003193601126102b15773ffffffffffffffffffffffffffffffffffffffff6040611e5f613a4c565b9260043581527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020522091165f52602052602060ff60405f2054166040519015158152f35b50346102b157806003193601126102b1578080527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040812073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611fa857611f126140a8565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b807f49e27cff0000000000000000000000000000000000000000000000000000000060049252fd5b50346102b15760206003193601126102b157611fea613a29565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156117345773ffffffffffffffffffffffffffffffffffffffff168015611c20577fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102b157806003193601126102b157602073ffffffffffffffffffffffffffffffffffffffff600e5416604051908152f35b50346102b157806003193601126102b1576020600f54604051908152f35b50346102b1576120e736613ab3565b9083809394527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156118ea57612150929361214b6140a8565b613b83565b80f35b50346102b15760c06003193601126102b15761216d613a29565b60243590612179613a6f565b906064359262ffffff8416908185036113c75760843560a4359373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303612896576121d86140a8565b6121e06140fb565b6121eb868483614172565b8473ffffffffffffffffffffffffffffffffffffffff821697888a52600360205260ff60408b2054161561286e57941561282d575b156127d8575b8442116127b0576020846122e3928a73ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541690818d10805f146127a95781935b501561160157506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156127125773ffffffffffffffffffffffffffffffffffffffff91899161278a575b50161561276257801561273a576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018390526020816044818b8b5af180156127125761271d575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018390526020816044818b8b5af18015612712576126f5575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a541693604051946123ee8661391e565b8886526020808701918252929091166040808701828152306060890190815260808901998a5260a0890188815260c08a0188815260e08b018f815260085495517f414bf3890000000000000000000000000000000000000000000000000000000081529b5173ffffffffffffffffffffffffffffffffffffffff90811660048e01529751881660248d0152935162ffffff1660448c01529151861660648b0152995160848a0152985160a4890152975160c48801529651821660e48701529585916101049183918c91165af192831561268e5787936126c1575b5082106126995773ffffffffffffffffffffffffffffffffffffffff60085416604051907f095ea7b300000000000000000000000000000000000000000000000000000000825260048201528660248201526020816044818a8a5af1801561268e57612671575b508573ffffffffffffffffffffffffffffffffffffffff600a5416803b156103bf578180916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528960048401525af18015610f595761265c575b5080808085885af16125a3613c6a565b501561263457927ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e2949273ffffffffffffffffffffffffffffffffffffffff9260c09584600a54169060405196875260208701526040860152606085015260808401521660a0820152a160017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6004867f90b8ec18000000000000000000000000000000000000000000000000000000008152fd5b8161266691613968565b6113c757855f612593565b6126899060203d602011610efd57610ef08183613968565b61252f565b6040513d89823e3d90fd5b6004867f8199f5f3000000000000000000000000000000000000000000000000000000008152fd5b9092506020813d6020116126ed575b816126dd60209383613968565b81010312610f4d5751915f6124c8565b3d91506126d0565b61270d9060203d602011610efd57610ef08183613968565b6123c2565b6040513d8a823e3d90fd5b6127359060203d602011610efd57610ef08183613968565b61235f565b6004877f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004877f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b6127a3915060203d602011610fe657610fd88183613968565b5f61230a565b8293612276565b6004887f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9350600654603c810290808204603c1490151715612800576127fa9042613c5d565b93612226565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8789526004602052604089205462ffffff16945084612220576004897f3733548a000000000000000000000000000000000000000000000000000000008152fd5b60048a7f4e38f95a000000000000000000000000000000000000000000000000000000008152fd5b6004887f53e51723000000000000000000000000000000000000000000000000000000008152fd5b50346102b15760206003193601126102b157604060209173ffffffffffffffffffffffffffffffffffffffff6128f2613a29565b168152600583522054604051908152f35b50346102b15760206003193601126102b1576004359067ffffffffffffffff82116102b157602061293b8161028b36600487016139e3565b8101601181520301902054604051908152f35b50346102b15761295d36613ab3565b9073ffffffffffffffffffffffffffffffffffffffff9392937f00000000000000000000000000000000000000000000000000000000000000001633036129ab57612150929361214b6140a8565b6004837f53e51723000000000000000000000000000000000000000000000000000000008152fd5b5034610f4d5760c0600319360112610f4d576129ed613a29565b6024356129f8613a6f565b6064358015918215809203610f4d5760843562ffffff811690818103610f4d5760a43573ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036131dd57612a606140a8565b612a686140fb565b612a7384888a614172565b5f9515612b925750506040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101869052919050602082806044810103818a73ffffffffffffffffffffffffffffffffffffffff8b165af190811561268e577ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49460609473ffffffffffffffffffffffffffffffffffffffff948594612b73575b505b6040519788526020880152604087015216941692a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b612b8b9060203d602011610efd57610ef08183613968565b505f612b35565b809192939550156131b55773ffffffffffffffffffffffffffffffffffffffff871691825f52600360205260ff60405f2054161561318d57921561314b575b600654603c810290808204603c149015171561311e57612bf19042613c5d565b8042116130f657612ca960208573ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a541680881090815f146130ef578d915b156130e7576040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015612fe25773ffffffffffffffffffffffffffffffffffffffff915f916130c8575b5016156130a0576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018890526020816044815f885af18015612fe257613083575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018890526020816044815f885af18015612fe257613066575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169460405195612dae8761391e565b858752602087015216604085015230606085015260808401528560a08401528060c08401525f60e08401526020612e9861010473ffffffffffffffffffffffffffffffffffffffff60085416955f60405197889485937f414bf389000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1928315612fe2575f93613032575b50821061300a5760205f91604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015612fe257612fed575b5073ffffffffffffffffffffffffffffffffffffffff600a5416803b15610f4d575f80916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528760048401525af18015612fe257612fcd575b508580808084875af1612f85613c6a565b50156126345773ffffffffffffffffffffffffffffffffffffffff7ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e493606093829390612b37565b612fda9196505f90613968565b5f945f612f74565b6040513d5f823e3d90fd5b6130059060203d602011610efd57610ef08183613968565b612f11565b7f8199f5f3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d60201161305e575b8161304e60209383613968565b81010312610f4d5751915f612ea8565b3d9150613041565b61307e9060203d602011610efd57610ef08183613968565b612d82565b61309b9060203d602011610efd57610ef08183613968565b612d1f565b7f76ecffc0000000000000000000000000000000000000000000000000000000005f5260045ffd5b6130e1915060203d602011610fe657610fd88183613968565b5f612cd0565b508c90610957565b8091612c3e565b7f1ab7da6b000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9150805f52600460205262ffffff60405f2054169182612bd1577f3733548a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e38f95a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f22c50cbf000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f53e51723000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d575f600319360112610f4d57602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610f4d575f600319360112610f4d57602073ffffffffffffffffffffffffffffffffffffffff60075416604051908152f35b34610f4d576040600319360112610f4d57613292613a29565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040902054602435919060ff16156133525773ffffffffffffffffffffffffffffffffffffffff16801561332a576113888211613302575f52600560205260405f20555f80f35b7fc31c0b6e000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f49e27cff000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d576020600319360112610f4d57335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff161561335257600435600f55005b34610f4d576020600319360112610f4d576004355f526002602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610f4d575f600319360112610f4d57602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b34610f4d576020600319360112610f4d576004355f526001602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610f4d575f600319360112610f4d57335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff1615613352577fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff81161561355d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d576040600319360112610f4d5761359e613a4c565b3373ffffffffffffffffffffffffffffffffffffffff8216036135c75761001a90600435613fa0565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610f4d576040600319360112610f4d5761001a60043561360e613a4c565b906136476117b5825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613e8e565b34610f4d576020600319360112610f4d5760206136966004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b34610f4d576020600319360112610f4d5773ffffffffffffffffffffffffffffffffffffffff6136cc613a29565b165f526010602052602060ff60405f2054166040519015158152f35b34610f4d575f600319360112610f4d57602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b34610f4d576020600319360112610f4d576004355f525f602052602060405f2054604051908152f35b34610f4d576040600319360112610f4d5761375d613a29565b613765613a92565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156133525773ffffffffffffffffffffffffffffffffffffffff61001a92165f52600360205260405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b34610f4d576040600319360112610f4d5760043567ffffffffffffffff8111610f4d576138219036906004016139e3565b60206138366040519283815193849201613b07565b810190600b82526020816024359303019020555f80f35b34610f4d576020600319360112610f4d576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610f4d57807f7965db0b00000000000000000000000000000000000000000000000000000000602092149081156138c4575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014826138b9565b34610f4d575f600319360112610f4d5760209073ffffffffffffffffffffffffffffffffffffffff600854168152f35b610100810190811067ffffffffffffffff82111761393b57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761393b57604052565b67ffffffffffffffff811161393b57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f82011215610f4d578035906139fa826139a9565b92613a086040519485613968565b82845260208383010111610f4d57815f926020809301838601378301015290565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610f4d57565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610f4d57565b6044359073ffffffffffffffffffffffffffffffffffffffff82168203610f4d57565b602435908115158203610f4d57565b6044359062ffffff82168203610f4d57565b6003196060910112610f4d5760043573ffffffffffffffffffffffffffffffffffffffff81168103610f4d57906024359060443573ffffffffffffffffffffffffffffffffffffffff81168103610f4d5790565b5f5b838110613b185750505f910152565b8181015183820152602001613b09565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093613b6481518092818752878088019101613b07565b0116010190565b90816020910312610f4d57518015158103610f4d5790565b90602091613c0493613b96818484614172565b5f73ffffffffffffffffffffffffffffffffffffffff6040518097819682957f47e7ef24000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0393165af18015612fe257613c165750565b613c2e9060203d602011610efd57610ef08183613968565b50565b90816020910312610f4d575173ffffffffffffffffffffffffffffffffffffffff81168103610f4d5790565b9190820180921161311e57565b3d15613c94573d90613c7b826139a9565b91613c896040519384613968565b82523d5f602084013e565b606090565b335f9081527f06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a602052604090205460ff1615613cd157565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0860245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615613d785750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613e895773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f14613f9a57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f14613f9a57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166140d357565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00541461414a5760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919073ffffffffffffffffffffffffffffffffffffffff161561332a5773ffffffffffffffffffffffffffffffffffffffff16801561332a5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168114908115614249575b5061422157156141f957565b7f1f2a2005000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f82d5d76a000000000000000000000000000000000000000000000000000000005f5260045ffd5b905030145f6141ed565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561428257565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea26469706673582212203646e3ee15c982505d4331c1a1af22a6dce9040f03c82da9a65983e246eeb0a764736f6c634300081a0033" +const HANDLER_CONTRACT_BYTECODE = "608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c908162bc574b146137825750806301ffc9a7146136e15780630379eae8146136815780630ac6eb77146135d5578063172bfc1c146135595780631a4e49d4146135305780631a873ce4146134fd578063240028e8146134b3578063248a9ca3146134615780632f2ff15d1461340457806336568abe1461339a5780633f4ba83a146132915780634b1d2eeb146132515780634d20d0f81461321e5780634eb7d1a1146131de57806357724c41146130dd5780635b549182146130aa5780635c975abb14613069578063606b05a414612ffc5780636435967b1461282f57806364f10e501461281457806368c70c9e146127c95780636ca752e31461277e5780636d4008a814612739578063780ad8271461203357806378a8812714611fb857806381fbadad14611f9a5780638377e23014611f6657806383b94a5214611eb05780638456cb5914611d8557806391d1485414611d0e5780639be7fdb214611c23578063a217fddf14611c07578063a5172ddb14611bbc578063a861469f14611b72578063ad14d38514611b28578063af90f35114611a4a578063b5d8349f146119e9578063be0580c014611843578063c6f1b7e7146117f2578063cd20c6e8146117ad578063d17c872c14611687578063d547741f14611620578063db9a0daf1461155d578063dbc1b464146114fc578063dcc16b5c146112be578063dd19e7551461102a578063e798646614610f4b578063ec87621c14610f10578063f881446714610716578063f8c8765e146103e4578063fa064472146102f3578063fb46e99d146102d55763fc6b5de80361000f57346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d25760206102bf816102ac3660048701613877565b81604051938285809451938492016139cd565b8101601281520301902054604051908152f35b80fd5b50346102d257806003193601126102d2576020600654604051908152f35b50346102d25760806003193601126102d25760043567ffffffffffffffff81116103e0576103ca6103497f5e41bf0052b493123a63e4e0d9095ed4324108e489d58c9a0948b2be366ac8c6923690600401613877565b60243560443560643590816103ab6020604051868851918381818c01946103718183886139cd565b8101600b815203019020558460405183818b5161038f8183886139cd565b8101601181520301902055604051809381928a519283916139cd565b81016012815203019020556040519485946080865260808601906139ee565b926020850152604084015260608301520390a180f35b5080fd5b50346102d25760806003193601126102d2576103fe6138ef565b610406613912565b61040e613935565b6064359173ffffffffffffffffffffffffffffffffffffffff8316809303610712577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff81168015908161070a575b6001149081610700575b1590816106f7575b506106cf579173ffffffffffffffffffffffffffffffffffffffff80949392838860017fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000859716177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005561067a575b506104fa614135565b610502614135565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561052e614135565b61053733613c89565b50167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a55167fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff000000000000000000000000000000000000000060085416176008557fffffffffffffffffffffffff000000000000000000000000000000000000000060095416176009556105e65780f35b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f6104f1565b6004877ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b9050155f610482565b303b15915061047a565b879150610470565b8480fd5b5060a06003193601126102d25761072b6138ef565b90610734613967565b9160443591606435936084359273ffffffffffffffffffffffffffffffffffffffff8416928385036102d25773ffffffffffffffffffffffffffffffffffffffff601054163303610ee857610787613f8a565b61078f613fdd565b8691839773ffffffffffffffffffffffffffffffffffffffff8216948515610ec0578615610ec0573415610e98578815610e985762ffffff1615610e56575b15610e2e575b824211610e065761088f60208973ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a54169488861090815f14610dff5786915b15610df757905b604051958694859384937f1698ee820000000000000000000000000000000000000000000000000000000085526004850191604091949373ffffffffffffffffffffffffffffffffffffffff62ffffff9281606087019816865216602085015216910152565b03915afa908115610c98579073ffffffffffffffffffffffffffffffffffffffff918491610dc8575b501615610da057803b156103e05781600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af18015610d0157908291610d8b575b50600a546008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015234602482015292602092849260449284929091165af18015610d0157610d6e575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a5416976040519861099d8a6137b2565b89528460208a0152169182604089015230606089015260808801528560a08801523460c08801528060e08801526020610a8961010473ffffffffffffffffffffffffffffffffffffffff6008541699846040519b8c9485937fdb3e2198000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1968715610d61578197610d29575b5080602073ffffffffffffffffffffffffffffffffffffffff600a5416604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015610d0157610d0c575b506040517f42966c6800000000000000000000000000000000000000000000000000000000815286600482015260208160248185885af18015610d0157610cd4575b5086340394348611610ca757873403610bd3575b505060606040967f01fd625a5ce1109c10761818e2ef64ea92cd4966d78086d37e5a4b50e322687892885191825287602083015288820152a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005582519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff600a5416803b15610ca3578280916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c60048401525af18015610c98579183918893610c7e575b5081809381925af1610c4a613b4c565b5015610c565780610b6a565b807f90b8ec180000000000000000000000000000000000000000000000000000000060049252fd5b610c8b91935082906137fc565b6103e0578186915f610c3a565b6040513d85823e3d90fd5b8280fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b610cf59060203d602011610cfa575b610ced81836137fc565b810190613a4d565b610b56565b503d610ce3565b6040513d84823e3d90fd5b610d249060203d602011610cfa57610ced81836137fc565b610b14565b9096506020813d602011610d59575b81610d45602093836137fc565b81010312610d555751955f610a99565b5f80fd5b3d9150610d38565b50604051903d90823e3d90fd5b610d869060203d602011610cfa57610ced81836137fc565b610971565b81610d95916137fc565b6102d257805f610906565b6004827f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b610dea915060203d602011610df0575b610de281836137fc565b810190613b13565b5f6108b8565b503d610dd8565b508590610829565b8091610822565b6004827f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9150600654603c810290808204603c1490151715610ca757610e509042613b3f565b916107d4565b8483526004602052604083205462ffffff169850886107ce575b6004837f3733548a000000000000000000000000000000000000000000000000000000008152fd5b6004847f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004847fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b807fbce361b00000000000000000000000000000000000000000000000000000000060049252fd5b50346102d257806003193601126102d25760206040517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50346102d25760406003193601126102d257610f656138ef565b73ffffffffffffffffffffffffffffffffffffffff610f82613958565b91610f8b613b7b565b169081156110025760207f16ef4de07b0452a43221c91064fb645963a8e2e60bd8a7514da58d56e315c42291838552600f8252610ff681604087209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b6004837fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760406003193601126102d2576110446138ef565b73ffffffffffffffffffffffffffffffffffffffff6024359116906040517fa0c50b690000000000000000000000000000000000000000000000000000000081528381600481865afa9081156112b3578491611236575b5060405191815192602081818501956110b58183896139cd565b81016014815203019020549080155f146111f75750925b73ffffffffffffffffffffffffffffffffffffffff60405160208185516110f481838a6139cd565b8101600c81520301902054169283156111cf57602061111e916040518093819287519283916139cd565b8101600b815203019020549081156111a757848202948286040361117a57856040916111769596975260136020522054604051958695865260208601526040850152606084015260a0608084015260a08301906139ee565b0390f35b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6004867fe661aed0000000000000000000000000000000000000000000000000000000008152fd5b6004867fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b939080851061120657506110cc565b85604491867fff632bea000000000000000000000000000000000000000000000000000000008352600452602452fd5b90503d8085833e61124781836137fc565b8101906020818303126107125780519067ffffffffffffffff82116112af570181601f8201121561071257805161127d8161383d565b9261128b60405194856137fc565b818452602082840101116112af576112a991602080850191016139cd565b5f61109b565b8580fd5b6040513d86823e3d90fd5b50346102d25760606003193601126102d25760043567ffffffffffffffff81116103e0576112f0903690600401613877565b6112f8613912565b60443562ffffff81169182820361071257611311613b7b565b73ffffffffffffffffffffffffffffffffffffffff811680156111cf57916020916113e39373ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541691821091825f146114f55780925b156114ed57506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156112b35773ffffffffffffffffffffffffffffffffffffffff9185916114ce575b50169081156114a65791611495917f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d93604051602081855161144f8183858a016139cd565b8101600d815203019020827fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790556040519384936060855260608501906139ee565b91602084015260408301520390a180f35b6004847f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b6114e7915060203d602011610df057610de281836137fc565b5f61140a565b905090610829565b8192611377565b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d257602073ffffffffffffffffffffffffffffffffffffffff611549826102ac3660048801613877565b8101600c8152030190205416604051908152f35b50346102d25760206003193601126102d2576004358180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115f8576020817f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b92600655604051908152a180f35b6004827f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760406003193601126102d257611683600435611640613912565b9061167e611679825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613c03565b613e82565b5080f35b50346102d25760406003193601126102d2576116a16138ef565b6116a9613967565b908280527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156117855773ffffffffffffffffffffffffffffffffffffffff169081156110025762ffffff16906101f482141580611779575b8061176d575b610e70578252600460205260408220907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000082541617905580f35b50612710821415611733565b50610bb882141561172d565b6004837f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d257604060209173ffffffffffffffffffffffffffffffffffffffff6117e16138ef565b168152601383522054604051908152f35b50346102d257806003193601126102d257602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102d25760606003193601126102d25761185d6138ef565b611865613912565b61186d613935565b918380527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040842073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156119c15773ffffffffffffffffffffffffffffffffffffffff16801580156119a3575b8015611985575b610ec05773ffffffffffffffffffffffffffffffffffffffff929183917fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff00000000000000000000000000000000000000006008541617600855167fffffffffffffffffffffffff0000000000000000000000000000000000000000600954161760095580f35b5073ffffffffffffffffffffffffffffffffffffffff8316156118e8565b5073ffffffffffffffffffffffffffffffffffffffff8216156118e1565b6004847f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d257602073ffffffffffffffffffffffffffffffffffffffff611a36826102ac3660048801613877565b8101600d8152030190205416604051908152f35b50346102d25760206003193601126102d257611a646138ef565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115f85773ffffffffffffffffffffffffffffffffffffffff168015611b00577fffffffffffffffffffffffff0000000000000000000000000000000000000000601054161760105580f35b6004827fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d25760ff604060209273ffffffffffffffffffffffffffffffffffffffff611b5e6138ef565b168152600384522054166040519015158152f35b50346102d25760206003193601126102d25762ffffff604060209273ffffffffffffffffffffffffffffffffffffffff611baa6138ef565b16815260048452205416604051908152f35b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d2576020611bf4816102ac3660048701613877565b8101600b81520301902054604051908152f35b50346102d257806003193601126102d257602090604051908152f35b50346102d25760406003193601126102d25760043567ffffffffffffffff81116103e057611c55903690600401613877565b73ffffffffffffffffffffffffffffffffffffffff611c72613912565b611c7a613b7b565b168015611002577f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94991611d02916040516020818451611cbc81838589016139cd565b8101600c815203019020817fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790556040519283926040845260408401906139ee565b9060208301520390a180f35b50346102d25760406003193601126102d25773ffffffffffffffffffffffffffffffffffffffff6040611d3f613912565b9260043581527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020522091165f52602052602060ff60405f2054166040519015158152f35b50346102d257806003193601126102d2578080527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040812073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611e8857611df2613f8a565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b807f49e27cff0000000000000000000000000000000000000000000000000000000060049252fd5b50346102d25760206003193601126102d257611eca6138ef565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115f85773ffffffffffffffffffffffffffffffffffffffff168015611b00577fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102d257806003193601126102d257602073ffffffffffffffffffffffffffffffffffffffff60105416604051908152f35b50346102d257806003193601126102d2576020600e54604051908152f35b50346102d257611fc736613979565b9083809394527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f2054161561178557612030929361202b613f8a565b613a65565b80f35b50346102d25760c06003193601126102d25761204d6138ef565b60243590612059613935565b906064359262ffffff8416908185036112af5760843560a4359361207b613f8a565b612083613fdd565b61208e868483614054565b8473ffffffffffffffffffffffffffffffffffffffff821697888a52600360205260ff60408b205416156127115794156126d0575b1561267b575b84421161265357602084612186928a73ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541690818d10805f1461264c5781935b50156114ed57506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156125b55773ffffffffffffffffffffffffffffffffffffffff91899161262d575b5016156126055780156125dd576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018390526020816044818b8b5af180156125b5576125c0575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018390526020816044818b8b5af180156125b557612598575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169360405194612291866137b2565b8886526020808701918252929091166040808701828152306060890190815260808901998a5260a0890188815260c08a0188815260e08b018f815260085495517f414bf3890000000000000000000000000000000000000000000000000000000081529b5173ffffffffffffffffffffffffffffffffffffffff90811660048e01529751881660248d0152935162ffffff1660448c01529151861660648b0152995160848a0152985160a4890152975160c48801529651821660e48701529585916101049183918c91165af1928315612531578793612564575b50821061253c5773ffffffffffffffffffffffffffffffffffffffff60085416604051907f095ea7b300000000000000000000000000000000000000000000000000000000825260048201528660248201526020816044818a8a5af1801561253157612514575b508573ffffffffffffffffffffffffffffffffffffffff600a5416803b156103e0578180916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528960048401525af18015610d01576124ff575b5080808085885af1612446613b4c565b50156124d757927ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e2949273ffffffffffffffffffffffffffffffffffffffff9260c09584600a54169060405196875260208701526040860152606085015260808401521660a0820152a160017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6004867f90b8ec18000000000000000000000000000000000000000000000000000000008152fd5b81612509916137fc565b6112af57855f612436565b61252c9060203d602011610cfa57610ced81836137fc565b6123d2565b6040513d89823e3d90fd5b6004867f8199f5f3000000000000000000000000000000000000000000000000000000008152fd5b9092506020813d602011612590575b81612580602093836137fc565b81010312610d555751915f61236b565b3d9150612573565b6125b09060203d602011610cfa57610ced81836137fc565b612265565b6040513d8a823e3d90fd5b6125d89060203d602011610cfa57610ced81836137fc565b612202565b6004877f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004877f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b612646915060203d602011610df057610de281836137fc565b5f6121ad565b8293612119565b6004887f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9350600654603c810290808204603c14901517156126a35761269d9042613b3f565b936120c9565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8789526004602052604089205462ffffff169450846120c3576004897f3733548a000000000000000000000000000000000000000000000000000000008152fd5b60048a7f4e38f95a000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d257604060209173ffffffffffffffffffffffffffffffffffffffff61276d6138ef565b168152600583522054604051908152f35b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d25760206127b6816102ac3660048701613877565b8101601481520301902054604051908152f35b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d2576020612801816102ac3660048701613877565b8101601181520301902054604051908152f35b50346102d25761203061282636613979565b9161202b613f8a565b5034610d555760c0600319360112610d55576128496138ef565b602435612854613935565b6064358015918215809203610d555760843562ffffff811690818103610d555760a43561287f613f8a565b612887613fdd565b61289284888a614054565b5f95156129b15750506040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101869052919050602082806044810103818a73ffffffffffffffffffffffffffffffffffffffff8b165af1908115612531577ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49460609473ffffffffffffffffffffffffffffffffffffffff948594612992575b505b6040519788526020880152604087015216941692a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6129aa9060203d602011610cfa57610ced81836137fc565b505f612954565b80919293955015612fd45773ffffffffffffffffffffffffffffffffffffffff871691825f52600360205260ff60405f20541615612fac579215612f6a575b600654603c810290808204603c1490151715612f3d57612a109042613b3f565b804211612f1557612ac860208573ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a541680881090815f14612f0e578d915b15612f06576040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015612e015773ffffffffffffffffffffffffffffffffffffffff915f91612ee7575b501615612ebf576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018890526020816044815f885af18015612e0157612ea2575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018890526020816044815f885af18015612e0157612e85575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169460405195612bcd876137b2565b858752602087015216604085015230606085015260808401528560a08401528060c08401525f60e08401526020612cb761010473ffffffffffffffffffffffffffffffffffffffff60085416955f60405197889485937f414bf389000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1928315612e01575f93612e51575b508210612e295760205f91604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015612e0157612e0c575b5073ffffffffffffffffffffffffffffffffffffffff600a5416803b15610d55575f80916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528760048401525af18015612e0157612dec575b508580808084875af1612da4613b4c565b50156124d75773ffffffffffffffffffffffffffffffffffffffff7ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e493606093829390612956565b612df99196505f906137fc565b5f945f612d93565b6040513d5f823e3d90fd5b612e249060203d602011610cfa57610ced81836137fc565b612d30565b7f8199f5f3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d602011612e7d575b81612e6d602093836137fc565b81010312610d555751915f612cc7565b3d9150612e60565b612e9d9060203d602011610cfa57610ced81836137fc565b612ba1565b612eba9060203d602011610cfa57610ced81836137fc565b612b3e565b7f76ecffc0000000000000000000000000000000000000000000000000000000005f5260045ffd5b612f00915060203d602011610df057610de281836137fc565b5f612aef565b508c90610829565b8091612a5d565b7f1ab7da6b000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9150805f52600460205262ffffff60405f20541691826129f0577f3733548a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e38f95a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f22c50cbf000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55577f882f47825d4043cd04a564cad4f524a7fe00a604ae024c23dbc8065b77668b4761302b366138bd565b90613034613b7b565b81604051602081845161304a81838589016139cd565b810160148152030190205561306460405192839283613a31565b0390a1005b34610d55575f600319360112610d5557602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610d55575f600319360112610d5557602073ffffffffffffffffffffffffffffffffffffffff60075416604051908152f35b34610d55576040600319360112610d55576130f66138ef565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040902054602435919060ff16156131b65773ffffffffffffffffffffffffffffffffffffffff16801561318e576113888211613166575f52600560205260405f20555f80f35b7fc31c0b6e000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f49e27cff000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55576020600319360112610d55576004355f526002602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610d55575f600319360112610d5557602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b34610d55576020600319360112610d55576004355f526001602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610d55575f600319360112610d5557335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131b6577fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff811615613372577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55576040600319360112610d55576133b3613912565b3373ffffffffffffffffffffffffffffffffffffffff8216036133dc5761001a90600435613e82565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55576040600319360112610d555761001a600435613423613912565b9061345c611679825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613d70565b34610d55576020600319360112610d555760206134ab6004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b34610d55576020600319360112610d555773ffffffffffffffffffffffffffffffffffffffff6134e16138ef565b165f52600f602052602060ff60405f2054166040519015158152f35b34610d55575f600319360112610d5557602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b34610d55576020600319360112610d55576004355f525f602052602060405f2054604051908152f35b34610d55576040600319360112610d55576135726138ef565b73ffffffffffffffffffffffffffffffffffffffff60243591613593613b7b565b1690811561318e5760207f911a025fb070fa2a29c37a3bf4c00d16acf15583cd050f17bdbacbab7e72320391835f52601382528060405f2055604051908152a2005b34610d55576040600319360112610d55576135ee6138ef565b6135f6613958565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131b65773ffffffffffffffffffffffffffffffffffffffff61001a92165f52600360205260405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b34610d55577f6a59d469e3757d6e139cdf95b12740f585d553afac49b90bdbe278502a4427186136b0366138bd565b908160405160208184516136c781838589016139cd565b8101600b8152030190205561306460405192839283613a31565b34610d55576020600319360112610d55576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610d5557807f7965db0b0000000000000000000000000000000000000000000000000000000060209214908115613758575b506040519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148261374d565b34610d55575f600319360112610d555760209073ffffffffffffffffffffffffffffffffffffffff600854168152f35b610100810190811067ffffffffffffffff8211176137cf57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176137cf57604052565b67ffffffffffffffff81116137cf57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f82011215610d555780359061388e8261383d565b9261389c60405194856137fc565b82845260208383010111610d5557815f926020809301838601378301015290565b6040600319820112610d55576004359067ffffffffffffffff8211610d55576138e891600401613877565b9060243590565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610d5557565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610d5557565b6044359073ffffffffffffffffffffffffffffffffffffffff82168203610d5557565b602435908115158203610d5557565b6024359062ffffff82168203610d5557565b6003196060910112610d555760043573ffffffffffffffffffffffffffffffffffffffff81168103610d5557906024359060443573ffffffffffffffffffffffffffffffffffffffff81168103610d555790565b5f5b8381106139de5750505f910152565b81810151838201526020016139cf565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093613a2a815180928187528780880191016139cd565b0116010190565b929190613a486020916040865260408601906139ee565b930152565b90816020910312610d5557518015158103610d555790565b90602091613ae693613a78818484614054565b5f73ffffffffffffffffffffffffffffffffffffffff6040518097819682957f47e7ef24000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0393165af18015612e0157613af85750565b613b109060203d602011610cfa57610ced81836137fc565b50565b90816020910312610d55575173ffffffffffffffffffffffffffffffffffffffff81168103610d555790565b91908201809211612f3d57565b3d15613b76573d90613b5d8261383d565b91613b6b60405193846137fc565b82523d5f602084013e565b606090565b335f9081527f06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a602052604090205460ff1615613bb357565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0860245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615613c5a5750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613d6b5773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f14613e7c57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f14613e7c57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416613fb557565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00541461402c5760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919073ffffffffffffffffffffffffffffffffffffffff161561318e5773ffffffffffffffffffffffffffffffffffffffff16801561318e5773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016811490811561412b575b5061410357156140db57565b7f1f2a2005000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f82d5d76a000000000000000000000000000000000000000000000000000000005f5260045ffd5b905030145f6140cf565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561416457565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea26469706673582212200a731130a8c5bcf01626a6f678a302cf572f981bffc866cffc5f6e8689e9ff9e64736f6c634300081a0033" const PRC20_CREATION_BYTECODE = "608060405234801561000f575f80fd5b50600436106101a5575f3560e01c806374be2150116100e8578063c701262611610093578063eddeb1231161006e578063eddeb12314610457578063f687d12a1461046a578063f97c007a1461047d578063fc5fecd514610486575f80fd5b8063c7012626146103cb578063d9eeebed146103de578063dd62ed3e14610412575f80fd5b8063b84c8246116100c3578063b84c82461461037e578063c47f002714610391578063c6f1b7e7146103a4575f80fd5b806374be21501461033c57806395d89b4114610363578063a9059cbb1461036b575f80fd5b806323b872dd1161015357806347e7ef241161012e57806347e7ef24146102a1578063609c92b8146102b4578063701cd43b146102e857806370a0823114610307575f80fd5b806323b872dd14610266578063313ce5671461027957806342966c681461028e575f80fd5b8063091d278811610183578063091d278814610224578063095ea7b31461023b57806318160ddd1461025e575f80fd5b8063044d9371146101a957806306fdde03146101fa57806307e2bd8d1461020f575b5f80fd5b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610202610499565b6040516101f1919061143c565b61022261021d366004611479565b610529565b005b61022d60015481565b6040519081526020016101f1565b61024e610249366004611494565b6105ef565b60405190151581526020016101f1565b60065461022d565b61024e6102743660046114be565b6106ae565b60055460405160ff90911681526020016101f1565b61024e61029c3660046114fc565b61079b565b61024e6102af366004611494565b6107ae565b6102db7f000000000000000000000000000000000000000000000000000000000000000081565b6040516101f19190611513565b5f546101d09073ffffffffffffffffffffffffffffffffffffffff1681565b61022d610315366004611479565b73ffffffffffffffffffffffffffffffffffffffff165f9081526007602052604090205490565b61022d7f000000000000000000000000000000000000000000000000000000000000000081565b610202610879565b61024e610379366004611494565b610888565b61022261038c36600461157f565b61089d565b61022261039f36600461157f565b61091c565b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b61024e6103d936600461166f565b610997565b6103e6610af9565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016101f1565b61022d6104203660046116e1565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260086020908152604080832093909416825291909152205490565b6102226104653660046114fc565b610d04565b6102226104783660046114fc565b610da8565b61022d60025481565b6103e66104943660046114fc565b610e4c565b6060600380546104a890611718565b80601f01602080910402602001604051908101604052809291908181526020018280546104d490611718565b801561051f5780601f106104f65761010080835404028352916020019161051f565b820191905f5260205f20905b81548152906001019060200180831161050257829003601f168201915b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610576576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f412d5a95dc32cbb6bd9319bccf1bc1febeda71e734893a440f1f6853252fe99f906020015b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff831661063d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f81815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060015b92915050565b5f6106ba848484611055565b73ffffffffffffffffffffffffffffffffffffffff84165f90815260086020908152604080832033845290915290205482811015610724576040517f10bad14700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85165f81815260086020908152604080832033808552908352928190208786039081905590519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3506001949350505050565b5f6107a6338361119c565b506001919050565b5f6107b983836112ed565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060601b1660208201527f67fc7bdaed5b0ec550d8706b87d60568ab70c6b781263c70101d54cd1564aab390603401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526108689186908690611769565b60405180910390a150600192915050565b6060600480546104a890611718565b5f610894338484611055565b50600192915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461090c576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600461091882826117ef565b5050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461098b576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361091882826117ef565b5f805f6109a2610af9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018390529294509092505f918416906323b872dd906064016020604051808303815f875af1158015610a42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a669190611906565b905080610a9f576040517f0a7cd6d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610aa9338661119c565b7f9ffbffc04a397460ee1dbe8c9503e098090567d6b7f4b3c02a8617d800b6d9553388888886600254604051610ae496959493929190611925565b60405180910390a15060019695505050505050565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610bf8576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610c84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca891906119c0565b9050805f03610ce3576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254600154610cf39083611a04565b610cfd9190611a1b565b9150509091565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d73576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028190556040518181527fef13af88e424b5d15f49c77758542c1938b08b8b95b91ed0751f98ba99000d8f906020016105e4565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e17576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018190556040518181527fff5788270f43bfc1ca41c503606d2594aa3023a1a7547de403a3e2f146a4a80a906020016105e4565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610efc91906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610f4b576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610fd7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffb91906119c0565b9050805f03611036576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546110438583611a04565b61104d9190611a1b565b915050915091565b73ffffffffffffffffffffffffffffffffffffffff8316158061108c575073ffffffffffffffffffffffffffffffffffffffff8216155b156110c3576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526007602052604090205481811015611122576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8085165f8181526007602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061118e9086815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611222576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526007602052604090205481811015611281576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f8181526007602090815260408083208686039055600680548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff821661133a576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611373576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600680548201905573ffffffffffffffffffffffffffffffffffffffff82165f818152600760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b5f81518084525f5b818110156113ff576020818501810151868301820152016113e3565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61144e60208301846113db565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611476575f80fd5b50565b5f60208284031215611489575f80fd5b813561144e81611455565b5f80604083850312156114a5575f80fd5b82356114b081611455565b946020939093013593505050565b5f805f606084860312156114d0575f80fd5b83356114db81611455565b925060208401356114eb81611455565b929592945050506040919091013590565b5f6020828403121561150c575f80fd5b5035919050565b602081016003831061154c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91905290565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f6020828403121561158f575f80fd5b813567ffffffffffffffff8111156115a5575f80fd5b8201601f810184136115b5575f80fd5b803567ffffffffffffffff8111156115cf576115cf611552565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561163b5761163b611552565b604052818152828201602001861015611652575f80fd5b816020840160208301375f91810160200191909152949350505050565b5f805f60408486031215611681575f80fd5b833567ffffffffffffffff811115611697575f80fd5b8401601f810186136116a7575f80fd5b803567ffffffffffffffff8111156116bd575f80fd5b8660208284010111156116ce575f80fd5b6020918201979096509401359392505050565b5f80604083850312156116f2575f80fd5b82356116fd81611455565b9150602083013561170d81611455565b809150509250929050565b600181811c9082168061172c57607f821691505b602082108103611763577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b606081525f61177b60608301866113db565b73ffffffffffffffffffffffffffffffffffffffff9490941660208301525060400152919050565b601f8211156117ea57805f5260205f20601f840160051c810160208510156117c85750805b601f840160051c820191505b818110156117e7575f81556001016117d4565b50505b505050565b815167ffffffffffffffff81111561180957611809611552565b61181d816118178454611718565b846117a3565b6020601f82116001811461186e575f83156118385750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556117e7565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156118bb578785015182556020948501946001909201910161189b565b50848210156118f757868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215611916575f80fd5b8151801515811461144e575f80fd5b73ffffffffffffffffffffffffffffffffffffffff8716815260a060208201528460a0820152848660c08301375f60c086830101525f60c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8801168301019050846040830152836060830152826080830152979650505050505050565b5f602082840312156119b5575f80fd5b815161144e81611455565b5f602082840312156119d0575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176106a8576106a86119d7565b808201808211156106a8576106a86119d756fea26469706673582212206be692aa215f21df823c52c689a11caa03254730bfade7b8b36788d6a72ba61764736f6c634300081a0033" -const UNIVERSAL_GATEWAY_PC_BYTECODE = "6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610f6857508063248a9ca314610ef85780632f2ff15d14610e7d57806336568abe14610df55780633f4ba83a14610d1d5780635c975abb14610cbe5780637f57735014610c6e5780638456cb5914610b935780638e61856014610a6a57806391d14854146109d6578063a217fddf1461099e578063affed0e014610963578063b3ca1fbc1461058e578063c1ee135a1461053d578063d547741f146104bb578063e63ab1e9146104635763f8c8765e146100d7575f80fd5b3461045f5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5761010e611047565b610116611024565b9060443573ffffffffffffffffffffffffffffffffffffffff811680910361045f576064359173ffffffffffffffffffffffffffffffffffffffff831680930361045f577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff811680159081610457575b600114908161044d575b159081610444575b5061041c578560017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008316177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556103c7575b5073ffffffffffffffffffffffffffffffffffffffff82161580156103a9575b80156103a1575b8015610399575b61037157610281610287926102406117ef565b6102486117ef565b6102506117ef565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561027c6117ef565b6112c6565b506113ad565b507fffffffffffffffffffffffff00000000000000000000000000000000000000005f5416175f557fffffffffffffffffffffffff000000000000000000000000000000000000000060015416176001556102de57005b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b50831561022d565b508215610226565b5073ffffffffffffffffffffffffffffffffffffffff81161561021f565b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f6101ff565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050155f6101ac565b303b1591506101a4565b87915061019a565b5f80fd5b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5760206040517f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a8152f35b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5761053b6004356104f8611024565b90610536610531825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b611240565b6115c3565b005b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5760043567ffffffffffffffff811161045f578060040160c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc833603011261045f5761060761171f565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00541461093b5761063981611772565b6040805191610648828461106a565b600f83527f6569703135353a313131353531313100000000000000000000000000000000006020840152600254946001860180871161090e576002556024810193610692856110ab565b9360448301359460848401936106a8858a6110cc565b97909a67ffffffffffffffff89116108e1578451956106ef601f8b017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020018861106a565b8987526020870197368e8c011161045f576107e36107da6107f99f8f9d60a499610807976107c273ffffffffffffffffffffffffffffffffffffffff9f61082f9f908f915f6020886107cb996107d29b8637830101525190209281519373ffffffffffffffffffffffffffffffffffffffff928593602085019733895216908401528d6060840152608083015260c060a083015261079060e083018c61111d565b9060c0830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261106a565b5190209f6110ab565b9d806110cc565b93909f6110cc565b979096016110ab565b9c87519e8f93610140855261014085019061111d565b92602081850391015261117a565b938b0152600160608b015261520860808b015261520860a08b015289830360c08b015261117a565b9461520860e08801521661010086015260048110156108b4577fd8352005a8b681f8cf230f28f60cef58ebe9a25d92e88f72cb6cb78799a6ca6d9173ffffffffffffffffffffffffffffffffffffffff9161012087015216938033940390a460017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f576020600254604051908152f35b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5760206040515f8152f35b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610a0d611024565b6004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610aa1611047565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff1615610b635773ffffffffffffffffffffffffffffffffffffffff90610af561171f565b1680156103715773ffffffffffffffffffffffffffffffffffffffff600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167fd0ef78509e8ed82196200827f0d10672cfab667994f990456881f413c1c475eb5f80a3005b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004525f60245260445ffd5b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610bc96111b8565b610bd161171f565b610bd961171f565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b3461045f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610d536111b8565b610d5b6116cb565b610d636116cb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57610e2c611024565b3373ffffffffffffffffffffffffffffffffffffffff821603610e555761053b906004356115c3565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461045f5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f5761053b600435610eba611024565b90610ef3610531825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b6114b1565b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f576020610f606004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b3461045f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261045f57600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361045f57817f7965db0b0000000000000000000000000000000000000000000000000000000060209314908115610ffa575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610ff3565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361045f57565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361045f57565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108e157604052565b3573ffffffffffffffffffffffffffffffffffffffff8116810361045f5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561045f570180359067ffffffffffffffff821161045f5760200191813603831361045f57565b91908251928382525f5b8481106111655750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b80602080928401015182828601015201611127565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b335f9081527f75442b0a96088b5456bc4ed01394c96a4feec0f883c9494257d76b96ab1c9b6b602052604090205460ff16156111f057565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a60245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156112975750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff166113a85773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b73ffffffffffffffffffffffffffffffffffffffff81165f9081527f75442b0a96088b5456bc4ed01394c96a4feec0f883c9494257d76b96ab1c9b6b602052604090205460ff166113a85773ffffffffffffffffffffffffffffffffffffffff165f8181527f75442b0a96088b5456bc4ed01394c96a4feec0f883c9494257d76b96ab1c9b6b6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f146115bd57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f146115bd57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416156116f757565b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300541661174a57565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b61177f60808201826110cc565b15801592604001351591506117e85781806117e0575b6117d957816117d1575b506117cc577fb4fa3fb3000000000000000000000000000000000000000000000000000000005f5260045ffd5b600190565b90505f61179f565b5050600390565b508015611795565b5050600290565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561181e57565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea26469706673582212206796924c3fa73cff81856f96b0134a35adc90b65de0eff7f3363998084206a5064736f6c634300081a0033" +const UNIVERSAL_GATEWAY_PC_BYTECODE = "6080806040526004361015610012575f80fd5b5f3560e01c9081637f577350146102f757508063affed0e0146102da578063b3ca1fbc146100745763c1ee135a14610048575f80fd5b34610070575f366003190112610070576001546040516001600160a01b039091168152602090f35b5f80fd5b60203660031901126100705760043567ffffffffffffffff8111610070578060040160c0600319833603011261007057600254600181018082116102c6576002556100bf8280610319565b91909360248101926100d08461034c565b60448301359060848401976100e58989610319565b67ffffffffffffffff81969296116102b2576040519061010f601f8201601f191660200183610360565b80825260208201933682890111610070577f8882d1d8f7b1750e49d021ea8d62e07c2d163645b8fa31c035905d6572ffc637996101d060a49787610186965f60208861027f9f996101e49a6101ed9e37830101525190206040519687956020870199338b5260e06040890152610100880191610382565b6001600160a01b039092166060860152608085018b905260a0850152838103601f190160c0850152600f81526e6569703135353a313131353531313160881b602082015260400190565b9060e083015203601f198101835282610360565b5190209661034c565b936102556102126102096102018b80610319565b9c909b610319565b9490930161034c565b986040519a6101608c526102476101608d01604090600f81526e6569703135353a313131353531313160881b60208201520190565b8c810360208e015291610382565b9260408a015261111160608a0152606f60808a015261520860a08a015288830360c08a0152610382565b5f60e087018190526001600160a01b039586166101008801526002610120880152610140870152931693339381900390a4005b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b34610070575f366003190112610070576020600254604051908152f35b34610070575f366003190112610070575f546001600160a01b03168152602090f35b903590601e1981360301821215610070570180359067ffffffffffffffff82116100705760200191813603831361007057565b356001600160a01b03811681036100705790565b90601f8019910116810190811067ffffffffffffffff8211176102b257604052565b908060209392818452848401375f828201840152601f01601f191601019056fea264697066735822122079614179005ddf0c314633ad63c96a5c52a1a1b032f71791f9eddc160bd868ed64736f6c634300081a0033" const UEA_MIGRATION_BYTECODE = "608060405234801561000f575f80fd5b506004361061006f575f3560e01c80639538c4b31161004d5780639538c4b3146100e7578063a5df53a01461010b578063f6829c321461012a575f80fd5b806352fa5c221461007357806367f102111461007d5780638c9ec7f5146100c7575b5f80fd5b61007b610132565b005b60025461009d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b60015461009d9073ffffffffffffffffffffffffffffffffffffffff1681565b6100fb6100f5366004610248565b3b151590565b60405190151581526020016100be565b5f5461009d9073ffffffffffffffffffffffffffffffffffffffff1681565b61007b61018a565b610e077f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d81815560405190919081907f310ba5f1d2ed074b51e2eccd052a47ae9ab7c6b800d1fca3db3999d6a592ca03905f90a25050565b5f5473ffffffffffffffffffffffffffffffffffffffff1630036101da576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025473ffffffffffffffffffffffffffffffffffffffff167f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d81815560405190919081907f310ba5f1d2ed074b51e2eccd052a47ae9ab7c6b800d1fca3db3999d6a592ca03905f90a25050565b5f60208284031215610258575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461027b575f80fd5b939250505056fea2646970667358221220b7392b390eabe1d8398ca6a63c585fe969825199b6bfe2a285e4edf564c16b6a64736f6c634300081a0033" From a3b701254d55d221f876d63855568ba6a16a0a1a Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 17:29:19 +0530 Subject: [PATCH 29/75] refactor: added generated protobuf --- x/uexecutor/types/types.pb.go | 327 +++++++++++++++++++++++----------- 1 file changed, 220 insertions(+), 107 deletions(-) diff --git a/x/uexecutor/types/types.pb.go b/x/uexecutor/types/types.pb.go index 41fbf44e..b1656633 100644 --- a/x/uexecutor/types/types.pb.go +++ b/x/uexecutor/types/types.pb.go @@ -871,6 +871,8 @@ 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"` } func (m *OutboundTx) Reset() { *m = OutboundTx{} } @@ -1010,6 +1012,20 @@ 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 "" +} + 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"` @@ -1370,115 +1386,116 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/types.proto", fileDescriptor_fab6d3ca71d1e2a5) } var fileDescriptor_fab6d3ca71d1e2a5 = []byte{ - // 1717 bytes of a gzipped FileDescriptorProto + // 1742 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, + 0x86, 0x8b, 0xd8, 0x9d, 0xb4, 0x1d, 0xa0, 0x02, 0x8a, 0x42, 0x96, 0x69, 0x8f, 0x5a, 0x8f, 0xac, + 0x52, 0x92, 0x91, 0xe9, 0x86, 0xa0, 0xc9, 0x6b, 0x9a, 0xa8, 0x44, 0x0a, 0x7c, 0xa8, 0xf4, 0xa2, + 0xab, 0xee, 0x8a, 0x2e, 0xba, 0xcc, 0x32, 0xcb, 0xa2, 0xdd, 0xb4, 0x40, 0x7f, 0xc4, 0x2c, 0xa7, + 0xbb, 0x02, 0xdd, 0x14, 0x09, 0x8a, 0x16, 0xe8, 0x9f, 0x28, 0xee, 0x83, 0x22, 0xa9, 0xc7, 0x64, + 0x8a, 0x2c, 0x0a, 0x74, 0x63, 0xf1, 0x3c, 0xee, 0xe1, 0x77, 0xce, 0x77, 0xce, 0xb9, 0xb2, 0x40, + 0x0e, 0x71, 0x84, 0x8d, 0x30, 0x70, 0xbd, 0xe3, 0xd9, 0x27, 0xc7, 0xc1, 0xdd, 0x14, 0xfb, 0x47, + 0x53, 0xcf, 0x0d, 0x5c, 0xb4, 0x39, 0xb7, 0x1c, 0xcd, 0x3e, 0x79, 0xbc, 0x63, 0xb9, 0x96, 0x4b, + 0x0d, 0xc7, 0xe4, 0x89, 0xf9, 0x3c, 0xae, 0xeb, 0x13, 0xdb, 0x71, 0x8f, 0xe9, 0x5f, 0xa6, 0x6a, + 0x9e, 0x41, 0xb1, 0xaf, 0x7b, 0xfa, 0xc4, 0x47, 0xbb, 0x00, 0xbe, 0x3b, 0xc1, 0xda, 0x4c, 0x1f, + 0x87, 0x58, 0x16, 0xf7, 0x85, 0x83, 0xb2, 0x5a, 0x21, 0x9a, 0x2b, 0xa2, 0x68, 0xed, 0xbe, 0x7a, + 0xbd, 0xb7, 0xf1, 0xaf, 0xd7, 0x7b, 0xc2, 0xaf, 0xff, 0xf9, 0xc7, 0x43, 0x29, 0x81, 0x31, 0xa5, + 0xa7, 0x9b, 0x7f, 0x13, 0x41, 0x1a, 0x39, 0xf6, 0x0c, 0x7b, 0xbe, 0x3e, 0xee, 0xeb, 0x77, 0x63, + 0x57, 0x37, 0xd1, 0x16, 0x88, 0x81, 0x2b, 0x0b, 0xfb, 0xc2, 0x41, 0x45, 0x15, 0x03, 0x17, 0xed, + 0x40, 0x21, 0x89, 0x5e, 0x51, 0x99, 0x80, 0x10, 0xe4, 0x4d, 0x3d, 0xd0, 0xe5, 0x1c, 0x55, 0xd2, + 0x67, 0xf4, 0x04, 0x2a, 0x96, 0xee, 0x6b, 0x63, 0x7b, 0x62, 0x07, 0x72, 0x9e, 0x1a, 0xca, 0x96, + 0xee, 0x5f, 0x10, 0x19, 0x7d, 0x0c, 0xb5, 0x89, 0x1e, 0x69, 0x37, 0x18, 0x6b, 0x53, 0xec, 0x69, + 0x96, 0xee, 0xcb, 0x05, 0xea, 0xb2, 0x39, 0xd1, 0xa3, 0x33, 0x8c, 0xfb, 0xd8, 0x3b, 0xd7, 0x7d, + 0xf4, 0x29, 0xc8, 0xc4, 0x6d, 0xea, 0xd9, 0xae, 0x67, 0x07, 0x77, 0x19, 0xff, 0x22, 0xf5, 0xdf, + 0x99, 0xe8, 0x51, 0x9f, 0x9b, 0x93, 0x73, 0x3b, 0x50, 0x70, 0x5c, 0xc7, 0xc0, 0x72, 0x89, 0xa1, + 0xa4, 0x02, 0x7a, 0x0c, 0x65, 0x13, 0xeb, 0xe6, 0xd8, 0x76, 0xb0, 0x5c, 0x66, 0x80, 0x62, 0x19, + 0x7d, 0x1f, 0x8a, 0x33, 0x8d, 0x90, 0x21, 0x57, 0xf6, 0x85, 0x83, 0xad, 0x17, 0x8d, 0xa3, 0x34, + 0x19, 0x47, 0x57, 0xd8, 0xb3, 0x6f, 0x6c, 0x43, 0x0f, 0x6c, 0xd7, 0x19, 0xde, 0x4d, 0xb1, 0x5a, + 0x98, 0x91, 0x8f, 0xd6, 0x41, 0xba, 0xa4, 0x4f, 0x92, 0x92, 0x86, 0x71, 0x1d, 0xb5, 0x29, 0x2b, + 0x64, 0xf3, 0x37, 0x02, 0x48, 0x9f, 0xdb, 0x96, 0x47, 0x43, 0xc4, 0xd5, 0xfd, 0x00, 0x2a, 0x93, + 0x58, 0xc7, 0x8b, 0x9c, 0x28, 0x92, 0x2c, 0xc4, 0x75, 0x59, 0xe4, 0xb2, 0x59, 0xac, 0x85, 0x33, + 0x8f, 0x39, 0x87, 0xf3, 0x4a, 0x00, 0x34, 0x27, 0xbb, 0x6d, 0x18, 0x6e, 0xe8, 0x04, 0x5d, 0x13, + 0x3d, 0x83, 0x9a, 0x71, 0xab, 0xdb, 0x8e, 0xe6, 0xe8, 0x13, 0xec, 0x4f, 0x75, 0x03, 0x73, 0x58, + 0x5b, 0x54, 0xdd, 0x8b, 0xb5, 0xe8, 0x11, 0x94, 0x99, 0xa3, 0x6d, 0x72, 0x78, 0x25, 0x2a, 0x77, + 0x4d, 0x02, 0xdb, 0xfd, 0x85, 0x83, 0x3d, 0x8e, 0x8e, 0x09, 0xdf, 0xa0, 0x52, 0x3a, 0x43, 0xd1, + 0x34, 0x00, 0xa9, 0x78, 0x86, 0xbd, 0xa0, 0xeb, 0xf8, 0x81, 0x17, 0x1a, 0x04, 0xb7, 0x8f, 0x3e, + 0x86, 0xad, 0x9b, 0xd0, 0x31, 0x35, 0x0f, 0x1b, 0xf6, 0xd4, 0xc6, 0x4e, 0xc0, 0x81, 0xdd, 0x23, + 0x5a, 0x35, 0x56, 0xb6, 0xbe, 0x15, 0xbf, 0x62, 0x37, 0x79, 0x85, 0x47, 0xa3, 0x69, 0x76, 0x2a, + 0x5c, 0xf3, 0xdf, 0x39, 0x28, 0x75, 0x9d, 0x6b, 0x37, 0x74, 0x4c, 0xf4, 0x14, 0x36, 0x7d, 0x37, + 0xf4, 0x0c, 0xac, 0xd1, 0x14, 0x78, 0xe0, 0x2a, 0xd3, 0x75, 0x88, 0x0a, 0x3d, 0x84, 0x52, 0x10, + 0x69, 0xb7, 0xba, 0x7f, 0xcb, 0xb3, 0x2d, 0x06, 0xd1, 0x67, 0xba, 0x7f, 0x8b, 0x1e, 0x40, 0xd1, + 0xc7, 0x8e, 0x39, 0xcf, 0x96, 0x4b, 0x84, 0xd9, 0x04, 0x29, 0xeb, 0xfe, 0x44, 0x41, 0x4e, 0xe9, + 0x13, 0x92, 0x2c, 0xef, 0x7a, 0x2e, 0x91, 0x01, 0xd6, 0x7d, 0x1f, 0x07, 0x9a, 0x6e, 0x9a, 0x1e, + 0xef, 0xf0, 0x0a, 0xd5, 0xb4, 0x4d, 0xd3, 0x23, 0x23, 0x35, 0x76, 0x2d, 0xcd, 0x76, 0x4c, 0x1c, + 0xf1, 0xd6, 0x2e, 0x8f, 0x5d, 0xab, 0x4b, 0x64, 0xf4, 0x9c, 0x42, 0xa4, 0x2d, 0x5c, 0xa6, 0x2d, + 0xbc, 0x93, 0x6d, 0xe1, 0x61, 0x44, 0x1b, 0xb7, 0x18, 0xd0, 0x4f, 0xf4, 0x13, 0xa8, 0x2f, 0x35, + 0x29, 0xed, 0xfd, 0xea, 0x62, 0xef, 0x2f, 0xee, 0x04, 0x55, 0x0a, 0x17, 0xb7, 0xc4, 0xb7, 0xa1, + 0x3e, 0x4b, 0x4d, 0x88, 0x46, 0x97, 0x01, 0x50, 0x80, 0x52, 0xda, 0x70, 0x4a, 0x16, 0xc3, 0x4f, + 0x61, 0x7b, 0x05, 0x23, 0x72, 0x95, 0xbe, 0x7b, 0x3f, 0xfb, 0xee, 0xe5, 0x46, 0x50, 0x91, 0xb7, + 0xdc, 0x1c, 0x3b, 0x50, 0xb0, 0xfd, 0x8e, 0xd2, 0x96, 0x37, 0xe9, 0xce, 0x63, 0x42, 0xab, 0x1c, + 0xb7, 0x5c, 0xf3, 0x4b, 0x01, 0xf2, 0xfd, 0xce, 0x30, 0x4a, 0xf3, 0x28, 0xac, 0xe1, 0x51, 0xcc, + 0xf0, 0xf8, 0x08, 0xc8, 0xd2, 0xd2, 0x42, 0x1f, 0x9b, 0x94, 0xe1, 0xbc, 0x5a, 0xb2, 0x74, 0x7f, + 0xe4, 0x63, 0xda, 0x36, 0xd7, 0x63, 0xd7, 0xf8, 0xb9, 0x76, 0x8b, 0x6d, 0xeb, 0x96, 0xb1, 0x9c, + 0x57, 0xab, 0x54, 0xf7, 0x19, 0x55, 0xd1, 0xa8, 0x81, 0x1e, 0x84, 0xf1, 0xb6, 0xe2, 0x12, 0x21, + 0x12, 0x7b, 0x9e, 0xeb, 0x69, 0x13, 0xdf, 0x8a, 0x89, 0xa4, 0x8a, 0xcf, 0x7d, 0xab, 0xf5, 0x41, + 0x7a, 0x52, 0x6a, 0xa9, 0x35, 0x6d, 0x68, 0x41, 0xd4, 0xfc, 0x93, 0x00, 0xdb, 0x97, 0x61, 0x40, + 0x3b, 0xf7, 0xf2, 0xda, 0xc7, 0xde, 0x8c, 0x2d, 0x0b, 0x19, 0x4a, 0x7e, 0x68, 0x18, 0xd8, 0xf7, + 0x69, 0x66, 0x65, 0x35, 0x16, 0x97, 0x70, 0x8a, 0xcb, 0x38, 0x53, 0x65, 0xc9, 0x65, 0xca, 0x92, + 0x01, 0x9a, 0x5f, 0x00, 0xfa, 0x2c, 0x06, 0xd9, 0x48, 0x40, 0xba, 0x1c, 0x9a, 0xe6, 0x26, 0xd8, + 0x9a, 0x13, 0xa8, 0x5d, 0x7a, 0xb6, 0x65, 0x3b, 0x7a, 0x60, 0x3b, 0x56, 0xdf, 0xf8, 0x3a, 0x22, + 0x32, 0x3d, 0x2e, 0x66, 0x7b, 0xbc, 0xf5, 0xd1, 0x8a, 0x05, 0xe2, 0x26, 0x91, 0x35, 0x56, 0xa2, + 0x7f, 0x14, 0x00, 0xe2, 0x12, 0x0d, 0x23, 0xd2, 0x9c, 0x26, 0xf6, 0x03, 0xea, 0xe3, 0x3a, 0x99, + 0x19, 0x97, 0x52, 0x06, 0x36, 0xe8, 0x99, 0xb9, 0x15, 0xd7, 0xcf, 0x6d, 0x2e, 0x33, 0xb7, 0x47, + 0xb0, 0x8d, 0xa3, 0x00, 0x7b, 0x0e, 0x59, 0x63, 0xc9, 0x00, 0xb3, 0x82, 0xd5, 0x63, 0x53, 0x7b, + 0x3e, 0xc8, 0x07, 0x20, 0x4d, 0x3d, 0xe3, 0xc5, 0x77, 0xd2, 0xce, 0x6c, 0x13, 0x6c, 0x51, 0x7d, + 0xe2, 0x99, 0xf4, 0x65, 0x31, 0xd3, 0x97, 0x32, 0x94, 0xe2, 0xa1, 0x65, 0xfd, 0x13, 0x8b, 0xd9, + 0x7b, 0xb7, 0xbc, 0x70, 0xef, 0xa6, 0x96, 0x44, 0xe5, 0x1b, 0x2c, 0x89, 0x17, 0x50, 0xa0, 0x25, + 0xa5, 0xb3, 0x5c, 0x7d, 0xb1, 0x9b, 0x75, 0x5e, 0xe0, 0x54, 0xcd, 0x4f, 0x09, 0xb3, 0x27, 0x50, + 0x65, 0xdc, 0x63, 0x93, 0x9c, 0x64, 0x63, 0xfd, 0x74, 0xe1, 0xe4, 0x72, 0x03, 0xab, 0x10, 0x9f, + 0x1a, 0x46, 0xe4, 0x5b, 0x87, 0x6d, 0xd2, 0x61, 0xae, 0xa8, 0xa2, 0x6d, 0xa2, 0x1f, 0x42, 0x6d, + 0xde, 0x58, 0x7c, 0xa0, 0xee, 0xad, 0x82, 0x3f, 0xa0, 0x36, 0x75, 0x2b, 0x76, 0x66, 0xf2, 0xba, + 0x8d, 0xb3, 0xf5, 0x1e, 0x1b, 0xe7, 0x04, 0xb6, 0xa7, 0x86, 0xc6, 0xa3, 0xb2, 0xf3, 0xe4, 0x0e, + 0xaf, 0xd1, 0x90, 0x28, 0x1b, 0x92, 0x6c, 0x1e, 0xb5, 0x3e, 0x35, 0x58, 0x68, 0x25, 0x76, 0x8e, + 0x99, 0x9a, 0x7a, 0xb6, 0x81, 0x65, 0x69, 0xce, 0x54, 0x9f, 0xc8, 0x64, 0x40, 0x88, 0xf1, 0x06, + 0x63, 0xb9, 0xce, 0x98, 0xb7, 0x74, 0xff, 0x0c, 0xe3, 0xd4, 0x56, 0xfb, 0x9d, 0x08, 0xd5, 0xf9, + 0x72, 0x9e, 0x57, 0x4d, 0x98, 0x57, 0xed, 0x7b, 0x00, 0x36, 0xbb, 0xe2, 0x08, 0x11, 0x22, 0x85, + 0x76, 0x3f, 0x0b, 0x8d, 0x5f, 0x81, 0x6a, 0x85, 0x3b, 0x0e, 0x23, 0xf4, 0x2c, 0xe6, 0x3c, 0xb7, + 0x9f, 0x5b, 0x93, 0x0b, 0x23, 0xfa, 0x07, 0x50, 0x9d, 0x93, 0x12, 0x44, 0x72, 0x9e, 0xba, 0xcb, + 0xab, 0x89, 0x1e, 0x46, 0x2a, 0xb8, 0xc9, 0x48, 0xfe, 0x18, 0x92, 0x3b, 0x24, 0x26, 0xb4, 0x40, + 0x09, 0xdd, 0x5b, 0x73, 0xf7, 0x0c, 0x23, 0xce, 0x6d, 0x6d, 0x7e, 0x90, 0x29, 0x5a, 0x1f, 0xa6, + 0xd7, 0xe5, 0x83, 0x55, 0x5f, 0x2c, 0x82, 0xa8, 0xf9, 0x87, 0x1c, 0xdc, 0xe3, 0xb9, 0x5e, 0x60, + 0x4b, 0x37, 0xee, 0xfe, 0x4f, 0x2e, 0xfd, 0xd6, 0xe2, 0xa5, 0xff, 0x74, 0x25, 0xbf, 0x6c, 0xac, + 0x59, 0xe6, 0xff, 0xfb, 0x6f, 0x00, 0xad, 0xc6, 0xab, 0xd7, 0x7b, 0x42, 0x4c, 0x59, 0x3d, 0xa1, + 0x8c, 0x37, 0x61, 0xf3, 0x2f, 0x02, 0x48, 0x49, 0xe7, 0x70, 0xc2, 0xfe, 0xab, 0x35, 0xbe, 0x96, + 0xba, 0x0c, 0x45, 0xb9, 0xf5, 0x14, 0xe5, 0xbf, 0x86, 0xa2, 0xc2, 0x02, 0x45, 0xad, 0x66, 0x3a, + 0x9f, 0xfb, 0x2b, 0x2e, 0xc3, 0x20, 0x6a, 0xfe, 0x5e, 0x84, 0x7a, 0xaa, 0x9b, 0x79, 0x52, 0xad, + 0xcc, 0x88, 0x0a, 0xb4, 0xf8, 0x4f, 0x56, 0x52, 0xc8, 0xc9, 0x5b, 0x35, 0xa8, 0xe2, 0x3b, 0x06, + 0xf5, 0x47, 0xd9, 0x41, 0xcd, 0xad, 0xa2, 0x78, 0xb1, 0xdc, 0xef, 0x1c, 0xd7, 0xfc, 0x7b, 0x8c, + 0xab, 0xf0, 0x8e, 0x71, 0x3d, 0x3c, 0x07, 0x69, 0xf1, 0x3f, 0x2e, 0xf4, 0x00, 0x90, 0x6f, 0x5b, + 0x0e, 0x36, 0xd3, 0x16, 0x69, 0x03, 0x3d, 0x81, 0x87, 0x61, 0xf2, 0xda, 0x8c, 0x51, 0x38, 0xfc, + 0x55, 0xb6, 0xea, 0xfc, 0x3e, 0xf8, 0x10, 0xf6, 0x46, 0xbd, 0xee, 0x95, 0xa2, 0x0e, 0xda, 0x17, + 0xda, 0xf0, 0xa5, 0x36, 0x18, 0xb6, 0x87, 0xa3, 0x81, 0x36, 0xea, 0x0d, 0xfa, 0x4a, 0xa7, 0x7b, + 0xd6, 0x55, 0x4e, 0xa5, 0x0d, 0xb4, 0x0d, 0xb5, 0x6e, 0xef, 0xe4, 0x72, 0xd4, 0x3b, 0xd5, 0x06, + 0xa3, 0x4e, 0x47, 0x19, 0x0c, 0x24, 0x01, 0xed, 0xc2, 0xa3, 0xbe, 0xd2, 0x3b, 0xed, 0xf6, 0xce, + 0xb5, 0xd8, 0xa8, 0xbc, 0x54, 0x3a, 0xa3, 0x61, 0xf7, 0xb2, 0x27, 0x89, 0xe8, 0x21, 0x6c, 0xf7, + 0x3b, 0x5c, 0xa3, 0x24, 0xe7, 0x72, 0x04, 0x7c, 0xda, 0x70, 0xd6, 0xee, 0x5e, 0x28, 0xa7, 0x52, + 0x1e, 0xdd, 0x87, 0x7a, 0xbf, 0xa3, 0xc5, 0x21, 0x55, 0xe5, 0x4a, 0x51, 0x87, 0x52, 0x01, 0xed, + 0x80, 0x74, 0x39, 0x1a, 0xb2, 0xf8, 0xdc, 0x28, 0x15, 0x33, 0xda, 0x38, 0x74, 0x89, 0xe0, 0x9c, + 0x6b, 0x79, 0xdc, 0x32, 0xda, 0x84, 0x72, 0xa7, 0xdd, 0xeb, 0x28, 0x44, 0xaa, 0x1c, 0x9e, 0x40, + 0x91, 0x67, 0x5e, 0x83, 0x6a, 0x36, 0xcb, 0x2a, 0x94, 0xe2, 0x17, 0x08, 0xe4, 0xd4, 0xe5, 0xc9, + 0x40, 0x51, 0xaf, 0x94, 0x53, 0x49, 0x24, 0x12, 0x03, 0xa4, 0x9c, 0x4a, 0xb9, 0xc3, 0x5f, 0x42, + 0x91, 0x6d, 0x11, 0x84, 0x60, 0x2b, 0x15, 0x43, 0x1b, 0xbe, 0x94, 0x36, 0x50, 0x09, 0x72, 0xe7, + 0x6d, 0x52, 0xa0, 0x6d, 0xa8, 0x9d, 0xb7, 0x07, 0x5a, 0x9b, 0x00, 0x6f, 0x7f, 0x71, 0x71, 0xd9, + 0x26, 0x91, 0x2a, 0x50, 0x38, 0x1b, 0xf5, 0x4e, 0x49, 0x21, 0xee, 0x43, 0x9d, 0x3e, 0x66, 0x3c, + 0xf2, 0x14, 0x06, 0x17, 0x0a, 0xe4, 0x05, 0x71, 0x71, 0x79, 0x45, 0x8a, 0x87, 0x7f, 0x16, 0x60, + 0x7b, 0xc5, 0x32, 0x43, 0x4f, 0x61, 0x37, 0xf6, 0xbd, 0x50, 0xce, 0xdb, 0x9d, 0x2f, 0xb4, 0x25, + 0x6c, 0x0f, 0x00, 0x2d, 0xb8, 0x30, 0xa8, 0x32, 0xec, 0x2c, 0xe8, 0x19, 0x48, 0x11, 0x7d, 0x04, + 0xfb, 0xab, 0x2c, 0x19, 0xcc, 0x39, 0xd4, 0x84, 0xc6, 0x72, 0xdc, 0x6c, 0x5e, 0x27, 0xfd, 0x2f, + 0xdf, 0x34, 0x84, 0xaf, 0xde, 0x34, 0x84, 0xbf, 0xbf, 0x69, 0x08, 0xbf, 0x7d, 0xdb, 0xd8, 0xf8, + 0xea, 0x6d, 0x63, 0xe3, 0xaf, 0x6f, 0x1b, 0x1b, 0x3f, 0xfb, 0xd4, 0xb2, 0x83, 0xdb, 0xf0, 0xfa, + 0xc8, 0x70, 0x27, 0xc7, 0xd3, 0xd0, 0xbf, 0xa5, 0xfb, 0x8c, 0x3e, 0x3d, 0xa7, 0x8f, 0xcf, 0x1d, + 0xd7, 0xc4, 0xc7, 0xd1, 0x71, 0x32, 0x21, 0xf4, 0xa7, 0xa2, 0xeb, 0x22, 0xfd, 0xd1, 0xe7, 0xbb, + 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x3e, 0x6c, 0xeb, 0x47, 0x12, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -1857,6 +1874,12 @@ 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 + } return true } func (this *UniversalTx) Equal(that interface{}) bool { @@ -2553,6 +2576,24 @@ func (m *OutboundTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + 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]) @@ -3284,6 +3325,14 @@ 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)) + } return n } @@ -5596,6 +5645,70 @@ 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 default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) From 7d4d56702698463f95cb930f437c82f2a4cc14c9 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 18:56:36 +0530 Subject: [PATCH 30/75] feat: added gas_fee_used in the outbound proto --- proto/uexecutor/v1/types.proto | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proto/uexecutor/v1/types.proto b/proto/uexecutor/v1/types.proto index 58fb1d06..a68d8dad 100644 --- a/proto/uexecutor/v1/types.proto +++ b/proto/uexecutor/v1/types.proto @@ -137,6 +137,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 { @@ -169,6 +170,9 @@ message OutboundTx { 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 { From 810a14dd1d84cc4cb2d5302dec9db2ee12284659 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 18:56:43 +0530 Subject: [PATCH 31/75] refactor: added generated protobuf --- api/uexecutor/v1/types.pulsar.go | 727 ++++++++++++++++++++++--------- 1 file changed, 524 insertions(+), 203 deletions(-) diff --git a/api/uexecutor/v1/types.pulsar.go b/api/uexecutor/v1/types.pulsar.go index e41fdf0c..228be4f2 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:]) @@ -5781,6 +5845,9 @@ var ( 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() { @@ -5803,6 +5870,9 @@ func init() { 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) @@ -5972,6 +6042,24 @@ func (x *fastReflection_OutboundTx) Range(f func(protoreflect.FieldDescriptor, p 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. @@ -6021,6 +6109,12 @@ func (x *fastReflection_OutboundTx) Has(fd protoreflect.FieldDescriptor) bool { 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")) @@ -6071,6 +6165,12 @@ func (x *fastReflection_OutboundTx) Clear(fd protoreflect.FieldDescriptor) { 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")) @@ -6138,6 +6238,15 @@ func (x *fastReflection_OutboundTx) Get(descriptor protoreflect.FieldDescriptor) 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")) @@ -6192,6 +6301,12 @@ func (x *fastReflection_OutboundTx) Set(fd protoreflect.FieldDescriptor, value p 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")) @@ -6232,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": @@ -6258,6 +6378,10 @@ func (x *fastReflection_OutboundTx) Mutable(fd protoreflect.FieldDescriptor) pro 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")) @@ -6309,6 +6433,13 @@ func (x *fastReflection_OutboundTx) NewField(fd protoreflect.FieldDescriptor) pr 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")) @@ -6444,6 +6575,18 @@ func (x *fastReflection_OutboundTx) ProtoMethods() *protoiface.Methods { 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) } @@ -6473,6 +6616,40 @@ 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) @@ -7203,6 +7380,106 @@ func (x *fastReflection_OutboundTx) ProtoMethods() *protoiface.Methods { } 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:]) @@ -11213,6 +11490,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() { @@ -11263,6 +11541,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 @@ -11326,8 +11611,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 + 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() { @@ -11469,6 +11757,27 @@ func (x *OutboundTx) GetGasFee() string { 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 @@ -11872,7 +12181,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, @@ -11880,197 +12189,208 @@ 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, 0xe5, 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, - 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, - 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, + 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, 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, + 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, 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, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, + 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, 0x01, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x16, 0x75, 0x65, + 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, 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, + 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, 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, } var ( @@ -12119,21 +12439,22 @@ 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 - 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 - 11, // 17: uexecutor.v1.UniversalTxLegacy.pc_tx:type_name -> uexecutor.v1.PCTx - 17, // 18: uexecutor.v1.UniversalTxLegacy.outbound_tx:type_name -> uexecutor.v1.OutboundTxLegacy - 1, // 19: uexecutor.v1.UniversalTxLegacy.universal_status:type_name -> uexecutor.v1.UniversalTxStatus - 20, // [20:20] is the sub-list for method output_type - 20, // [20:20] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name + 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 + 1, // 14: uexecutor.v1.UniversalTx.universal_status:type_name -> uexecutor.v1.UniversalTxStatus + 4, // 15: uexecutor.v1.InboundLegacy.tx_type:type_name -> uexecutor.v1.InboundTxTypeLegacy + 6, // 16: uexecutor.v1.InboundLegacy.universal_payload:type_name -> uexecutor.v1.UniversalPayload + 16, // 17: uexecutor.v1.UniversalTxLegacy.inbound_tx:type_name -> uexecutor.v1.InboundLegacy + 11, // 18: uexecutor.v1.UniversalTxLegacy.pc_tx:type_name -> uexecutor.v1.PCTx + 17, // 19: uexecutor.v1.UniversalTxLegacy.outbound_tx:type_name -> uexecutor.v1.OutboundTxLegacy + 1, // 20: uexecutor.v1.UniversalTxLegacy.universal_status:type_name -> uexecutor.v1.UniversalTxStatus + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_uexecutor_v1_types_proto_init() } From 346ca45df1792808e43d90891fdf7aa275a20cfd Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 18:57:40 +0530 Subject: [PATCH 32/75] feat: added GasToken in the chain outbound event --- x/uexecutor/keeper/create_outbound.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/uexecutor/keeper/create_outbound.go b/x/uexecutor/keeper/create_outbound.go index 3f9e6f4d..5c59967f 100644 --- a/x/uexecutor/keeper/create_outbound.go +++ b/x/uexecutor/keeper/create_outbound.go @@ -73,6 +73,7 @@ func (k Keeper) BuildOutboundsFromReceipt( GasFee: event.GasFee.String(), GasLimit: event.GasLimit.String(), GasPrice: event.GasPrice.String(), + GasToken: event.GasToken, TxType: event.TxType, PcTx: &types.OriginatingPcTx{ TxHash: receipt.Hash, @@ -206,6 +207,7 @@ func (k Keeper) attachOutboundsToUtx( GasFee: outbound.GasFee, GasLimit: outbound.GasLimit, GasPrice: outbound.GasPrice, + GasToken: outbound.GasToken, TxType: outbound.TxType.String(), PcTxHash: pcTxHash, LogIndex: logIndex, From f5b1d9eafe3fe44f1b1a16a533e73c0e14b4c51c Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 18:58:35 +0530 Subject: [PATCH 33/75] feat: added refund unused gas implementation --- x/uexecutor/keeper/evm.go | 57 ++++++++++++++- x/uexecutor/keeper/outbound.go | 124 ++++++++++++++++++++++++++++++--- x/uexecutor/types/abi.go | 14 ++++ x/uexecutor/types/events.go | 2 + 4 files changed, 186 insertions(+), 11 deletions(-) diff --git a/x/uexecutor/keeper/evm.go b/x/uexecutor/keeper/evm.go index 39fbe003..05ec3fc8 100644 --- a/x/uexecutor/keeper/evm.go +++ b/x/uexecutor/keeper/evm.go @@ -430,13 +430,13 @@ func (k Keeper) GetDefaultFeeTierForToken(ctx sdk.Context, prc20Address common.A return nil, errors.Wrap(err, "failed to unpack defaultFeeTier result") } - // go-ethereum unpacks uint24 as uint32 - fee, ok := results[0].(uint32) + // 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 new(big.Int).SetUint64(uint64(fee)), nil + return fee, nil } // GetSwapQuote calls QuoterV2.quoteExactInputSingle (commit=false) to get the expected @@ -526,3 +526,54 @@ func (k Keeper) CallPRC20DepositAutoSwap( 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, + ) +} diff --git a/x/uexecutor/keeper/outbound.go b/x/uexecutor/keeper/outbound.go index 11d6042d..9839c21f 100644 --- a/x/uexecutor/keeper/outbound.go +++ b/x/uexecutor/keeper/outbound.go @@ -44,18 +44,27 @@ func (k Keeper) FinalizeOutbound(ctx context.Context, utxId string, outbound typ } obs := outbound.ObservedTx - if obs == nil || obs.Success { + if obs == nil { return nil } + sdkCtx := sdk.UnwrapSDKContext(ctx) + + if !obs.Success { + return k.handleFailedOutbound(sdkCtx, utxId, outbound) + } + + return k.handleSuccessfulOutbound(sdkCtx, utxId, outbound, obs) +} + +// handleFailedOutbound mints back the bridged tokens to the revert recipient. +func (k Keeper) handleFailedOutbound(ctx sdk.Context, utxId string, outbound types.OutboundTx) error { // 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 { return nil } - sdkCtx := sdk.UnwrapSDKContext(ctx) - // Decide refund recipient safely recipient := outbound.Sender if outbound.RevertInstructions != nil && @@ -69,16 +78,16 @@ func (k Keeper) FinalizeOutbound(ctx context.Context, utxId string, outbound typ if !ok { return fmt.Errorf("invalid amount: %s", outbound.Amount) } - receipt, err := k.CallPRC20Deposit(sdkCtx, common.HexToAddress(outbound.Prc20AssetAddr), common.HexToAddress(recipient), amount) + receipt, err := k.CallPRC20Deposit(ctx, 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 + TxHash: "", Sender: outbound.Sender, GasUsed: 0, - BlockHeight: uint64(sdkCtx.BlockHeight()), + BlockHeight: uint64(ctx.BlockHeight()), } if err != nil { @@ -88,11 +97,110 @@ func (k Keeper) FinalizeOutbound(ctx context.Context, utxId string, outbound typ pcTx.TxHash = receipt.Hash pcTx.GasUsed = receipt.GasUsed pcTx.Status = "SUCCESS" - pcTx.ErrorMsg = "" } outbound.PcRevertExecution = &pcTx - // Store Reverted tx in Outbound 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 { + // Only attempt refund if gas_fee_used is populated and gas token is known + if obs.GasFeeUsed == "" || outbound.GasFee == "" || outbound.GasToken == "" { + return k.UpdateOutbound(ctx, utxId, outbound) + } + + gasFee := new(big.Int) + if _, ok := gasFee.SetString(outbound.GasFee, 10); !ok { + return k.UpdateOutbound(ctx, utxId, outbound) + } + + gasFeeUsed := new(big.Int) + if _, ok := gasFeeUsed.SetString(obs.GasFeeUsed, 10); !ok { + return k.UpdateOutbound(ctx, utxId, outbound) + } + + // No refund needed + if gasFee.Cmp(gasFeeUsed) <= 0 { + return k.UpdateOutbound(ctx, utxId, outbound) + } + + 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, + BlockHeight: uint64(ctx.BlockHeight()), + } + + // Step 1: try refund with swap (gasToken → PC native) + fee, swapErr := k.GetDefaultFeeTierForToken(ctx, gasToken) + var swapFallbackReason string + var receipt interface{ GetHash() 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 k.UpdateOutbound(ctx, utxId, outbound) + } + 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()) + } + + _ = receipt + + // Step 2: fallback — refund without swap (deposit PRC20 directly to recipient) + ctx.Logger().Error("FinalizeOutbound: 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 { + refundPcTx.Status = "FAILED" + refundPcTx.ErrorMsg = err.Error() + } else { + refundPcTx.TxHash = resp.Hash + refundPcTx.GasUsed = resp.GasUsed + refundPcTx.Status = "SUCCESS" + } + + outbound.PcRefundExecution = refundPcTx + outbound.RefundSwapError = swapFallbackReason + + 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/types/abi.go b/x/uexecutor/types/abi.go index b318f58c..37587e4a 100644 --- a/x/uexecutor/types/abi.go +++ b/x/uexecutor/types/abi.go @@ -353,6 +353,20 @@ const UNIVERSAL_CORE_ABI = `[ "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" } ]` diff --git a/x/uexecutor/types/events.go b/x/uexecutor/types/events.go index 599c937e..59e62187 100644 --- a/x/uexecutor/types/events.go +++ b/x/uexecutor/types/events.go @@ -24,6 +24,7 @@ type OutboundCreatedEvent struct { 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"` @@ -54,6 +55,7 @@ func NewOutboundCreatedEvent(e OutboundCreatedEvent) (sdk.Event, error) { 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), From 0d6731f5bddc660639a784d333a46c51d2263025 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 18:58:55 +0530 Subject: [PATCH 34/75] tests: added integration tests for refund gas --- .../uexecutor/gas_fee_refund_test.go | 249 ++++++++++++++++++ .../uexecutor/vote_outbound_test.go | 11 + 2 files changed, 260 insertions(+) create mode 100644 test/integration/uexecutor/gas_fee_refund_test.go 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..2194488d --- /dev/null +++ b/test/integration/uexecutor/gas_fee_refund_test.go @@ -0,0 +1,249 @@ +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("no refund when gasFeeUsed is empty", func(t *testing.T) { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + 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 empty → no refund + ) + 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.True(t, ob.ObservedTx.Success) + // No refund should be triggered + require.Nil(t, ob.PcRefundExecution, "no refund expected when gasFeeUsed is empty") + require.Empty(t, ob.RefundSwapError) + }) + + 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 still performs revert not refund", func(t *testing.T) { + app, ctx, vals, utxId, outbound, coreVals := + setupOutboundVotingTest(t, 4) + + // Vote as FAILED with gasFeeUsed set — refund should NOT run for failed outbounds + 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 provided but shouldn't trigger refund on failure + ) + 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 was executed (funds minted back) + require.NotNil(t, ob.PcRevertExecution) + require.Equal(t, "SUCCESS", ob.PcRevertExecution.Status) + + // Gas refund must NOT run for failed outbounds + require.Nil(t, ob.PcRefundExecution, + "gas refund must not run when outbound failed") + }) +} diff --git a/test/integration/uexecutor/vote_outbound_test.go b/test/integration/uexecutor/vote_outbound_test.go index 55312e7c..39d47be5 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, "", + "", ) require.NoError(t, err) @@ -125,6 +126,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + "", ) require.NoError(t, err) } @@ -155,6 +157,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + "", ) require.NoError(t, err) @@ -168,6 +171,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + "", ) require.Error(t, err) require.Contains(t, err.Error(), "already voted") @@ -192,6 +196,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + "", ) require.NoError(t, err) } @@ -210,6 +215,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + "", ) 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 + "", ) require.NoError(t, err) } @@ -274,6 +281,7 @@ func TestOutboundVoting(t *testing.T) { outbound, false, "failed", + "", ) require.NoError(t, err) } @@ -312,6 +320,7 @@ func TestOutboundVoting(t *testing.T) { &prefixedOutbound, true, "", + "", ) require.NoError(t, err) } @@ -342,6 +351,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", + "", ) require.Error(t, err) require.Contains(t, err.Error(), "not found") @@ -367,6 +377,7 @@ func TestOutboundVoting(t *testing.T) { &badOutbound, true, "", + "", ) require.Error(t, err) require.Contains(t, err.Error(), "not found") From 6fc159933ce4f6d11f43798a16298267d38cb7ad Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 18:59:02 +0530 Subject: [PATCH 35/75] tests: added integration tests for refund gas --- test/utils/helpers.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/utils/helpers.go b/test/utils/helpers.go index 037d376e..c06787d8 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{ From 82703f37b7cd06ba323b055fe3e6a185af8522c0 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Fri, 13 Mar 2026 18:59:08 +0530 Subject: [PATCH 36/75] refactor: added generated protobuf --- x/uexecutor/types/types.pb.go | 456 ++++++++++++++++++++++++++-------- 1 file changed, 346 insertions(+), 110 deletions(-) diff --git a/x/uexecutor/types/types.pb.go b/x/uexecutor/types/types.pb.go index b1656633..462d4216 100644 --- a/x/uexecutor/types/types.pb.go +++ b/x/uexecutor/types/types.pb.go @@ -740,6 +740,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 +804,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"` @@ -873,6 +881,9 @@ type OutboundTx struct { 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{} } @@ -1026,6 +1037,27 @@ func (m *OutboundTx) GetGasFee() string { 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"` @@ -1386,116 +1418,121 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/types.proto", fileDescriptor_fab6d3ca71d1e2a5) } var fileDescriptor_fab6d3ca71d1e2a5 = []byte{ - // 1742 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, 0x9d, 0xb4, 0x1d, 0xa0, 0x02, 0x8a, 0x42, 0x96, 0x69, 0x8f, 0x5a, 0x8f, 0xac, - 0x52, 0x92, 0x91, 0xe9, 0x86, 0xa0, 0xc9, 0x6b, 0x9a, 0xa8, 0x44, 0x0a, 0x7c, 0xa8, 0xf4, 0xa2, - 0xab, 0xee, 0x8a, 0x2e, 0xba, 0xcc, 0x32, 0xcb, 0xa2, 0xdd, 0xb4, 0x40, 0x7f, 0xc4, 0x2c, 0xa7, - 0xbb, 0x02, 0xdd, 0x14, 0x09, 0x8a, 0x16, 0xe8, 0x9f, 0x28, 0xee, 0x83, 0x22, 0xa9, 0xc7, 0x64, - 0x8a, 0x2c, 0x0a, 0x74, 0x63, 0xf1, 0x3c, 0xee, 0xe1, 0x77, 0xce, 0x77, 0xce, 0xb9, 0xb2, 0x40, - 0x0e, 0x71, 0x84, 0x8d, 0x30, 0x70, 0xbd, 0xe3, 0xd9, 0x27, 0xc7, 0xc1, 0xdd, 0x14, 0xfb, 0x47, - 0x53, 0xcf, 0x0d, 0x5c, 0xb4, 0x39, 0xb7, 0x1c, 0xcd, 0x3e, 0x79, 0xbc, 0x63, 0xb9, 0x96, 0x4b, - 0x0d, 0xc7, 0xe4, 0x89, 0xf9, 0x3c, 0xae, 0xeb, 0x13, 0xdb, 0x71, 0x8f, 0xe9, 0x5f, 0xa6, 0x6a, - 0x9e, 0x41, 0xb1, 0xaf, 0x7b, 0xfa, 0xc4, 0x47, 0xbb, 0x00, 0xbe, 0x3b, 0xc1, 0xda, 0x4c, 0x1f, - 0x87, 0x58, 0x16, 0xf7, 0x85, 0x83, 0xb2, 0x5a, 0x21, 0x9a, 0x2b, 0xa2, 0x68, 0xed, 0xbe, 0x7a, - 0xbd, 0xb7, 0xf1, 0xaf, 0xd7, 0x7b, 0xc2, 0xaf, 0xff, 0xf9, 0xc7, 0x43, 0x29, 0x81, 0x31, 0xa5, - 0xa7, 0x9b, 0x7f, 0x13, 0x41, 0x1a, 0x39, 0xf6, 0x0c, 0x7b, 0xbe, 0x3e, 0xee, 0xeb, 0x77, 0x63, - 0x57, 0x37, 0xd1, 0x16, 0x88, 0x81, 0x2b, 0x0b, 0xfb, 0xc2, 0x41, 0x45, 0x15, 0x03, 0x17, 0xed, - 0x40, 0x21, 0x89, 0x5e, 0x51, 0x99, 0x80, 0x10, 0xe4, 0x4d, 0x3d, 0xd0, 0xe5, 0x1c, 0x55, 0xd2, - 0x67, 0xf4, 0x04, 0x2a, 0x96, 0xee, 0x6b, 0x63, 0x7b, 0x62, 0x07, 0x72, 0x9e, 0x1a, 0xca, 0x96, - 0xee, 0x5f, 0x10, 0x19, 0x7d, 0x0c, 0xb5, 0x89, 0x1e, 0x69, 0x37, 0x18, 0x6b, 0x53, 0xec, 0x69, - 0x96, 0xee, 0xcb, 0x05, 0xea, 0xb2, 0x39, 0xd1, 0xa3, 0x33, 0x8c, 0xfb, 0xd8, 0x3b, 0xd7, 0x7d, - 0xf4, 0x29, 0xc8, 0xc4, 0x6d, 0xea, 0xd9, 0xae, 0x67, 0x07, 0x77, 0x19, 0xff, 0x22, 0xf5, 0xdf, - 0x99, 0xe8, 0x51, 0x9f, 0x9b, 0x93, 0x73, 0x3b, 0x50, 0x70, 0x5c, 0xc7, 0xc0, 0x72, 0x89, 0xa1, - 0xa4, 0x02, 0x7a, 0x0c, 0x65, 0x13, 0xeb, 0xe6, 0xd8, 0x76, 0xb0, 0x5c, 0x66, 0x80, 0x62, 0x19, - 0x7d, 0x1f, 0x8a, 0x33, 0x8d, 0x90, 0x21, 0x57, 0xf6, 0x85, 0x83, 0xad, 0x17, 0x8d, 0xa3, 0x34, - 0x19, 0x47, 0x57, 0xd8, 0xb3, 0x6f, 0x6c, 0x43, 0x0f, 0x6c, 0xd7, 0x19, 0xde, 0x4d, 0xb1, 0x5a, - 0x98, 0x91, 0x8f, 0xd6, 0x41, 0xba, 0xa4, 0x4f, 0x92, 0x92, 0x86, 0x71, 0x1d, 0xb5, 0x29, 0x2b, - 0x64, 0xf3, 0x37, 0x02, 0x48, 0x9f, 0xdb, 0x96, 0x47, 0x43, 0xc4, 0xd5, 0xfd, 0x00, 0x2a, 0x93, - 0x58, 0xc7, 0x8b, 0x9c, 0x28, 0x92, 0x2c, 0xc4, 0x75, 0x59, 0xe4, 0xb2, 0x59, 0xac, 0x85, 0x33, - 0x8f, 0x39, 0x87, 0xf3, 0x4a, 0x00, 0x34, 0x27, 0xbb, 0x6d, 0x18, 0x6e, 0xe8, 0x04, 0x5d, 0x13, - 0x3d, 0x83, 0x9a, 0x71, 0xab, 0xdb, 0x8e, 0xe6, 0xe8, 0x13, 0xec, 0x4f, 0x75, 0x03, 0x73, 0x58, - 0x5b, 0x54, 0xdd, 0x8b, 0xb5, 0xe8, 0x11, 0x94, 0x99, 0xa3, 0x6d, 0x72, 0x78, 0x25, 0x2a, 0x77, - 0x4d, 0x02, 0xdb, 0xfd, 0x85, 0x83, 0x3d, 0x8e, 0x8e, 0x09, 0xdf, 0xa0, 0x52, 0x3a, 0x43, 0xd1, - 0x34, 0x00, 0xa9, 0x78, 0x86, 0xbd, 0xa0, 0xeb, 0xf8, 0x81, 0x17, 0x1a, 0x04, 0xb7, 0x8f, 0x3e, - 0x86, 0xad, 0x9b, 0xd0, 0x31, 0x35, 0x0f, 0x1b, 0xf6, 0xd4, 0xc6, 0x4e, 0xc0, 0x81, 0xdd, 0x23, - 0x5a, 0x35, 0x56, 0xb6, 0xbe, 0x15, 0xbf, 0x62, 0x37, 0x79, 0x85, 0x47, 0xa3, 0x69, 0x76, 0x2a, - 0x5c, 0xf3, 0xdf, 0x39, 0x28, 0x75, 0x9d, 0x6b, 0x37, 0x74, 0x4c, 0xf4, 0x14, 0x36, 0x7d, 0x37, - 0xf4, 0x0c, 0xac, 0xd1, 0x14, 0x78, 0xe0, 0x2a, 0xd3, 0x75, 0x88, 0x0a, 0x3d, 0x84, 0x52, 0x10, - 0x69, 0xb7, 0xba, 0x7f, 0xcb, 0xb3, 0x2d, 0x06, 0xd1, 0x67, 0xba, 0x7f, 0x8b, 0x1e, 0x40, 0xd1, - 0xc7, 0x8e, 0x39, 0xcf, 0x96, 0x4b, 0x84, 0xd9, 0x04, 0x29, 0xeb, 0xfe, 0x44, 0x41, 0x4e, 0xe9, - 0x13, 0x92, 0x2c, 0xef, 0x7a, 0x2e, 0x91, 0x01, 0xd6, 0x7d, 0x1f, 0x07, 0x9a, 0x6e, 0x9a, 0x1e, - 0xef, 0xf0, 0x0a, 0xd5, 0xb4, 0x4d, 0xd3, 0x23, 0x23, 0x35, 0x76, 0x2d, 0xcd, 0x76, 0x4c, 0x1c, - 0xf1, 0xd6, 0x2e, 0x8f, 0x5d, 0xab, 0x4b, 0x64, 0xf4, 0x9c, 0x42, 0xa4, 0x2d, 0x5c, 0xa6, 0x2d, - 0xbc, 0x93, 0x6d, 0xe1, 0x61, 0x44, 0x1b, 0xb7, 0x18, 0xd0, 0x4f, 0xf4, 0x13, 0xa8, 0x2f, 0x35, - 0x29, 0xed, 0xfd, 0xea, 0x62, 0xef, 0x2f, 0xee, 0x04, 0x55, 0x0a, 0x17, 0xb7, 0xc4, 0xb7, 0xa1, - 0x3e, 0x4b, 0x4d, 0x88, 0x46, 0x97, 0x01, 0x50, 0x80, 0x52, 0xda, 0x70, 0x4a, 0x16, 0xc3, 0x4f, - 0x61, 0x7b, 0x05, 0x23, 0x72, 0x95, 0xbe, 0x7b, 0x3f, 0xfb, 0xee, 0xe5, 0x46, 0x50, 0x91, 0xb7, - 0xdc, 0x1c, 0x3b, 0x50, 0xb0, 0xfd, 0x8e, 0xd2, 0x96, 0x37, 0xe9, 0xce, 0x63, 0x42, 0xab, 0x1c, - 0xb7, 0x5c, 0xf3, 0x4b, 0x01, 0xf2, 0xfd, 0xce, 0x30, 0x4a, 0xf3, 0x28, 0xac, 0xe1, 0x51, 0xcc, - 0xf0, 0xf8, 0x08, 0xc8, 0xd2, 0xd2, 0x42, 0x1f, 0x9b, 0x94, 0xe1, 0xbc, 0x5a, 0xb2, 0x74, 0x7f, - 0xe4, 0x63, 0xda, 0x36, 0xd7, 0x63, 0xd7, 0xf8, 0xb9, 0x76, 0x8b, 0x6d, 0xeb, 0x96, 0xb1, 0x9c, - 0x57, 0xab, 0x54, 0xf7, 0x19, 0x55, 0xd1, 0xa8, 0x81, 0x1e, 0x84, 0xf1, 0xb6, 0xe2, 0x12, 0x21, - 0x12, 0x7b, 0x9e, 0xeb, 0x69, 0x13, 0xdf, 0x8a, 0x89, 0xa4, 0x8a, 0xcf, 0x7d, 0xab, 0xf5, 0x41, - 0x7a, 0x52, 0x6a, 0xa9, 0x35, 0x6d, 0x68, 0x41, 0xd4, 0xfc, 0x93, 0x00, 0xdb, 0x97, 0x61, 0x40, - 0x3b, 0xf7, 0xf2, 0xda, 0xc7, 0xde, 0x8c, 0x2d, 0x0b, 0x19, 0x4a, 0x7e, 0x68, 0x18, 0xd8, 0xf7, - 0x69, 0x66, 0x65, 0x35, 0x16, 0x97, 0x70, 0x8a, 0xcb, 0x38, 0x53, 0x65, 0xc9, 0x65, 0xca, 0x92, - 0x01, 0x9a, 0x5f, 0x00, 0xfa, 0x2c, 0x06, 0xd9, 0x48, 0x40, 0xba, 0x1c, 0x9a, 0xe6, 0x26, 0xd8, - 0x9a, 0x13, 0xa8, 0x5d, 0x7a, 0xb6, 0x65, 0x3b, 0x7a, 0x60, 0x3b, 0x56, 0xdf, 0xf8, 0x3a, 0x22, - 0x32, 0x3d, 0x2e, 0x66, 0x7b, 0xbc, 0xf5, 0xd1, 0x8a, 0x05, 0xe2, 0x26, 0x91, 0x35, 0x56, 0xa2, - 0x7f, 0x14, 0x00, 0xe2, 0x12, 0x0d, 0x23, 0xd2, 0x9c, 0x26, 0xf6, 0x03, 0xea, 0xe3, 0x3a, 0x99, - 0x19, 0x97, 0x52, 0x06, 0x36, 0xe8, 0x99, 0xb9, 0x15, 0xd7, 0xcf, 0x6d, 0x2e, 0x33, 0xb7, 0x47, - 0xb0, 0x8d, 0xa3, 0x00, 0x7b, 0x0e, 0x59, 0x63, 0xc9, 0x00, 0xb3, 0x82, 0xd5, 0x63, 0x53, 0x7b, - 0x3e, 0xc8, 0x07, 0x20, 0x4d, 0x3d, 0xe3, 0xc5, 0x77, 0xd2, 0xce, 0x6c, 0x13, 0x6c, 0x51, 0x7d, - 0xe2, 0x99, 0xf4, 0x65, 0x31, 0xd3, 0x97, 0x32, 0x94, 0xe2, 0xa1, 0x65, 0xfd, 0x13, 0x8b, 0xd9, - 0x7b, 0xb7, 0xbc, 0x70, 0xef, 0xa6, 0x96, 0x44, 0xe5, 0x1b, 0x2c, 0x89, 0x17, 0x50, 0xa0, 0x25, - 0xa5, 0xb3, 0x5c, 0x7d, 0xb1, 0x9b, 0x75, 0x5e, 0xe0, 0x54, 0xcd, 0x4f, 0x09, 0xb3, 0x27, 0x50, - 0x65, 0xdc, 0x63, 0x93, 0x9c, 0x64, 0x63, 0xfd, 0x74, 0xe1, 0xe4, 0x72, 0x03, 0xab, 0x10, 0x9f, - 0x1a, 0x46, 0xe4, 0x5b, 0x87, 0x6d, 0xd2, 0x61, 0xae, 0xa8, 0xa2, 0x6d, 0xa2, 0x1f, 0x42, 0x6d, - 0xde, 0x58, 0x7c, 0xa0, 0xee, 0xad, 0x82, 0x3f, 0xa0, 0x36, 0x75, 0x2b, 0x76, 0x66, 0xf2, 0xba, - 0x8d, 0xb3, 0xf5, 0x1e, 0x1b, 0xe7, 0x04, 0xb6, 0xa7, 0x86, 0xc6, 0xa3, 0xb2, 0xf3, 0xe4, 0x0e, - 0xaf, 0xd1, 0x90, 0x28, 0x1b, 0x92, 0x6c, 0x1e, 0xb5, 0x3e, 0x35, 0x58, 0x68, 0x25, 0x76, 0x8e, - 0x99, 0x9a, 0x7a, 0xb6, 0x81, 0x65, 0x69, 0xce, 0x54, 0x9f, 0xc8, 0x64, 0x40, 0x88, 0xf1, 0x06, - 0x63, 0xb9, 0xce, 0x98, 0xb7, 0x74, 0xff, 0x0c, 0xe3, 0xd4, 0x56, 0xfb, 0x9d, 0x08, 0xd5, 0xf9, - 0x72, 0x9e, 0x57, 0x4d, 0x98, 0x57, 0xed, 0x7b, 0x00, 0x36, 0xbb, 0xe2, 0x08, 0x11, 0x22, 0x85, - 0x76, 0x3f, 0x0b, 0x8d, 0x5f, 0x81, 0x6a, 0x85, 0x3b, 0x0e, 0x23, 0xf4, 0x2c, 0xe6, 0x3c, 0xb7, - 0x9f, 0x5b, 0x93, 0x0b, 0x23, 0xfa, 0x07, 0x50, 0x9d, 0x93, 0x12, 0x44, 0x72, 0x9e, 0xba, 0xcb, - 0xab, 0x89, 0x1e, 0x46, 0x2a, 0xb8, 0xc9, 0x48, 0xfe, 0x18, 0x92, 0x3b, 0x24, 0x26, 0xb4, 0x40, - 0x09, 0xdd, 0x5b, 0x73, 0xf7, 0x0c, 0x23, 0xce, 0x6d, 0x6d, 0x7e, 0x90, 0x29, 0x5a, 0x1f, 0xa6, - 0xd7, 0xe5, 0x83, 0x55, 0x5f, 0x2c, 0x82, 0xa8, 0xf9, 0x87, 0x1c, 0xdc, 0xe3, 0xb9, 0x5e, 0x60, - 0x4b, 0x37, 0xee, 0xfe, 0x4f, 0x2e, 0xfd, 0xd6, 0xe2, 0xa5, 0xff, 0x74, 0x25, 0xbf, 0x6c, 0xac, - 0x59, 0xe6, 0xff, 0xfb, 0x6f, 0x00, 0xad, 0xc6, 0xab, 0xd7, 0x7b, 0x42, 0x4c, 0x59, 0x3d, 0xa1, - 0x8c, 0x37, 0x61, 0xf3, 0x2f, 0x02, 0x48, 0x49, 0xe7, 0x70, 0xc2, 0xfe, 0xab, 0x35, 0xbe, 0x96, - 0xba, 0x0c, 0x45, 0xb9, 0xf5, 0x14, 0xe5, 0xbf, 0x86, 0xa2, 0xc2, 0x02, 0x45, 0xad, 0x66, 0x3a, - 0x9f, 0xfb, 0x2b, 0x2e, 0xc3, 0x20, 0x6a, 0xfe, 0x5e, 0x84, 0x7a, 0xaa, 0x9b, 0x79, 0x52, 0xad, - 0xcc, 0x88, 0x0a, 0xb4, 0xf8, 0x4f, 0x56, 0x52, 0xc8, 0xc9, 0x5b, 0x35, 0xa8, 0xe2, 0x3b, 0x06, - 0xf5, 0x47, 0xd9, 0x41, 0xcd, 0xad, 0xa2, 0x78, 0xb1, 0xdc, 0xef, 0x1c, 0xd7, 0xfc, 0x7b, 0x8c, - 0xab, 0xf0, 0x8e, 0x71, 0x3d, 0x3c, 0x07, 0x69, 0xf1, 0x3f, 0x2e, 0xf4, 0x00, 0x90, 0x6f, 0x5b, - 0x0e, 0x36, 0xd3, 0x16, 0x69, 0x03, 0x3d, 0x81, 0x87, 0x61, 0xf2, 0xda, 0x8c, 0x51, 0x38, 0xfc, - 0x55, 0xb6, 0xea, 0xfc, 0x3e, 0xf8, 0x10, 0xf6, 0x46, 0xbd, 0xee, 0x95, 0xa2, 0x0e, 0xda, 0x17, - 0xda, 0xf0, 0xa5, 0x36, 0x18, 0xb6, 0x87, 0xa3, 0x81, 0x36, 0xea, 0x0d, 0xfa, 0x4a, 0xa7, 0x7b, - 0xd6, 0x55, 0x4e, 0xa5, 0x0d, 0xb4, 0x0d, 0xb5, 0x6e, 0xef, 0xe4, 0x72, 0xd4, 0x3b, 0xd5, 0x06, - 0xa3, 0x4e, 0x47, 0x19, 0x0c, 0x24, 0x01, 0xed, 0xc2, 0xa3, 0xbe, 0xd2, 0x3b, 0xed, 0xf6, 0xce, - 0xb5, 0xd8, 0xa8, 0xbc, 0x54, 0x3a, 0xa3, 0x61, 0xf7, 0xb2, 0x27, 0x89, 0xe8, 0x21, 0x6c, 0xf7, - 0x3b, 0x5c, 0xa3, 0x24, 0xe7, 0x72, 0x04, 0x7c, 0xda, 0x70, 0xd6, 0xee, 0x5e, 0x28, 0xa7, 0x52, - 0x1e, 0xdd, 0x87, 0x7a, 0xbf, 0xa3, 0xc5, 0x21, 0x55, 0xe5, 0x4a, 0x51, 0x87, 0x52, 0x01, 0xed, - 0x80, 0x74, 0x39, 0x1a, 0xb2, 0xf8, 0xdc, 0x28, 0x15, 0x33, 0xda, 0x38, 0x74, 0x89, 0xe0, 0x9c, - 0x6b, 0x79, 0xdc, 0x32, 0xda, 0x84, 0x72, 0xa7, 0xdd, 0xeb, 0x28, 0x44, 0xaa, 0x1c, 0x9e, 0x40, - 0x91, 0x67, 0x5e, 0x83, 0x6a, 0x36, 0xcb, 0x2a, 0x94, 0xe2, 0x17, 0x08, 0xe4, 0xd4, 0xe5, 0xc9, - 0x40, 0x51, 0xaf, 0x94, 0x53, 0x49, 0x24, 0x12, 0x03, 0xa4, 0x9c, 0x4a, 0xb9, 0xc3, 0x5f, 0x42, - 0x91, 0x6d, 0x11, 0x84, 0x60, 0x2b, 0x15, 0x43, 0x1b, 0xbe, 0x94, 0x36, 0x50, 0x09, 0x72, 0xe7, - 0x6d, 0x52, 0xa0, 0x6d, 0xa8, 0x9d, 0xb7, 0x07, 0x5a, 0x9b, 0x00, 0x6f, 0x7f, 0x71, 0x71, 0xd9, - 0x26, 0x91, 0x2a, 0x50, 0x38, 0x1b, 0xf5, 0x4e, 0x49, 0x21, 0xee, 0x43, 0x9d, 0x3e, 0x66, 0x3c, - 0xf2, 0x14, 0x06, 0x17, 0x0a, 0xe4, 0x05, 0x71, 0x71, 0x79, 0x45, 0x8a, 0x87, 0x7f, 0x16, 0x60, - 0x7b, 0xc5, 0x32, 0x43, 0x4f, 0x61, 0x37, 0xf6, 0xbd, 0x50, 0xce, 0xdb, 0x9d, 0x2f, 0xb4, 0x25, - 0x6c, 0x0f, 0x00, 0x2d, 0xb8, 0x30, 0xa8, 0x32, 0xec, 0x2c, 0xe8, 0x19, 0x48, 0x11, 0x7d, 0x04, - 0xfb, 0xab, 0x2c, 0x19, 0xcc, 0x39, 0xd4, 0x84, 0xc6, 0x72, 0xdc, 0x6c, 0x5e, 0x27, 0xfd, 0x2f, - 0xdf, 0x34, 0x84, 0xaf, 0xde, 0x34, 0x84, 0xbf, 0xbf, 0x69, 0x08, 0xbf, 0x7d, 0xdb, 0xd8, 0xf8, - 0xea, 0x6d, 0x63, 0xe3, 0xaf, 0x6f, 0x1b, 0x1b, 0x3f, 0xfb, 0xd4, 0xb2, 0x83, 0xdb, 0xf0, 0xfa, - 0xc8, 0x70, 0x27, 0xc7, 0xd3, 0xd0, 0xbf, 0xa5, 0xfb, 0x8c, 0x3e, 0x3d, 0xa7, 0x8f, 0xcf, 0x1d, - 0xd7, 0xc4, 0xc7, 0xd1, 0x71, 0x32, 0x21, 0xf4, 0xa7, 0xa2, 0xeb, 0x22, 0xfd, 0xd1, 0xe7, 0xbb, - 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x3e, 0x6c, 0xeb, 0x47, 0x12, 0x00, 0x00, + // 1811 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, + 0xe8, 0xa9, 0xb7, 0xa2, 0x87, 0x1e, 0x73, 0xcc, 0xb1, 0x68, 0x2f, 0x3d, 0xf4, 0x43, 0xec, 0x71, + 0x8b, 0x5e, 0x0a, 0xf4, 0x52, 0x24, 0x87, 0x16, 0xe8, 0xad, 0x9f, 0xa0, 0x78, 0x7f, 0x28, 0x92, + 0xb2, 0x94, 0x6c, 0xb1, 0x87, 0x02, 0xbd, 0x58, 0x9c, 0x79, 0xf3, 0xe6, 0xfd, 0x66, 0xe6, 0x37, + 0xf3, 0x68, 0x82, 0x32, 0x23, 0x21, 0x31, 0x66, 0x81, 0xeb, 0x1d, 0xce, 0x3f, 0x39, 0x0c, 0x6e, + 0xa6, 0xc4, 0x3f, 0x98, 0x7a, 0x6e, 0xe0, 0xa2, 0xcd, 0xc5, 0xca, 0xc1, 0xfc, 0x93, 0x87, 0x0d, + 0xcb, 0xb5, 0x5c, 0xb6, 0x70, 0x48, 0x9f, 0xb8, 0xcd, 0xc3, 0x1a, 0x9e, 0xd8, 0x8e, 0x7b, 0xc8, + 0xfe, 0x72, 0x55, 0xeb, 0x04, 0x0a, 0x03, 0xec, 0xe1, 0x89, 0x8f, 0xb6, 0x01, 0x7c, 0x77, 0x42, + 0xf4, 0x39, 0xbe, 0x9e, 0x11, 0x25, 0xb3, 0x2b, 0xed, 0x95, 0xb4, 0x32, 0xd5, 0x5c, 0x50, 0x45, + 0x7b, 0xfb, 0xd5, 0xeb, 0x9d, 0x8d, 0x7f, 0xbe, 0xde, 0x91, 0x7e, 0xfd, 0x8f, 0x3f, 0xee, 0xcb, + 0x31, 0x8c, 0x29, 0xdb, 0xdd, 0xfa, 0x5b, 0x06, 0xe4, 0xb1, 0x63, 0xcf, 0x89, 0xe7, 0xe3, 0xeb, + 0x01, 0xbe, 0xb9, 0x76, 0xb1, 0x89, 0xb6, 0x20, 0x13, 0xb8, 0x8a, 0xb4, 0x2b, 0xed, 0x95, 0xb5, + 0x4c, 0xe0, 0xa2, 0x06, 0xe4, 0x63, 0xef, 0x65, 0x8d, 0x0b, 0x08, 0x41, 0xce, 0xc4, 0x01, 0x56, + 0xb2, 0x4c, 0xc9, 0x9e, 0xd1, 0x23, 0x28, 0x5b, 0xd8, 0xd7, 0xaf, 0xed, 0x89, 0x1d, 0x28, 0x39, + 0xb6, 0x50, 0xb2, 0xb0, 0x7f, 0x46, 0x65, 0xf4, 0x31, 0x54, 0x27, 0x38, 0xd4, 0x5f, 0x10, 0xa2, + 0x4f, 0x89, 0xa7, 0x5b, 0xd8, 0x57, 0xf2, 0xcc, 0x64, 0x73, 0x82, 0xc3, 0x13, 0x42, 0x06, 0xc4, + 0x3b, 0xc5, 0x3e, 0xfa, 0x14, 0x14, 0x6a, 0x36, 0xf5, 0x6c, 0xd7, 0xb3, 0x83, 0x9b, 0x94, 0x7d, + 0x81, 0xd9, 0x37, 0x26, 0x38, 0x1c, 0x88, 0xe5, 0x78, 0x5f, 0x03, 0xf2, 0x8e, 0xeb, 0x18, 0x44, + 0x29, 0x72, 0x94, 0x4c, 0x40, 0x0f, 0xa1, 0x64, 0x12, 0x6c, 0x5e, 0xdb, 0x0e, 0x51, 0x4a, 0x1c, + 0x50, 0x24, 0xa3, 0x1f, 0x42, 0x61, 0xae, 0xd3, 0x62, 0x28, 0xe5, 0x5d, 0x69, 0x6f, 0xeb, 0x59, + 0xf3, 0x20, 0x59, 0x8c, 0x83, 0x0b, 0xe2, 0xd9, 0x2f, 0x6c, 0x03, 0x07, 0xb6, 0xeb, 0x8c, 0x6e, + 0xa6, 0x44, 0xcb, 0xcf, 0xe9, 0x4f, 0x7b, 0x2f, 0x99, 0xd2, 0x47, 0x71, 0x4a, 0x67, 0x51, 0x1e, + 0xf5, 0x29, 0x4f, 0x64, 0xeb, 0x37, 0x12, 0xc8, 0x9f, 0xdb, 0x96, 0xc7, 0x5c, 0x44, 0xd9, 0xfd, + 0x00, 0xca, 0x93, 0x48, 0x27, 0x92, 0x1c, 0x2b, 0xe2, 0x28, 0x32, 0xeb, 0xa2, 0xc8, 0xa6, 0xa3, + 0x58, 0x0b, 0x67, 0xe1, 0x73, 0x01, 0xe7, 0x95, 0x04, 0x68, 0x51, 0xec, 0x8e, 0x61, 0xb8, 0x33, + 0x27, 0xe8, 0x99, 0xe8, 0x09, 0x54, 0x8d, 0x2b, 0x6c, 0x3b, 0xba, 0x83, 0x27, 0xc4, 0x9f, 0x62, + 0x83, 0x08, 0x58, 0x5b, 0x4c, 0xdd, 0x8f, 0xb4, 0xe8, 0x01, 0x94, 0xb8, 0xa1, 0x6d, 0x0a, 0x78, + 0x45, 0x26, 0xf7, 0x4c, 0x0a, 0xdb, 0x7d, 0xe9, 0x10, 0x4f, 0xa0, 0xe3, 0xc2, 0x37, 0xc8, 0x14, + 0xe6, 0x28, 0x5a, 0x06, 0x20, 0x8d, 0xcc, 0x89, 0x17, 0xf4, 0x1c, 0x3f, 0xf0, 0x66, 0x06, 0xc5, + 0xed, 0xa3, 0x8f, 0x61, 0xeb, 0xc5, 0xcc, 0x31, 0x75, 0x8f, 0x18, 0xf6, 0xd4, 0x26, 0x4e, 0x20, + 0x80, 0xdd, 0xa1, 0x5a, 0x2d, 0x52, 0xb6, 0xbf, 0x13, 0x1d, 0xb1, 0x1d, 0x1f, 0xe1, 0x31, 0x6f, + 0xba, 0x9d, 0x70, 0xd7, 0xfa, 0x57, 0x16, 0x8a, 0x3d, 0xe7, 0xd2, 0x9d, 0x39, 0x26, 0x7a, 0x0c, + 0x9b, 0xbe, 0x3b, 0xf3, 0x0c, 0xa2, 0xb3, 0x10, 0x84, 0xe3, 0x0a, 0xd7, 0x75, 0xa9, 0x0a, 0xdd, + 0x87, 0x62, 0x10, 0xea, 0x57, 0xd8, 0xbf, 0x12, 0xd1, 0x16, 0x82, 0xf0, 0x33, 0xec, 0x5f, 0xa1, + 0x7b, 0x50, 0xf0, 0x89, 0x63, 0x2e, 0xa2, 0x15, 0x12, 0xad, 0x6c, 0x8c, 0x94, 0xb3, 0x3f, 0x56, + 0xd0, 0x5d, 0x78, 0x42, 0x83, 0x15, 0xac, 0x17, 0x12, 0x6d, 0x60, 0xec, 0xfb, 0x24, 0xd0, 0xb1, + 0x69, 0x7a, 0x82, 0xe1, 0x65, 0xa6, 0xe9, 0x98, 0xa6, 0x47, 0x5b, 0xea, 0xda, 0xb5, 0x74, 0xdb, + 0x31, 0x49, 0x28, 0xa8, 0x5d, 0xba, 0x76, 0xad, 0x1e, 0x95, 0xd1, 0x53, 0x06, 0x91, 0x51, 0xb8, + 0xc4, 0x28, 0xdc, 0x48, 0x53, 0x78, 0x14, 0x32, 0xe2, 0x16, 0x02, 0xf6, 0x8b, 0x7e, 0x06, 0xb5, + 0x5b, 0x24, 0x65, 0xdc, 0xaf, 0x2c, 0x73, 0x7f, 0x79, 0x26, 0x68, 0xf2, 0x6c, 0x79, 0x4a, 0x7c, + 0x17, 0x6a, 0xf3, 0x44, 0x87, 0xe8, 0x6c, 0x18, 0x00, 0x03, 0x28, 0x27, 0x17, 0x8e, 0xe9, 0x60, + 0xf8, 0x39, 0xd4, 0x57, 0x54, 0x44, 0xa9, 0xb0, 0xb3, 0x77, 0xd3, 0x67, 0xdf, 0x26, 0x82, 0x86, + 0xbc, 0xdb, 0xe4, 0x68, 0x40, 0xde, 0xf6, 0xbb, 0x6a, 0x47, 0xd9, 0x64, 0x33, 0x8f, 0x0b, 0xed, + 0x52, 0x44, 0xb9, 0xd6, 0x57, 0x12, 0xe4, 0x06, 0xdd, 0x51, 0x98, 0xac, 0xa3, 0xb4, 0xa6, 0x8e, + 0x99, 0x54, 0x1d, 0x1f, 0x00, 0x1d, 0x5a, 0xfa, 0xcc, 0x27, 0x26, 0xab, 0x70, 0x4e, 0x2b, 0x5a, + 0xd8, 0x1f, 0xfb, 0x84, 0xd1, 0xe6, 0xf2, 0xda, 0x35, 0xbe, 0xd4, 0xaf, 0x88, 0x6d, 0x5d, 0xf1, + 0x2a, 0xe7, 0xb4, 0x0a, 0xd3, 0x7d, 0xc6, 0x54, 0xcc, 0x6b, 0x80, 0x83, 0x59, 0x34, 0xad, 0x84, + 0x44, 0x0b, 0x49, 0x3c, 0xcf, 0xf5, 0xf4, 0x89, 0x6f, 0x45, 0x85, 0x64, 0x8a, 0xcf, 0x7d, 0xab, + 0xfd, 0x41, 0xb2, 0x53, 0xaa, 0x89, 0x31, 0x6d, 0xe8, 0x41, 0xd8, 0xfa, 0x8b, 0x04, 0xf5, 0xf3, + 0x59, 0xc0, 0x98, 0x7b, 0x7e, 0xe9, 0x13, 0x6f, 0xce, 0x87, 0x85, 0x02, 0x45, 0x7f, 0x66, 0x18, + 0xc4, 0xf7, 0x59, 0x64, 0x25, 0x2d, 0x12, 0x6f, 0xe1, 0xcc, 0xdc, 0xc6, 0x99, 0x48, 0x4b, 0x36, + 0x95, 0x96, 0x14, 0xd0, 0x5c, 0x1a, 0x28, 0xda, 0x85, 0x4d, 0x9a, 0x1b, 0x3a, 0x94, 0x59, 0x7e, + 0x38, 0x97, 0xc1, 0xc2, 0xfe, 0x09, 0x21, 0x34, 0x45, 0xed, 0x27, 0x51, 0x18, 0xcd, 0x38, 0x0c, + 0x57, 0x80, 0xd7, 0xdd, 0x18, 0x7d, 0x6b, 0x02, 0xd5, 0x73, 0xcf, 0xb6, 0x6c, 0x07, 0x07, 0xb6, + 0x63, 0x0d, 0x8c, 0x77, 0x95, 0x2a, 0xd5, 0x05, 0x99, 0x74, 0x17, 0xb4, 0x3f, 0x5a, 0x31, 0x62, + 0xdc, 0xd8, 0xb3, 0xce, 0x93, 0xf8, 0xef, 0x02, 0x40, 0x94, 0xc4, 0x51, 0x48, 0xe9, 0x6b, 0x12, + 0x3f, 0x60, 0x36, 0xae, 0x93, 0x9a, 0x02, 0x72, 0x62, 0x81, 0x8f, 0x82, 0x54, 0x67, 0x67, 0xd6, + 0x77, 0x76, 0x36, 0xd5, 0xd9, 0x07, 0x50, 0x27, 0x61, 0x40, 0x3c, 0x87, 0x0e, 0xba, 0xb8, 0xc5, + 0x79, 0x4a, 0x6b, 0xd1, 0x52, 0x67, 0xd1, 0xea, 0x7b, 0x20, 0x4f, 0x3d, 0xe3, 0xd9, 0xf7, 0x92, + 0xc6, 0x3c, 0xbf, 0x5b, 0x4c, 0x1f, 0x5b, 0xc6, 0xcc, 0x2d, 0xa4, 0x98, 0xab, 0x40, 0x31, 0x6a, + 0x6b, 0xce, 0xb0, 0x48, 0x4c, 0xdf, 0xcc, 0xa5, 0xa5, 0x9b, 0x39, 0x31, 0x46, 0xca, 0xdf, 0x60, + 0x8c, 0x3c, 0x83, 0x3c, 0x4b, 0x29, 0xeb, 0xf6, 0xca, 0xb3, 0xed, 0xb4, 0xf1, 0x52, 0x4d, 0xb5, + 0xdc, 0x94, 0x56, 0xf6, 0x08, 0x2a, 0xbc, 0xf6, 0xc4, 0xa4, 0x3b, 0x79, 0xe3, 0x3f, 0x5e, 0xda, + 0x79, 0x9b, 0xe2, 0x1a, 0x44, 0xbb, 0x46, 0x21, 0x7d, 0x2f, 0xb1, 0x4d, 0xd6, 0xee, 0x65, 0x2d, + 0x63, 0x9b, 0xe8, 0xc7, 0x50, 0x5d, 0x10, 0x4b, 0xb4, 0xdc, 0x9d, 0x55, 0xf0, 0x87, 0x6c, 0x4d, + 0xdb, 0x8a, 0x8c, 0xb9, 0xbc, 0x6e, 0x26, 0x6d, 0x7d, 0x8b, 0x99, 0x74, 0x04, 0xf5, 0xa9, 0xa1, + 0x0b, 0xaf, 0x7c, 0x3f, 0xbd, 0xe5, 0xab, 0xcc, 0x25, 0x4a, 0xbb, 0xa4, 0xb3, 0x49, 0xab, 0x4d, + 0x0d, 0xee, 0x5a, 0x8d, 0x8c, 0xa3, 0x4a, 0x4d, 0x3d, 0xdb, 0x20, 0x8a, 0xbc, 0xa8, 0xd4, 0x80, + 0xca, 0xb4, 0x41, 0x44, 0xfb, 0x29, 0x35, 0x5e, 0x79, 0xde, 0x79, 0x8b, 0x93, 0xd9, 0x7d, 0x19, + 0x9f, 0x8c, 0xde, 0x7d, 0x32, 0xb5, 0x8e, 0x4f, 0xde, 0x87, 0x9a, 0x70, 0xe0, 0xbf, 0xc4, 0x53, + 0x9d, 0xf5, 0xbc, 0x52, 0x67, 0xc7, 0x54, 0xf9, 0xc2, 0xf0, 0x25, 0x9e, 0xaa, 0x54, 0x1d, 0xa1, + 0x0c, 0xdc, 0x2f, 0x89, 0xa3, 0x34, 0x16, 0x28, 0x47, 0x54, 0x4e, 0x0c, 0xe1, 0xdf, 0x65, 0xa0, + 0xb2, 0xb8, 0x4b, 0x16, 0x25, 0x94, 0x16, 0x25, 0xfc, 0x01, 0x80, 0xcd, 0x6f, 0x64, 0xca, 0x8a, + 0x0c, 0x43, 0x7b, 0x37, 0x8d, 0x56, 0xdc, 0xd8, 0x5a, 0x59, 0x18, 0x8e, 0x42, 0xf4, 0x24, 0x22, + 0x60, 0x76, 0x37, 0xbb, 0x26, 0x3c, 0xce, 0xba, 0x1f, 0x41, 0x65, 0xc1, 0x90, 0x20, 0x54, 0x72, + 0xcc, 0x5c, 0x59, 0xcd, 0xba, 0x51, 0xa8, 0x81, 0x1b, 0xcf, 0x87, 0x9f, 0x42, 0x7c, 0xe5, 0x45, + 0xec, 0xca, 0x33, 0x76, 0xed, 0xac, 0xb9, 0x2a, 0x47, 0xa1, 0x20, 0x5a, 0x75, 0xb1, 0x91, 0x2b, + 0xda, 0x1f, 0x26, 0xa7, 0xfb, 0xbd, 0x55, 0xef, 0x41, 0x41, 0xd8, 0xfa, 0x43, 0x16, 0xee, 0x88, + 0x58, 0xcf, 0x88, 0x85, 0x8d, 0x9b, 0xff, 0x93, 0x77, 0x94, 0xf6, 0xf2, 0x3b, 0xca, 0xe3, 0x95, + 0xf5, 0xe5, 0x33, 0x86, 0x47, 0xfe, 0xbf, 0x7f, 0x61, 0x69, 0x37, 0x5f, 0xbd, 0xde, 0x91, 0xa2, + 0x92, 0xd5, 0xe2, 0x92, 0x09, 0x12, 0xb6, 0xfe, 0x2c, 0x81, 0x1c, 0x33, 0x47, 0x14, 0xec, 0xbf, + 0xba, 0x53, 0xd6, 0x96, 0x2e, 0x55, 0xa2, 0xec, 0xfa, 0x12, 0xe5, 0xde, 0x51, 0xa2, 0xfc, 0x52, + 0x89, 0xda, 0xad, 0x64, 0x3c, 0x77, 0x57, 0xdc, 0xcc, 0x41, 0xd8, 0xfa, 0x7d, 0x06, 0x6a, 0x09, + 0x36, 0x8b, 0xa0, 0xda, 0xa9, 0x16, 0x95, 0x58, 0xf2, 0x1f, 0xad, 0x2c, 0xa1, 0x28, 0xde, 0xaa, + 0x46, 0xcd, 0xbc, 0xa7, 0x51, 0x7f, 0x92, 0x6e, 0xd4, 0xec, 0xaa, 0x12, 0x2f, 0xa7, 0xfb, 0xbd, + 0xed, 0x9a, 0xfb, 0x16, 0xed, 0x2a, 0xbd, 0xa7, 0x5d, 0xf7, 0x4f, 0x41, 0x5e, 0xfe, 0x07, 0x11, + 0xdd, 0x03, 0xe4, 0xdb, 0x96, 0x43, 0xcc, 0xe4, 0x8a, 0xbc, 0x81, 0x1e, 0xc1, 0xfd, 0x59, 0x7c, + 0x6c, 0x6a, 0x51, 0xda, 0xff, 0x55, 0x3a, 0xeb, 0xe2, 0x72, 0xfa, 0x10, 0x76, 0xc6, 0xfd, 0xde, + 0x85, 0xaa, 0x0d, 0x3b, 0x67, 0xfa, 0xe8, 0xb9, 0x3e, 0x1c, 0x75, 0x46, 0xe3, 0xa1, 0x3e, 0xee, + 0x0f, 0x07, 0x6a, 0xb7, 0x77, 0xd2, 0x53, 0x8f, 0xe5, 0x0d, 0x54, 0x87, 0x6a, 0xaf, 0x7f, 0x74, + 0x3e, 0xee, 0x1f, 0xeb, 0xc3, 0x71, 0xb7, 0xab, 0x0e, 0x87, 0xb2, 0x84, 0xb6, 0xe1, 0xc1, 0x40, + 0xed, 0x1f, 0xf7, 0xfa, 0xa7, 0x7a, 0xb4, 0xa8, 0x3e, 0x57, 0xbb, 0xe3, 0x51, 0xef, 0xbc, 0x2f, + 0x67, 0xd0, 0x7d, 0xa8, 0x0f, 0xba, 0x42, 0xa3, 0xc6, 0xfb, 0xb2, 0x14, 0x7c, 0x72, 0xe1, 0xa4, + 0xd3, 0x3b, 0x53, 0x8f, 0xe5, 0x1c, 0xba, 0x0b, 0xb5, 0x41, 0x57, 0x8f, 0x5c, 0x6a, 0xea, 0x85, + 0xaa, 0x8d, 0xe4, 0x3c, 0x6a, 0x80, 0x7c, 0x3e, 0x1e, 0x71, 0xff, 0x62, 0x51, 0x2e, 0xa4, 0xb4, + 0x91, 0xeb, 0x22, 0xc5, 0xb9, 0xd0, 0x0a, 0xbf, 0x25, 0xb4, 0x09, 0xa5, 0x6e, 0xa7, 0xdf, 0x55, + 0xa9, 0x54, 0xde, 0x3f, 0x82, 0x82, 0x88, 0xbc, 0x0a, 0x95, 0x74, 0x94, 0x15, 0x28, 0x46, 0x07, + 0x48, 0x74, 0xd7, 0xf9, 0xd1, 0x50, 0xd5, 0x2e, 0xd4, 0x63, 0x39, 0x43, 0x25, 0x0e, 0x48, 0x3d, + 0x96, 0xb3, 0xfb, 0xbf, 0x84, 0x02, 0x9f, 0x22, 0x08, 0xc1, 0x56, 0xc2, 0x87, 0x3e, 0x7a, 0x2e, + 0x6f, 0xa0, 0x22, 0x64, 0x4f, 0x3b, 0x34, 0x41, 0x75, 0xa8, 0x9e, 0x76, 0x86, 0x7a, 0x87, 0x02, + 0xef, 0x7c, 0x71, 0x76, 0xde, 0xa1, 0x9e, 0xca, 0x90, 0x3f, 0x19, 0xf7, 0x8f, 0x69, 0x22, 0xee, + 0x42, 0x8d, 0x3d, 0xa6, 0x2c, 0x72, 0x0c, 0x86, 0x10, 0xf2, 0xf4, 0x80, 0x28, 0xb9, 0x22, 0x23, + 0x85, 0xfd, 0x3f, 0x49, 0x50, 0x5f, 0x31, 0xcc, 0xd0, 0x63, 0xd8, 0x8e, 0x6c, 0xcf, 0xd4, 0xd3, + 0x4e, 0xf7, 0x0b, 0xfd, 0x16, 0xb6, 0x7b, 0x80, 0x96, 0x4c, 0x38, 0x54, 0x05, 0x1a, 0x4b, 0x7a, + 0x0e, 0x32, 0x83, 0x3e, 0x82, 0xdd, 0x55, 0x2b, 0x29, 0xcc, 0x59, 0xd4, 0x82, 0xe6, 0x6d, 0xbf, + 0xe9, 0xb8, 0x8e, 0x06, 0x5f, 0xbd, 0x69, 0x4a, 0x5f, 0xbf, 0x69, 0x4a, 0x7f, 0x7f, 0xd3, 0x94, + 0x7e, 0xfb, 0xb6, 0xb9, 0xf1, 0xf5, 0xdb, 0xe6, 0xc6, 0x5f, 0xdf, 0x36, 0x37, 0x7e, 0xf1, 0xa9, + 0x65, 0x07, 0x57, 0xb3, 0xcb, 0x03, 0xc3, 0x9d, 0x1c, 0x4e, 0x67, 0xfe, 0x15, 0x9b, 0x67, 0xec, + 0xe9, 0x29, 0x7b, 0x7c, 0xea, 0xb8, 0x26, 0x39, 0x0c, 0x0f, 0xe3, 0x0e, 0x61, 0x5f, 0xb6, 0x2e, + 0x0b, 0xec, 0x1b, 0xd5, 0xf7, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xd2, 0xba, 0xeb, 0xd8, 0xf6, + 0x12, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -1781,6 +1818,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 { @@ -1880,6 +1920,15 @@ func (this *OutboundTx) Equal(that interface{}) bool { 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 { @@ -2487,6 +2536,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) @@ -2576,6 +2632,38 @@ 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) @@ -3241,6 +3329,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 } @@ -3333,6 +3425,18 @@ func (m *OutboundTx) Size() (n int) { 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 } @@ -5011,6 +5115,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:]) @@ -5709,6 +5845,106 @@ func (m *OutboundTx) Unmarshal(dAtA []byte) error { } 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:]) From 645a7b0c61adb5d433f040ded0389bc4fe8da87e Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 16:18:48 +0530 Subject: [PATCH 37/75] fix: event structure & vote --- universalClient/chains/common/event_processor.go | 8 ++++++++ universalClient/chains/common/types.go | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/universalClient/chains/common/event_processor.go b/universalClient/chains/common/event_processor.go index 705306ac..b0ee937a 100644 --- a/universalClient/chains/common/event_processor.go +++ b/universalClient/chains/common/event_processor.go @@ -288,6 +288,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 +300,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 diff --git a/universalClient/chains/common/types.go b/universalClient/chains/common/types.go index e78c100b..53735c53 100644 --- a/universalClient/chains/common/types.go +++ b/universalClient/chains/common/types.go @@ -69,8 +69,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 From db5e77996ec5d2bdc2e1c405579a0ab80ad812c6 Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 16:20:03 +0530 Subject: [PATCH 38/75] fix: svm event parsing, add is CEA & change revertRecipient parsing --- universalClient/chains/svm/event_parser.go | 43 ++++------------------ 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/universalClient/chains/svm/event_parser.go b/universalClient/chains/svm/event_parser.go index 8d7072d8..8640c65f 100644 --- a/universalClient/chains/svm/event_parser.go +++ b/universalClient/chains/svm/event_parser.go @@ -301,10 +301,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 +310,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 +343,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 +357,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") From 96d64ac6a602803846f19aafa9b41c87fb2322f1 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Mon, 16 Mar 2026 16:31:00 +0530 Subject: [PATCH 39/75] ci: added logs in upgradeHandler --- app/upgrades/chain-meta/upgrade.go | 71 ++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/app/upgrades/chain-meta/upgrade.go b/app/upgrades/chain-meta/upgrade.go index 73da6a4b..eb648e15 100644 --- a/app/upgrades/chain-meta/upgrade.go +++ b/app/upgrades/chain-meta/upgrade.go @@ -33,9 +33,74 @@ func CreateUpgradeHandler( ) upgradetypes.UpgradeHandler { return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { sdkCtx := sdk.UnwrapSDKContext(ctx) - sdkCtx.Logger().Info("🔧 Running upgrade:", "name", UpgradeName) + logger := sdkCtx.Logger().With("upgrade", UpgradeName) + logger.Info("Starting upgrade handler") - // RunMigrations triggers uexecutor v4→v5 which calls MigrateGasPricesToChainMeta. - return mm.RunMigrations(ctx, configurator, fromVM) + // ── 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; observedAt is set to 0 as it was not + // tracked previously). + 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 } } From d6af047a5cfce18e8c2ca9e852c234192c8b936e Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 16:59:23 +0530 Subject: [PATCH 40/75] fix: evm parsing --- universalClient/chains/evm/event_parser.go | 269 +++++++++++---------- 1 file changed, 141 insertions(+), 128 deletions(-) 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 From d31609779ec0b1884a7e3d05766c0234ac615254 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Mon, 16 Mar 2026 17:01:45 +0530 Subject: [PATCH 41/75] feat: added a validation for gas_fee_used if success is true --- .../uexecutor/gas_fee_refund_test.go | 47 +++++++------------ .../uexecutor/vote_outbound_test.go | 18 +++---- x/uexecutor/types/msg_vote_outbound.go | 6 ++- 3 files changed, 32 insertions(+), 39 deletions(-) diff --git a/test/integration/uexecutor/gas_fee_refund_test.go b/test/integration/uexecutor/gas_fee_refund_test.go index 2194488d..e1480c31 100644 --- a/test/integration/uexecutor/gas_fee_refund_test.go +++ b/test/integration/uexecutor/gas_fee_refund_test.go @@ -13,39 +13,28 @@ import ( func TestGasFeeRefund(t *testing.T) { - t.Run("no refund when gasFeeUsed is empty", func(t *testing.T) { + t.Run("success vote with empty gasFeeUsed is rejected", func(t *testing.T) { app, ctx, vals, utxId, outbound, coreVals := setupOutboundVotingTest(t, 4) - 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 empty → no refund - ) - require.NoError(t, err) - } - - utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + valAddr, err := sdk.ValAddressFromBech32(coreVals[0].OperatorAddress) require.NoError(t, err) - - ob := utx.OutboundTx[0] - require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) - require.True(t, ob.ObservedTx.Success) - // No refund should be triggered - require.Nil(t, ob.PcRefundExecution, "no refund expected when gasFeeUsed is empty") - require.Empty(t, ob.RefundSwapError) + coreAcc := sdk.AccAddress(valAddr).String() + + err = utils.ExecVoteOutbound( + t, + ctx, + app, + vals[0], + coreAcc, + utxId, + outbound, + true, + "", + "", // gas_fee_used required when success=true → must be rejected + ) + require.Error(t, err) + require.Contains(t, err.Error(), "gas_fee_used required when success=true") }) t.Run("no refund when gasFeeUsed equals gasFee", func(t *testing.T) { diff --git a/test/integration/uexecutor/vote_outbound_test.go b/test/integration/uexecutor/vote_outbound_test.go index 39d47be5..40e2f8d3 100644 --- a/test/integration/uexecutor/vote_outbound_test.go +++ b/test/integration/uexecutor/vote_outbound_test.go @@ -94,7 +94,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", - "", + outbound.GasFee, ) require.NoError(t, err) @@ -126,7 +126,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", - "", + outbound.GasFee, ) require.NoError(t, err) } @@ -157,7 +157,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", - "", + outbound.GasFee, ) require.NoError(t, err) @@ -171,7 +171,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", - "", + outbound.GasFee, ) require.Error(t, err) require.Contains(t, err.Error(), "already voted") @@ -196,7 +196,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", - "", + outbound.GasFee, ) require.NoError(t, err) } @@ -215,7 +215,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", - "", + outbound.GasFee, ) require.Error(t, err) require.Contains(t, err.Error(), "already finalized") @@ -320,7 +320,7 @@ func TestOutboundVoting(t *testing.T) { &prefixedOutbound, true, "", - "", + outbound.GasFee, ) require.NoError(t, err) } @@ -351,7 +351,7 @@ func TestOutboundVoting(t *testing.T) { outbound, true, "", - "", + outbound.GasFee, ) require.Error(t, err) require.Contains(t, err.Error(), "not found") @@ -377,7 +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/x/uexecutor/types/msg_vote_outbound.go b/x/uexecutor/types/msg_vote_outbound.go index 61f01170..9b9ce866 100644 --- a/x/uexecutor/types/msg_vote_outbound.go +++ b/x/uexecutor/types/msg_vote_outbound.go @@ -69,7 +69,7 @@ func (msg *MsgVoteOutbound) ValidateBasic() error { obs := msg.ObservedTx if obs.Success { - // Success requires tx_hash AND block_height > 0 + // Success requires tx_hash AND block_height > 0 AND gas_fee_used if strings.TrimSpace(obs.TxHash) == "" { return errors.Wrap(sdkerrors.ErrInvalidRequest, "observed_tx.tx_hash required when success=true") @@ -78,6 +78,10 @@ func (msg *MsgVoteOutbound) ValidateBasic() error { return errors.Wrap(sdkerrors.ErrInvalidRequest, "observed_tx.block_height must be > 0 when success=true") } + if strings.TrimSpace(obs.GasFeeUsed) == "" { + return errors.Wrap(sdkerrors.ErrInvalidRequest, + "observed_tx.gas_fee_used required when success=true") + } } else { // Failure case: From c88aa4933394267429003971b784b3dd9cb40f70 Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 17:16:47 +0530 Subject: [PATCH 42/75] fix: chainMetaVoting --- universalClient/constant/constant.go | 2 +- .../pushsigner/grant_verifier_test.go | 18 +++++++++--------- universalClient/pushsigner/pushsigner.go | 6 +++--- universalClient/pushsigner/pushsigner_test.go | 6 +++--- universalClient/pushsigner/vote.go | 14 ++++++++------ 5 files changed, 24 insertions(+), 22 deletions(-) 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_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..57aeadef 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, observation timestamp). +func (s *Signer) VoteChainMeta(ctx context.Context, chainID string, price uint64, chainHeight uint64, observedAt uint64) (string, error) { + return voteChainMeta(ctx, s, s.log, s.granter, chainID, price, chainHeight, observedAt) } // VoteOutbound votes on an outbound transaction observation. diff --git a/universalClient/pushsigner/pushsigner_test.go b/universalClient/pushsigner/pushsigner_test.go index 41bf868a..00aa041e 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, observedAt uint64) (string, error) assert.True(t, true) }) } diff --git a/universalClient/pushsigner/vote.go b/universalClient/pushsigner/vote.go index 812d6153..5fbf4554 100644 --- a/universalClient/pushsigner/vote.go +++ b/universalClient/pushsigner/vote.go @@ -86,23 +86,25 @@ 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, observation timestamp) +func voteChainMeta( ctx context.Context, signer *Signer, log zerolog.Logger, granter string, chainID string, price uint64, - blockNumber uint64, + chainHeight uint64, + observedAt uint64, ) (string, error) { - msg := &uexecutortypes.MsgVoteGasPrice{ + msg := &uexecutortypes.MsgVoteChainMeta{ Signer: granter, ObservedChainId: chainID, Price: price, - BlockNumber: blockNumber, + ChainHeight: chainHeight, + ObservedAt: observedAt, } - 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) } From 47b47e2859c022a96294a539b1c174c2d7acc565 Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 17:17:11 +0530 Subject: [PATCH 43/75] chore: fix pushSigner test --- universalClient/pushsigner/vote_test.go | 32 ++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/universalClient/pushsigner/vote_test.go b/universalClient/pushsigner/vote_test.go index cc0e0749..ca96ec0f 100644 --- a/universalClient/pushsigner/vote_test.go +++ b/universalClient/pushsigner/vote_test.go @@ -59,35 +59,40 @@ 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) + observedAt := uint64(1700000001) - msg := &uexecutortypes.MsgVoteGasPrice{ + msg := &uexecutortypes.MsgVoteChainMeta{ Signer: granter, ObservedChainId: chainID, Price: price, - BlockNumber: blockNumber, + ChainHeight: chainHeight, + ObservedAt: observedAt, } 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) + assert.Equal(t, observedAt, msg.ObservedAt) }) - 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, + ObservedAt: 0, } assert.Equal(t, uint64(0), msg.Price) - assert.Equal(t, uint64(0), msg.BlockNumber) + assert.Equal(t, uint64(0), msg.ChainHeight) + assert.Equal(t, uint64(0), msg.ObservedAt) }) } @@ -251,11 +256,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) }) From 3e93e6f8ffd8f4948deac7e50b7fcf7c8b276ac3 Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 17:19:06 +0530 Subject: [PATCH 44/75] refactor: changed gasPriceOracle to chainMetaOracle --- .../{gas_oracle.go => chain_meta_oracle.go} | 39 ++++++++++--------- ...acle_test.go => chain_meta_oracle_test.go} | 32 +++++++-------- universalClient/chains/evm/client.go | 20 +++++----- .../{gas_oracle.go => chain_meta_oracle.go} | 39 ++++++++++--------- ...acle_test.go => chain_meta_oracle_test.go} | 32 +++++++-------- universalClient/chains/svm/client.go | 20 +++++----- 6 files changed, 94 insertions(+), 88 deletions(-) rename universalClient/chains/evm/{gas_oracle.go => chain_meta_oracle.go} (69%) rename universalClient/chains/evm/{gas_oracle_test.go => chain_meta_oracle_test.go} (68%) rename universalClient/chains/svm/{gas_oracle.go => chain_meta_oracle.go} (69%) rename universalClient/chains/svm/{gas_oracle_test.go => chain_meta_oracle_test.go} (67%) diff --git a/universalClient/chains/evm/gas_oracle.go b/universalClient/chains/evm/chain_meta_oracle.go similarity index 69% rename from universalClient/chains/evm/gas_oracle.go rename to universalClient/chains/evm/chain_meta_oracle.go index 5824340c..6ebb2e1c 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,17 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { continue } - // Vote on gas price + // Vote on chain meta (gas price + block height + observation timestamp) priceUint64 := gasPrice.Uint64() - voteTxHash, err := g.pushSigner.VoteGasPrice(ctx, g.chainID, priceUint64, blockNumber) + observedAt := uint64(time.Now().Unix()) + voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, blockNumber, observedAt) if err != nil { g.logger.Error(). Err(err). Uint64("price", priceUint64). Uint64("block", blockNumber). - Msg("failed to vote on gas price") + Uint64("observed_at", observedAt). + Msg("failed to vote on chain meta") continue } @@ -113,13 +115,14 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { Str("vote_tx_hash", voteTxHash). Uint64("price", priceUint64). Uint64("block", blockNumber). - Msg("successfully voted on gas price") + Uint64("observed_at", observedAt). + 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/svm/gas_oracle.go b/universalClient/chains/svm/chain_meta_oracle.go similarity index 69% rename from universalClient/chains/svm/gas_oracle.go rename to universalClient/chains/svm/chain_meta_oracle.go index bb1aaca7..8cea54a6 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,17 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { continue } - // Vote on gas price + // Vote on chain meta (gas price + slot height + observation timestamp) priceUint64 := gasPrice.Uint64() - voteTxHash, err := g.pushSigner.VoteGasPrice(ctx, g.chainID, priceUint64, slotNumber) + observedAt := uint64(time.Now().Unix()) + voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, slotNumber, observedAt) if err != nil { g.logger.Error(). Err(err). Uint64("price", priceUint64). Uint64("slot", slotNumber). - Msg("failed to vote on gas price") + Uint64("observed_at", observedAt). + Msg("failed to vote on chain meta") continue } @@ -113,13 +115,14 @@ func (g *GasOracle) fetchAndVoteGasPrice(ctx context.Context) { Str("vote_tx_hash", voteTxHash). Uint64("price", priceUint64). Uint64("slot", slotNumber). - Msg("successfully voted on gas price") + Uint64("observed_at", observedAt). + 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) } } From 0b7595753cf00e6fba8f254ca04c42616d1b66aa Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 17:26:11 +0530 Subject: [PATCH 45/75] fix: grant error log --- universalClient/pushsigner/grant_verifier.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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{ From d1174b94daa24634bbfd3d005e081f6494270398 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Mon, 16 Mar 2026 17:48:46 +0530 Subject: [PATCH 46/75] feat: improved chain meta reporting algo --- .../uexecutor/vote_chain_meta_test.go | 153 ++++++++++++++++++ x/uexecutor/keeper/chain_meta.go | 23 +-- x/uexecutor/keeper/gas_price.go | 54 +++++++ x/uexecutor/types/constants.go | 5 + 4 files changed, 224 insertions(+), 11 deletions(-) diff --git a/test/integration/uexecutor/vote_chain_meta_test.go b/test/integration/uexecutor/vote_chain_meta_test.go index 81ebae13..4f417ad0 100644 --- a/test/integration/uexecutor/vote_chain_meta_test.go +++ b/test/integration/uexecutor/vote_chain_meta_test.go @@ -149,6 +149,159 @@ func TestVoteChainMetaIntegration(t *testing.T) { }) } +// TestVoteChainMetaStalenessFilter verifies that validators whose observedAt timestamp +// deviates from the median by more than ObservedAtStalenessThresholdSeconds are excluded +// from the price median computation. +// Using wall-clock seconds (observedAt) is chain-agnostic: it works identically for +// Solana (0.4 s/block) and Bitcoin (600 s/block) without per-chain configuration. +func TestVoteChainMetaStalenessFilter(t *testing.T) { + t.Parallel() + chainId := "eip155:11155111" + // threshold in seconds (300s = 5 minutes) + threshold := uexecutortypes.ObservedAtStalenessThresholdSeconds + + t.Run("stale validator excluded when observedAt beyond staleness threshold", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 3) + + // Base timestamp for "current" validators. + baseTs := uint64(1_700_000_000) + // val0: current (ts=baseTs, price=200, height=1000) + // val1: stale (ts=baseTs-threshold-5, price=250, height=900) → must be excluded + // val2: current (ts=baseTs+1, price=300, height=1001) + // + // Median observedAt = baseTs. + // val1 diff = baseTs - (baseTs-threshold-5) = threshold+5 > threshold → excluded. + // + // Without filtering: sorted prices [200, 250, 300] → median=250 (stale val1) + // With filtering: val1 excluded sorted [200, 300] → median=300 (val2) + staleTs := baseTs - threshold - 5 + votes := []struct { + price uint64 + height uint64 + observedAt uint64 + }{ + {200, 1000, baseTs}, + {250, 900, staleTs}, // stale + {300, 1001, baseTs + 1}, + } + + for i, v := range votes { + coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + coreAcc := sdk.AccAddress(coreVal).String() + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) + } + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + + // The chosen validator must NOT be the stale one. + // With filtering the median price is 300 (val2, height=1001). + require.Equal(t, uint64(300), stored.Prices[stored.MedianIndex], + "median price should come from a current validator, not the stale one") + require.Equal(t, uint64(1001), stored.ChainHeights[stored.MedianIndex], + "co-indexed height must be from a current validator") + }) + + t.Run("validator exactly at threshold boundary is included", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 3) + + baseTs := uint64(1_700_000_000) + // val1 is exactly threshold seconds behind the median → diff == threshold → included (<=) + exactBoundaryTs := baseTs - threshold + votes := []struct { + price uint64 + height uint64 + observedAt uint64 + }{ + {200, 1000, baseTs}, + {250, 990, exactBoundaryTs}, // diff == threshold → still included + {300, 1001, baseTs + 1}, + } + + for i, v := range votes { + coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + coreAcc := sdk.AccAddress(coreVal).String() + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) + } + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + + // All three included → sorted prices [200, 250, 300] → median = 250 (val1) + require.Equal(t, uint64(250), stored.Prices[stored.MedianIndex], + "boundary validator should be included in median computation") + }) + + t.Run("all validators current: filtering does not change median", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 4) + + // All timestamps are close together (within threshold). + // Result must match an unfiltered median. + baseTs := uint64(1_700_000_000) + votes := []struct { + price uint64 + height uint64 + observedAt uint64 + }{ + {300, 1000, baseTs}, + {200, 1001, baseTs + 1}, + {400, 1002, baseTs + 2}, + {250, 999, baseTs - 1}, + } + + for i, v := range votes { + coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + coreAcc := sdk.AccAddress(coreVal).String() + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) + } + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + + // All current → sorted [200, 250, 300, 400] → upper-median (index 2) = 300 + require.Equal(t, uint64(300), stored.Prices[stored.MedianIndex]) + // Co-indexed height must belong to the same validator (height=1000) + require.Equal(t, uint64(1000), stored.ChainHeights[stored.MedianIndex]) + }) + + t.Run("multiple stale validators excluded, median from current set", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 5) + + // 3 current validators, 2 stale (observedAt > threshold seconds behind) + baseTs := uint64(1_700_000_000) + staleTs := baseTs - threshold - 10 + votes := []struct { + price uint64 + height uint64 + observedAt uint64 + }{ + {500, 1000, baseTs}, // current + {100, 800, staleTs}, // stale → excluded + {300, 1001, baseTs + 1}, // current + {150, 810, staleTs}, // stale → excluded + {200, 1002, baseTs + 2}, // current + } + + for i, v := range votes { + coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + coreAcc := sdk.AccAddress(coreVal).String() + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) + } + + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) + require.NoError(t, err) + require.True(t, found) + + // After excluding the two stale validators, current set prices: [500, 300, 200] + // Sorted: [200, 300, 500] → upper-median (index 1) = 300 (val with height=1001) + require.Equal(t, uint64(300), stored.Prices[stored.MedianIndex]) + require.Equal(t, uint64(1001), stored.ChainHeights[stored.MedianIndex]) + }) +} + func TestMigrateGasPricesToChainMeta(t *testing.T) { chainId := "eip155:11155111" diff --git a/x/uexecutor/keeper/chain_meta.go b/x/uexecutor/keeper/chain_meta.go index f64d8c2d..b8fb09b4 100644 --- a/x/uexecutor/keeper/chain_meta.go +++ b/x/uexecutor/keeper/chain_meta.go @@ -51,14 +51,11 @@ func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAdd return sdkerrors.Wrap(err, "failed to set initial chain meta entry") } - // EVM call with single price priceBig := math.NewUint(price).BigInt() chainHeightBig := math.NewUint(blockNumber).BigInt() observedAtBig := math.NewUint(observedAt).BigInt() if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, priceBig, chainHeightBig, observedAtBig); evmErr != nil { - // Non-fatal: log the error. The EVM call may fail if the contract hasn't been upgraded yet - // (old bytecode only has setGasPrice). State is still persisted. - sdkCtx.Logger().Error("VoteChainMeta: EVM setChainMeta call failed", "chain", observedChainId, "error", evmErr) + return sdkerrors.Wrap(evmErr, "failed to call EVM setChainMeta") } return nil @@ -83,20 +80,24 @@ func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAdd entry.ObservedAts = append(entry.ObservedAts, observedAt) } - // Recompute median on price - medianIdx := computeMedianIndex(entry.Prices) + // Recompute median: filter out stale validators first, then median on price. + // Staleness is measured by observedAt (Unix seconds) — chain-agnostic. + // See computeMedianIndexFiltered for the two-step algorithm. + medianIdx := computeMedianIndexFiltered(entry.Prices, entry.ObservedAts) entry.MedianIndex = uint64(medianIdx) if err := k.SetChainMeta(ctx, observedChainId, entry); err != nil { return sdkerrors.Wrap(err, "failed to set updated chain meta entry") } + // Use the full observation tuple from the median-price validator. + // chainHeight and observedAt are NOT independent medians — they are the + // co-indexed values from whichever validator submitted the median price. medianPrice := math.NewUint(entry.Prices[medianIdx]).BigInt() - medianChainHeight := math.NewUint(entry.ChainHeights[medianIdx]).BigInt() - medianObservedAt := math.NewUint(entry.ObservedAts[medianIdx]).BigInt() - if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, medianPrice, medianChainHeight, medianObservedAt); evmErr != nil { - // Non-fatal: log. Same forward-compat reason as above. - sdkCtx.Logger().Error("VoteChainMeta: EVM setChainMeta call failed", "chain", observedChainId, "error", evmErr) + coChainHeight := math.NewUint(entry.ChainHeights[medianIdx]).BigInt() + coObservedAt := math.NewUint(entry.ObservedAts[medianIdx]).BigInt() + if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, medianPrice, coChainHeight, coObservedAt); evmErr != nil { + return sdkerrors.Wrap(evmErr, "failed to call EVM setChainMeta") } return nil diff --git a/x/uexecutor/keeper/gas_price.go b/x/uexecutor/keeper/gas_price.go index f4834486..e9657ccd 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,56 @@ 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 } + +// computeMedianIndexFiltered returns the original index (into prices/observedAts) +// of the validator chosen as the representative for VoteChainMeta. The selection +// is a two-step process: +// +// 1. Compute the median of observedAt timestamps across all validators. +// 2. Exclude validators whose observedAt deviates from that median by more than +// ObservedAtStalenessThresholdSeconds (they are considered lagging / stale). +// Using wall-clock seconds is chain-agnostic: it works identically for Solana +// (0.4 s/block) and Bitcoin (600 s/block) without per-chain configuration. +// 3. Among the remaining validators compute the median of prices and return that +// validator's original index. +// +// The returned index is valid for all three parallel slices (prices, chainHeights, +// observedAts), so the caller gets a coherent (price, height, timestamp) tuple +// from a single validator who is both current and representative on price. +// +// If – after filtering – no candidates remain (should not happen with a sensible +// threshold), the function falls back to computeMedianIndex on the full price slice. +func computeMedianIndexFiltered(prices, observedAts []uint64) int { + // Step 1: median observedAt timestamp across all validators + medianObservedAtIdx := computeMedianIndex(observedAts) + medianObservedAt := observedAts[medianObservedAtIdx] + + // Step 2: keep only validators within the staleness threshold (in seconds) + type candidate struct { + originalIdx int + price uint64 + } + var candidates []candidate + for i, ts := range observedAts { + var diff uint64 + if ts >= medianObservedAt { + diff = ts - medianObservedAt + } else { + diff = medianObservedAt - ts + } + if diff <= types.ObservedAtStalenessThresholdSeconds { + candidates = append(candidates, candidate{i, prices[i]}) + } + } + + // Fallback: threshold filtered everyone out (should not happen) + if len(candidates) == 0 { + return computeMedianIndex(prices) + } + + // Step 3: median of prices among current validators + sort.SliceStable(candidates, func(i, j int) bool { + return candidates[i].price < candidates[j].price + }) + return candidates[len(candidates)/2].originalIdx +} diff --git a/x/uexecutor/types/constants.go b/x/uexecutor/types/constants.go index 53285709..7b3e97eb 100644 --- a/x/uexecutor/types/constants.go +++ b/x/uexecutor/types/constants.go @@ -40,6 +40,11 @@ const ( // Default number of blocks after which ballot expires DefaultExpiryAfterBlocks = 10000 + + // ObservedAtStalenessThresholdSeconds is the maximum number of seconds a + // validator's observedAt timestamp may deviate from the median observedAt before + // its price vote is excluded from the median price computation in VoteChainMeta. + ObservedAtStalenessThresholdSeconds uint64 = 300 ) var UniversalTxOutboundEventSig = crypto.Keccak256Hash([]byte( From ff299b51752cb4a78f69909e996ca80fce026e01 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Mon, 16 Mar 2026 18:07:12 +0530 Subject: [PATCH 47/75] feat: improved chain meta reporting algo --- .../uexecutor/vote_chain_meta_test.go | 76 +++++++++++++++++++ x/uexecutor/keeper/chain_meta.go | 37 ++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/test/integration/uexecutor/vote_chain_meta_test.go b/test/integration/uexecutor/vote_chain_meta_test.go index 4f417ad0..8c4b1d45 100644 --- a/test/integration/uexecutor/vote_chain_meta_test.go +++ b/test/integration/uexecutor/vote_chain_meta_test.go @@ -415,3 +415,79 @@ func TestVoteChainMetaContractState(t *testing.T) { require.Equal(t, new(big.Int).SetUint64(observedAt), got) }) } + +// TestVoteChainMetaAbsoluteStaleness verifies that when all validators' observedAt timestamps +// are older than ObservedAtStalenessThresholdSeconds relative to the current block time, +// the EVM contract is NOT updated (it retains its previous value). +// +// These tests call VoteChainMeta directly on the keeper (bypassing authz) so that +// block time can be freely manipulated without hitting authz grant expiry. +func TestVoteChainMetaAbsoluteStaleness(t *testing.T) { + chainId := "eip155:11155111" + threshold := uexecutortypes.ObservedAtStalenessThresholdSeconds // 300 + + universalCoreAddr := utils.GetDefaultAddresses().HandlerAddr + + readGasPrice := func(t *testing.T, testApp *app.ChainApp, ctx sdk.Context) *big.Int { + t.Helper() + 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) + return new(big.Int).SetBytes(res.Ret) + } + + t.Run("stale single vote does not update contract", func(t *testing.T) { + testApp, ctx, _, vals := setupVoteChainMetaTest(t, 1) + + staleObservedAt := uint64(1_700_000_000) + // Block time is far past the staleness window + staleCtx := ctx.WithBlockTime(time.Unix(int64(staleObservedAt+threshold+60), 0)) + + valAddr, err := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + require.NoError(t, err) + + require.NoError(t, testApp.UexecutorKeeper.VoteChainMeta(staleCtx, valAddr, chainId, + 100_000_000_000, 12345, staleObservedAt)) + + // Vote was stored in state + stored, found, err := testApp.UexecutorKeeper.GetChainMeta(staleCtx, chainId) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, uint64(100_000_000_000), stored.Prices[0]) + + // Contract must NOT have been updated — should still be 0 + require.Zero(t, readGasPrice(t, testApp, staleCtx).Sign(), + "contract must not be updated when all validators are stale") + }) + + t.Run("all validators stale does not update contract", func(t *testing.T) { + testApp, ctx, _, vals := setupVoteChainMetaTest(t, 3) + + freshObservedAt := uint64(1_700_000_000) + + // First vote with fresh block time → contract gets updated + freshCtx := ctx.WithBlockTime(time.Unix(int64(freshObservedAt), 0)) + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + require.NoError(t, err) + require.NoError(t, testApp.UexecutorKeeper.VoteChainMeta(freshCtx, valAddr, chainId, + 200_000_000_000, uint64(12345+i), freshObservedAt+uint64(i))) + } + require.Equal(t, new(big.Int).SetUint64(200_000_000_000), readGasPrice(t, testApp, freshCtx)) + + // Re-vote with same old timestamps but block time past staleness window + futureCtx := ctx.WithBlockTime(time.Unix(int64(freshObservedAt+threshold+60), 0)) + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(vals[i].OperatorAddress) + require.NoError(t, err) + require.NoError(t, testApp.UexecutorKeeper.VoteChainMeta(futureCtx, valAddr, chainId, + 999_000_000_000, uint64(99999+i), freshObservedAt+uint64(i))) + } + + // Contract must retain the old fresh value — stale votes must not overwrite it + require.Equal(t, new(big.Int).SetUint64(200_000_000_000), readGasPrice(t, testApp, futureCtx), + "contract must retain last good value when all validators report stale data") + }) +} diff --git a/x/uexecutor/keeper/chain_meta.go b/x/uexecutor/keeper/chain_meta.go index b8fb09b4..f9fed767 100644 --- a/x/uexecutor/keeper/chain_meta.go +++ b/x/uexecutor/keeper/chain_meta.go @@ -26,8 +26,26 @@ func (k Keeper) SetChainMeta(ctx context.Context, chainID string, chainMeta type return k.ChainMetas.Set(ctx, chainID, chainMeta) } +// isObservedAtStale returns true if observedAt (Unix seconds) is older than +// ObservedAtStalenessThresholdSeconds relative to the current block time. +// When true the data should not be pushed to the UniversalCore contract. +// Returns false when block time is zero or negative (not yet configured). +func isObservedAtStale(sdkCtx sdk.Context, observedAt uint64) bool { + blockTimeUnix := sdkCtx.BlockTime().Unix() + if blockTimeUnix <= 0 { + // Block time not configured (e.g. genesis or test setup) — skip staleness check. + return false + } + blockTimeSec := uint64(blockTimeUnix) + return blockTimeSec > observedAt && + blockTimeSec-observedAt > types.ObservedAtStalenessThresholdSeconds +} + // VoteChainMeta processes a universal validator's vote on chain metadata (gas price + chain height + observed timestamp). // It accumulates votes, computes the median price, and calls setChainMeta on the UniversalCore contract. +// If the median observedAt is older than ObservedAtStalenessThresholdSeconds relative to the current +// block time, the EVM contract is NOT updated — all validators are considered stale and retaining +// the last good contract state is preferred over pushing stale data. func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAddress, observedChainId string, price, blockNumber, observedAt uint64) error { sdkCtx := sdk.UnwrapSDKContext(ctx) @@ -51,6 +69,12 @@ func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAdd return sdkerrors.Wrap(err, "failed to set initial chain meta entry") } + if isObservedAtStale(sdkCtx, observedAt) { + sdkCtx.Logger().Info("VoteChainMeta: skipping EVM update — single vote is stale", + "chain", observedChainId, "observedAt", observedAt) + return nil + } + priceBig := math.NewUint(price).BigInt() chainHeightBig := math.NewUint(blockNumber).BigInt() observedAtBig := math.NewUint(observedAt).BigInt() @@ -90,12 +114,23 @@ func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAdd return sdkerrors.Wrap(err, "failed to set updated chain meta entry") } + // If the median observedAt is stale relative to the current block time, all + // validators are considered offline/lagging. Skip the EVM update so the + // contract retains its last known good value rather than being overwritten + // with stale data. + medianObservedAt := entry.ObservedAts[medianIdx] + if isObservedAtStale(sdkCtx, medianObservedAt) { + sdkCtx.Logger().Info("VoteChainMeta: skipping EVM update — all validators stale", + "chain", observedChainId, "medianObservedAt", medianObservedAt) + return nil + } + // Use the full observation tuple from the median-price validator. // chainHeight and observedAt are NOT independent medians — they are the // co-indexed values from whichever validator submitted the median price. medianPrice := math.NewUint(entry.Prices[medianIdx]).BigInt() coChainHeight := math.NewUint(entry.ChainHeights[medianIdx]).BigInt() - coObservedAt := math.NewUint(entry.ObservedAts[medianIdx]).BigInt() + coObservedAt := math.NewUint(medianObservedAt).BigInt() if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, medianPrice, coChainHeight, coObservedAt); evmErr != nil { return sdkerrors.Wrap(evmErr, "failed to call EVM setChainMeta") } From e43a67b4b27eed66f13cdb137ee7bda7f61df1a1 Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 19:17:59 +0530 Subject: [PATCH 48/75] fix: gasPrice & limit changes --- universalClient/chains/common/types.go | 8 ++- universalClient/chains/evm/tx_builder.go | 42 ++++++++++------ universalClient/chains/evm/tx_builder_test.go | 43 ++++++++-------- universalClient/chains/push/event_parser.go | 6 +++ universalClient/chains/svm/tx_builder.go | 45 +++++++---------- universalClient/chains/svm/tx_builder_test.go | 50 +++++++------------ 6 files changed, 95 insertions(+), 99 deletions(-) diff --git a/universalClient/chains/common/types.go b/universalClient/chains/common/types.go index 53735c53..2d4dced8 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. diff --git a/universalClient/chains/evm/tx_builder.go b/universalClient/chains/evm/tx_builder.go index 15a985b1..9a2566f3 100644 --- a/universalClient/chains/evm/tx_builder.go +++ b/universalClient/chains/evm/tx_builder.go @@ -18,8 +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; } @@ -90,7 +88,6 @@ func NewTxBuilder( func (tb *TxBuilder) GetOutboundSigningRequest( ctx context.Context, data *uetypes.OutboundCreatedEvent, - gasPrice *big.Int, nonce uint64, ) (*common.UnSignedOutboundTxReq, error) { if data == nil { @@ -102,11 +99,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) @@ -148,7 +155,6 @@ func (tb *TxBuilder) GetOutboundSigningRequest( return &common.UnSignedOutboundTxReq{ SigningHash: txHash, Nonce: nonce, - GasPrice: gasPrice, }, nil } @@ -206,14 +212,22 @@ func (tb *TxBuilder) BroadcastOutboundSigningRequest( return "", fmt.Errorf("failed to resolve tx params: %w", err) } - gasLimitForTx := parseGasLimit(data.GasLimit) + gasLimitForTx, err := parseGasLimit(data.GasLimit) + if err != nil { + return "", fmt.Errorf("invalid gas limit: %w", err) + } + + gasPrice := new(big.Int) + if data.GasPrice != "" { + gasPrice.SetString(data.GasPrice, 10) + } tx := types.NewTransaction( req.Nonce, toAddress, txValue, gasLimitForTx.Uint64(), - req.GasPrice, + gasPrice, txData, ) @@ -469,17 +483,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, diff --git a/universalClient/chains/evm/tx_builder_test.go b/universalClient/chains/evm/tx_builder_test.go index b4f8d30b..471e5e2c 100644 --- a/universalClient/chains/evm/tx_builder_test.go +++ b/universalClient/chains/evm/tx_builder_test.go @@ -36,9 +36,6 @@ func newTestTxBuilder(t *testing.T) *TxBuilder { } } -func TestDefaultGasLimit(t *testing.T) { - assert.Equal(t, int64(500000), int64(DefaultGasLimit)) -} func TestRevertInstructionsStruct(t *testing.T) { recipient := ethcommon.HexToAddress("0x1234567890123456789012345678901234567890") @@ -519,24 +516,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 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/tx_builder.go b/universalClient/chains/svm/tx_builder.go index db45c651..3c6a948b 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) @@ -381,12 +374,9 @@ func (tb *TxBuilder) GetOutboundSigningRequest( 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 } @@ -567,8 +557,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 { @@ -747,23 +740,19 @@ 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 if needsRecipientATA { diff --git a/universalClient/chains/svm/tx_builder_test.go b/universalClient/chains/svm/tx_builder_test.go index bfc62894..a86701fb 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" @@ -231,9 +230,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" @@ -1143,32 +1139,24 @@ func TestGatewayAccountMetaStruct(t *testing.T) { // ============================================================ 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) - }) - } + t.Run("empty returns error", func(t *testing.T) { + _, err := parseUint32("") + assert.Error(t, err) + }) + t.Run("zero returns error", func(t *testing.T) { + _, err := parseUint32("0") + // parseUint32 parses successfully but returns 0 + assert.NoError(t, err) + }) + t.Run("valid", func(t *testing.T) { + result, err := parseUint32("300000") + assert.NoError(t, err) + assert.Equal(t, uint32(300000), result) + }) + t.Run("invalid number returns error", func(t *testing.T) { + _, err := parseUint32("abc") + assert.Error(t, err) + }) } func parseUint32(s string) (uint32, error) { @@ -1461,7 +1449,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) } From 866ef89f719ba4a926d02e3c978d8c4cce81318d Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 19:19:26 +0530 Subject: [PATCH 49/75] fix: sessionManager & coordinator - removing gasPrice passing --- .../tss/coordinator/coordinator.go | 10 +--- .../tss/sessionmanager/sessionmanager.go | 53 +------------------ .../tss/sessionmanager/sessionmanager_test.go | 3 -- 3 files changed, 4 insertions(+), 62 deletions(-) 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/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) { From 772b3d73413c9d60d03d01d920965d93f37b89ce Mon Sep 17 00:00:00 2001 From: aman035 Date: Mon, 16 Mar 2026 19:20:07 +0530 Subject: [PATCH 50/75] fix: tc & broadcaster --- universalClient/tss/txbroadcaster/broadcaster.go | 12 +----------- .../tss/txbroadcaster/broadcaster_test.go | 6 ++---- universalClient/tss/txresolver/resolver_test.go | 5 ++--- 3 files changed, 5 insertions(+), 18 deletions(-) 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..74aa3c50 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) } @@ -120,7 +119,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/resolver_test.go b/universalClient/tss/txresolver/resolver_test.go index a635e3ee..edf94863 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) } From 66c0dab3caf94ddb1a0e7f89b045be8492456f5f Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Mon, 16 Mar 2026 19:55:35 +0530 Subject: [PATCH 51/75] feat: added logic to refundGasFee in failure outbound txs as well --- .../uexecutor/gas_fee_refund_test.go | 58 +++++----- .../uexecutor/vote_outbound_test.go | 4 +- x/uexecutor/keeper/outbound.go | 104 +++++++++--------- x/uexecutor/types/msg_vote_outbound.go | 17 +-- 4 files changed, 94 insertions(+), 89 deletions(-) diff --git a/test/integration/uexecutor/gas_fee_refund_test.go b/test/integration/uexecutor/gas_fee_refund_test.go index e1480c31..18aa82db 100644 --- a/test/integration/uexecutor/gas_fee_refund_test.go +++ b/test/integration/uexecutor/gas_fee_refund_test.go @@ -13,28 +13,28 @@ import ( func TestGasFeeRefund(t *testing.T) { - t.Run("success vote with empty gasFeeUsed is rejected", func(t *testing.T) { - app, ctx, vals, utxId, outbound, coreVals := - setupOutboundVotingTest(t, 4) + 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() - - err = utils.ExecVoteOutbound( - t, - ctx, - app, - vals[0], - coreAcc, - utxId, - outbound, - true, - "", - "", // gas_fee_used required when success=true → must be rejected - ) - require.Error(t, err) - require.Contains(t, err.Error(), "gas_fee_used required when success=true") + 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) { @@ -196,11 +196,12 @@ func TestGasFeeRefund(t *testing.T) { require.Equal(t, uexecutortypes.Status_OBSERVED, ob.OutboundStatus) }) - t.Run("failed outbound still performs revert not refund", func(t *testing.T) { + t.Run("failed outbound performs both revert and gas refund", func(t *testing.T) { app, ctx, vals, utxId, outbound, coreVals := setupOutboundVotingTest(t, 4) - // Vote as FAILED with gasFeeUsed set — refund should NOT run for failed outbounds + // 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) @@ -216,7 +217,7 @@ func TestGasFeeRefund(t *testing.T) { outbound, false, "execution failed", - "50", // gasFeeUsed provided but shouldn't trigger refund on failure + "50", // gasFeeUsed=50 < gasFee=111 → 61 excess ) require.NoError(t, err) } @@ -227,12 +228,13 @@ func TestGasFeeRefund(t *testing.T) { ob := utx.OutboundTx[0] require.Equal(t, uexecutortypes.Status_REVERTED, ob.OutboundStatus) - // Revert was executed (funds minted back) + // Revert: bridged funds minted back require.NotNil(t, ob.PcRevertExecution) require.Equal(t, "SUCCESS", ob.PcRevertExecution.Status) - // Gas refund must NOT run for failed outbounds - require.Nil(t, ob.PcRefundExecution, - "gas refund must not run when outbound failed") + // 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/vote_outbound_test.go b/test/integration/uexecutor/vote_outbound_test.go index 40e2f8d3..9c5e31cc 100644 --- a/test/integration/uexecutor/vote_outbound_test.go +++ b/test/integration/uexecutor/vote_outbound_test.go @@ -240,7 +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) } @@ -281,7 +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) } diff --git a/x/uexecutor/keeper/outbound.go b/x/uexecutor/keeper/outbound.go index 9839c21f..892f02a8 100644 --- a/x/uexecutor/keeper/outbound.go +++ b/x/uexecutor/keeper/outbound.go @@ -51,79 +51,86 @@ func (k Keeper) FinalizeOutbound(ctx context.Context, utxId string, outbound typ sdkCtx := sdk.UnwrapSDKContext(ctx) if !obs.Success { - return k.handleFailedOutbound(sdkCtx, utxId, outbound) + return k.handleFailedOutbound(sdkCtx, utxId, outbound, obs) } return k.handleSuccessfulOutbound(sdkCtx, utxId, outbound, obs) } -// handleFailedOutbound mints back the bridged tokens to the revert recipient. -func (k Keeper) handleFailedOutbound(ctx sdk.Context, utxId string, outbound types.OutboundTx) error { - // 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 { - return nil - } +// 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 + } - // Decide refund 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) - // Mint tokens back - amount := new(big.Int) - amount, ok := amount.SetString(outbound.Amount, 10) - if !ok { - return fmt.Errorf("invalid amount: %s", outbound.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(ctx, common.HexToAddress(outbound.Prc20AssetAddr), common.HexToAddress(recipient), amount) - // Update outbound status outbound.OutboundStatus = types.Status_REVERTED - pcTx := types.PCTx{ - TxHash: "", - Sender: outbound.Sender, - GasUsed: 0, - 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 + // 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 { - // Only attempt refund if gas_fee_used is populated and gas token is known + 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 k.UpdateOutbound(ctx, utxId, outbound) + return } gasFee := new(big.Int) if _, ok := gasFee.SetString(outbound.GasFee, 10); !ok { - return k.UpdateOutbound(ctx, utxId, outbound) + return } gasFeeUsed := new(big.Int) if _, ok := gasFeeUsed.SetString(obs.GasFeeUsed, 10); !ok { - return k.UpdateOutbound(ctx, utxId, outbound) + return } - // No refund needed + // No excess gas to refund if gasFee.Cmp(gasFeeUsed) <= 0 { - return k.UpdateOutbound(ctx, utxId, outbound) + return } refundAmount := new(big.Int).Sub(gasFee, gasFeeUsed) @@ -144,7 +151,6 @@ func (k Keeper) handleSuccessfulOutbound(ctx sdk.Context, utxId string, outbound // Step 1: try refund with swap (gasToken → PC native) fee, swapErr := k.GetDefaultFeeTierForToken(ctx, gasToken) var swapFallbackReason string - var receipt interface{ GetHash() string } if swapErr == nil { quote, quoteErr := k.getSwapQuoteForRefund(ctx, gasToken, fee, refundAmount) @@ -158,7 +164,7 @@ func (k Keeper) handleSuccessfulOutbound(ctx sdk.Context, utxId string, outbound refundPcTx.GasUsed = resp.GasUsed refundPcTx.Status = "SUCCESS" outbound.PcRefundExecution = refundPcTx - return k.UpdateOutbound(ctx, utxId, outbound) + return } swapFallbackReason = fmt.Sprintf("swap refund failed: %s", err.Error()) } else { @@ -168,10 +174,8 @@ func (k Keeper) handleSuccessfulOutbound(ctx sdk.Context, utxId string, outbound swapFallbackReason = fmt.Sprintf("fee tier fetch failed: %s", swapErr.Error()) } - _ = receipt - // Step 2: fallback — refund without swap (deposit PRC20 directly to recipient) - ctx.Logger().Error("FinalizeOutbound: swap refund failed, falling back to no-swap", + ctx.Logger().Error("applyGasRefund: swap refund failed, falling back to no-swap", "outbound_id", outbound.Id, "reason", swapFallbackReason, ) @@ -188,8 +192,6 @@ func (k Keeper) handleSuccessfulOutbound(ctx sdk.Context, utxId string, outbound outbound.PcRefundExecution = refundPcTx outbound.RefundSwapError = swapFallbackReason - - return k.UpdateOutbound(ctx, utxId, outbound) } // getSwapQuoteForRefund fetches a Uniswap quote for the gas token refund swap. diff --git a/x/uexecutor/types/msg_vote_outbound.go b/x/uexecutor/types/msg_vote_outbound.go index 9b9ce866..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 AND gas_fee_used + // 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,14 +85,8 @@ func (msg *MsgVoteOutbound) ValidateBasic() error { return errors.Wrap(sdkerrors.ErrInvalidRequest, "observed_tx.block_height must be > 0 when success=true") } - if strings.TrimSpace(obs.GasFeeUsed) == "" { - return errors.Wrap(sdkerrors.ErrInvalidRequest, - "observed_tx.gas_fee_used required 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, From f03207dbe547c64f6e6267a7bc7d5d306b2d9c4f Mon Sep 17 00:00:00 2001 From: aman035 Date: Tue, 17 Mar 2026 10:43:37 +0530 Subject: [PATCH 52/75] fix: outbound failure voting --- universalClient/chains/common/chain_store.go | 20 ++++++++++++++ universalClient/chains/common/types.go | 11 ++++++-- universalClient/chains/evm/rpc_client.go | 12 +++++++++ universalClient/chains/evm/tx_builder.go | 25 +++++++++++++++++ universalClient/chains/svm/tx_builder.go | 7 +++++ universalClient/tss/expirysweeper/sweeper.go | 7 ++--- .../tss/txbroadcaster/broadcaster_test.go | 5 ++++ universalClient/tss/txresolver/evm.go | 27 +++++++++++++------ universalClient/tss/txresolver/resolver.go | 8 ++++-- .../tss/txresolver/resolver_test.go | 7 ++++- universalClient/tss/txresolver/svm.go | 4 +-- 11 files changed, 115 insertions(+), 18 deletions(-) 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/types.go b/universalClient/chains/common/types.go index 2d4dced8..bf7c231c 100644 --- a/universalClient/chains/common/types.go +++ b/universalClient/chains/common/types.go @@ -54,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 @@ -76,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/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 9a2566f3..7c7e5716 100644 --- a/universalClient/chains/evm/tx_builder.go +++ b/universalClient/chains/evm/tx_builder.go @@ -501,3 +501,28 @@ func parseGasLimit(gasLimitStr string) (*big.Int, error) { 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/svm/tx_builder.go b/universalClient/chains/svm/tx_builder.go index 3c6a948b..92b5f6af 100644 --- a/universalClient/chains/svm/tx_builder.go +++ b/universalClient/chains/svm/tx_builder.go @@ -415,6 +415,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 // 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/txbroadcaster/broadcaster_test.go b/universalClient/tss/txbroadcaster/broadcaster_test.go index 74aa3c50..860a16f5 100644 --- a/universalClient/tss/txbroadcaster/broadcaster_test.go +++ b/universalClient/tss/txbroadcaster/broadcaster_test.go @@ -59,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 } 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 edf94863..af7214e4 100644 --- a/universalClient/tss/txresolver/resolver_test.go +++ b/universalClient/tss/txresolver/resolver_test.go @@ -58,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 } @@ -417,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") } From 87f949e5433ec867b0732243b28c624523195669 Mon Sep 17 00:00:00 2001 From: aman035 Date: Tue, 17 Mar 2026 10:49:57 +0530 Subject: [PATCH 53/75] fix: success event parsing --- .../chains/common/event_processor.go | 48 +++++------ .../chains/common/event_processor_test.go | 79 ++++++++++++------- universalClient/chains/evm/event_confirmer.go | 46 ++++++++++- universalClient/chains/svm/event_confirmer.go | 31 +++++++- 4 files changed, 148 insertions(+), 56 deletions(-) diff --git a/universalClient/chains/common/event_processor.go b/universalClient/chains/common/event_processor.go index b0ee937a..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 @@ -338,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, ":") @@ -388,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/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/svm/event_confirmer.go b/universalClient/chains/svm/event_confirmer.go index fdfa8b0b..c5e6b529 100644 --- a/universalClient/chains/svm/event_confirmer.go +++ b/universalClient/chains/svm/event_confirmer.go @@ -2,6 +2,7 @@ package svm import ( "context" + "encoding/json" "fmt" "strings" "sync" @@ -169,8 +170,34 @@ func (ec *EventConfirmer) processPendingEvents(ctx context.Context) error { confirmations := latestSlot - txSlot + 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 from tx metadata + if event.Type == chaincommon.EventTypeOutbound { + 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 = "0" + + 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). From 9acdb721141126a134e802e64e8cc04924d28faf Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 11:10:43 +0530 Subject: [PATCH 54/75] feat: removed UniversalTxStatus from UniversalTx proto --- proto/uexecutor/v1/types.proto | 1 - 1 file changed, 1 deletion(-) diff --git a/proto/uexecutor/v1/types.proto b/proto/uexecutor/v1/types.proto index a68d8dad..8237a69c 100644 --- a/proto/uexecutor/v1/types.proto +++ b/proto/uexecutor/v1/types.proto @@ -184,7 +184,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 From 5489799451be54d999ade2e1332a2663815b04d8 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 11:11:05 +0530 Subject: [PATCH 55/75] refactor: added generated protobuf --- api/uexecutor/v1/types.pulsar.go | 340 +++++++++++++------------------ 1 file changed, 139 insertions(+), 201 deletions(-) diff --git a/api/uexecutor/v1/types.pulsar.go b/api/uexecutor/v1/types.pulsar.go index 228be4f2..d9725fe6 100644 --- a/api/uexecutor/v1/types.pulsar.go +++ b/api/uexecutor/v1/types.pulsar.go @@ -7618,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() { @@ -7633,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) @@ -7725,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. @@ -7754,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")) @@ -7780,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")) @@ -7816,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")) @@ -7851,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")) @@ -7892,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")) @@ -7918,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")) @@ -8009,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) } @@ -8041,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]) @@ -8284,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:]) @@ -11783,11 +11735,10 @@ type UniversalTx struct { 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() { @@ -11838,13 +11789,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 @@ -12256,7 +12200,7 @@ var file_uexecutor_v1_types_proto_rawDesc = []byte{ 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, 0xa8, 0x02, 0x0a, 0x0b, 0x55, 0x6e, + 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, @@ -12268,129 +12212,124 @@ var file_uexecutor_v1_types_proto_rawDesc = []byte{ 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, 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, + 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, 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, 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, } var ( @@ -12443,18 +12382,17 @@ var file_uexecutor_v1_types_proto_depIdxs = []int32{ 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 - 1, // 14: uexecutor.v1.UniversalTx.universal_status:type_name -> uexecutor.v1.UniversalTxStatus - 4, // 15: uexecutor.v1.InboundLegacy.tx_type:type_name -> uexecutor.v1.InboundTxTypeLegacy - 6, // 16: uexecutor.v1.InboundLegacy.universal_payload:type_name -> uexecutor.v1.UniversalPayload - 16, // 17: uexecutor.v1.UniversalTxLegacy.inbound_tx:type_name -> uexecutor.v1.InboundLegacy - 11, // 18: uexecutor.v1.UniversalTxLegacy.pc_tx:type_name -> uexecutor.v1.PCTx - 17, // 19: uexecutor.v1.UniversalTxLegacy.outbound_tx:type_name -> uexecutor.v1.OutboundTxLegacy - 1, // 20: uexecutor.v1.UniversalTxLegacy.universal_status:type_name -> uexecutor.v1.UniversalTxStatus - 21, // [21:21] is the sub-list for method output_type - 21, // [21:21] is the sub-list for method input_type - 21, // [21:21] is the sub-list for extension type_name - 21, // [21:21] is the sub-list for extension extendee - 0, // [0:21] is the sub-list for field type_name + 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 + 11, // 17: uexecutor.v1.UniversalTxLegacy.pc_tx:type_name -> uexecutor.v1.PCTx + 17, // 18: uexecutor.v1.UniversalTxLegacy.outbound_tx:type_name -> uexecutor.v1.OutboundTxLegacy + 1, // 19: uexecutor.v1.UniversalTxLegacy.universal_status:type_name -> uexecutor.v1.UniversalTxStatus + 20, // [20:20] is the sub-list for method output_type + 20, // [20:20] is the sub-list for method input_type + 20, // [20:20] is the sub-list for extension type_name + 20, // [20:20] is the sub-list for extension extendee + 0, // [0:20] is the sub-list for field type_name } func init() { file_uexecutor_v1_types_proto_init() } From e1cd7f8c38d4337f713f4b22c6e79b1b24f31715 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 11:11:54 +0530 Subject: [PATCH 56/75] feat: implemented UniversalTxStatus removal changes in keeper methods --- x/uexecutor/keeper/create_outbound.go | 1 - x/uexecutor/keeper/execute_inbound_funds.go | 4 +- .../execute_inbound_funds_and_payload.go | 8 ++-- x/uexecutor/keeper/execute_inbound_gas.go | 4 +- .../keeper/execute_inbound_gas_and_payload.go | 8 ++-- x/uexecutor/keeper/msg_vote_inbound.go | 1 - x/uexecutor/keeper/query_server.go | 46 ++++++++++++++++++- x/uexecutor/keeper/universal_tx.go | 26 ++--------- x/uexecutor/migrations/v4/migrate.go | 9 ++-- x/uexecutor/types/universal_tx.go | 5 -- 10 files changed, 64 insertions(+), 48 deletions(-) diff --git a/x/uexecutor/keeper/create_outbound.go b/x/uexecutor/keeper/create_outbound.go index 5c59967f..6f769013 100644 --- a/x/uexecutor/keeper/create_outbound.go +++ b/x/uexecutor/keeper/create_outbound.go @@ -115,7 +115,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 { diff --git a/x/uexecutor/keeper/execute_inbound_funds.go b/x/uexecutor/keeper/execute_inbound_funds.go index e99d5935..09e67583 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) diff --git a/x/uexecutor/keeper/execute_inbound_funds_and_payload.go b/x/uexecutor/keeper/execute_inbound_funds_and_payload.go index c485e155..ff6b3d15 100644 --- a/x/uexecutor/keeper/execute_inbound_funds_and_payload.go +++ b/x/uexecutor/keeper/execute_inbound_funds_and_payload.go @@ -138,7 +138,7 @@ 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 }) @@ -190,7 +190,7 @@ 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 @@ -221,9 +221,9 @@ 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 }) diff --git a/x/uexecutor/keeper/execute_inbound_gas.go b/x/uexecutor/keeper/execute_inbound_gas.go index 3d28d083..b479cf64 100644 --- a/x/uexecutor/keeper/execute_inbound_gas.go +++ b/x/uexecutor/keeper/execute_inbound_gas.go @@ -156,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 }) diff --git a/x/uexecutor/keeper/execute_inbound_gas_and_payload.go b/x/uexecutor/keeper/execute_inbound_gas_and_payload.go index 9a9f4420..ab09f80e 100644 --- a/x/uexecutor/keeper/execute_inbound_gas_and_payload.go +++ b/x/uexecutor/keeper/execute_inbound_gas_and_payload.go @@ -160,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 }) @@ -211,7 +211,7 @@ 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 @@ -247,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/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/query_server.go b/x/uexecutor/keeper/query_server.go index d9e50aa9..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), } } 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/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 } From d1dfbc5810cd29fd6de3ed514dffd32d7e86f899 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 11:11:58 +0530 Subject: [PATCH 57/75] refactor: added generated protobuf --- x/uexecutor/types/types.pb.go | 267 +++++++++++++++------------------- 1 file changed, 114 insertions(+), 153 deletions(-) diff --git a/x/uexecutor/types/types.pb.go b/x/uexecutor/types/types.pb.go index 462d4216..edce0ef2 100644 --- a/x/uexecutor/types/types.pb.go +++ b/x/uexecutor/types/types.pb.go @@ -1059,11 +1059,10 @@ func (m *OutboundTx) GetGasToken() string { } 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{} } @@ -1126,13 +1125,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"` @@ -1418,121 +1410,120 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/types.proto", fileDescriptor_fab6d3ca71d1e2a5) } var fileDescriptor_fab6d3ca71d1e2a5 = []byte{ - // 1811 bytes of a gzipped FileDescriptorProto + // 1808 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, - 0xe8, 0xa9, 0xb7, 0xa2, 0x87, 0x1e, 0x73, 0xcc, 0xb1, 0x68, 0x2f, 0x3d, 0xf4, 0x43, 0xec, 0x71, - 0x8b, 0x5e, 0x0a, 0xf4, 0x52, 0x24, 0x87, 0x16, 0xe8, 0xad, 0x9f, 0xa0, 0x78, 0x7f, 0x28, 0x92, - 0xb2, 0x94, 0x6c, 0xb1, 0x87, 0x02, 0xbd, 0x58, 0x9c, 0x79, 0xf3, 0xe6, 0xfd, 0x66, 0xe6, 0x37, - 0xf3, 0x68, 0x82, 0x32, 0x23, 0x21, 0x31, 0x66, 0x81, 0xeb, 0x1d, 0xce, 0x3f, 0x39, 0x0c, 0x6e, - 0xa6, 0xc4, 0x3f, 0x98, 0x7a, 0x6e, 0xe0, 0xa2, 0xcd, 0xc5, 0xca, 0xc1, 0xfc, 0x93, 0x87, 0x0d, - 0xcb, 0xb5, 0x5c, 0xb6, 0x70, 0x48, 0x9f, 0xb8, 0xcd, 0xc3, 0x1a, 0x9e, 0xd8, 0x8e, 0x7b, 0xc8, - 0xfe, 0x72, 0x55, 0xeb, 0x04, 0x0a, 0x03, 0xec, 0xe1, 0x89, 0x8f, 0xb6, 0x01, 0x7c, 0x77, 0x42, - 0xf4, 0x39, 0xbe, 0x9e, 0x11, 0x25, 0xb3, 0x2b, 0xed, 0x95, 0xb4, 0x32, 0xd5, 0x5c, 0x50, 0x45, - 0x7b, 0xfb, 0xd5, 0xeb, 0x9d, 0x8d, 0x7f, 0xbe, 0xde, 0x91, 0x7e, 0xfd, 0x8f, 0x3f, 0xee, 0xcb, - 0x31, 0x8c, 0x29, 0xdb, 0xdd, 0xfa, 0x5b, 0x06, 0xe4, 0xb1, 0x63, 0xcf, 0x89, 0xe7, 0xe3, 0xeb, - 0x01, 0xbe, 0xb9, 0x76, 0xb1, 0x89, 0xb6, 0x20, 0x13, 0xb8, 0x8a, 0xb4, 0x2b, 0xed, 0x95, 0xb5, - 0x4c, 0xe0, 0xa2, 0x06, 0xe4, 0x63, 0xef, 0x65, 0x8d, 0x0b, 0x08, 0x41, 0xce, 0xc4, 0x01, 0x56, - 0xb2, 0x4c, 0xc9, 0x9e, 0xd1, 0x23, 0x28, 0x5b, 0xd8, 0xd7, 0xaf, 0xed, 0x89, 0x1d, 0x28, 0x39, - 0xb6, 0x50, 0xb2, 0xb0, 0x7f, 0x46, 0x65, 0xf4, 0x31, 0x54, 0x27, 0x38, 0xd4, 0x5f, 0x10, 0xa2, - 0x4f, 0x89, 0xa7, 0x5b, 0xd8, 0x57, 0xf2, 0xcc, 0x64, 0x73, 0x82, 0xc3, 0x13, 0x42, 0x06, 0xc4, - 0x3b, 0xc5, 0x3e, 0xfa, 0x14, 0x14, 0x6a, 0x36, 0xf5, 0x6c, 0xd7, 0xb3, 0x83, 0x9b, 0x94, 0x7d, - 0x81, 0xd9, 0x37, 0x26, 0x38, 0x1c, 0x88, 0xe5, 0x78, 0x5f, 0x03, 0xf2, 0x8e, 0xeb, 0x18, 0x44, - 0x29, 0x72, 0x94, 0x4c, 0x40, 0x0f, 0xa1, 0x64, 0x12, 0x6c, 0x5e, 0xdb, 0x0e, 0x51, 0x4a, 0x1c, - 0x50, 0x24, 0xa3, 0x1f, 0x42, 0x61, 0xae, 0xd3, 0x62, 0x28, 0xe5, 0x5d, 0x69, 0x6f, 0xeb, 0x59, - 0xf3, 0x20, 0x59, 0x8c, 0x83, 0x0b, 0xe2, 0xd9, 0x2f, 0x6c, 0x03, 0x07, 0xb6, 0xeb, 0x8c, 0x6e, - 0xa6, 0x44, 0xcb, 0xcf, 0xe9, 0x4f, 0x7b, 0x2f, 0x99, 0xd2, 0x47, 0x71, 0x4a, 0x67, 0x51, 0x1e, - 0xf5, 0x29, 0x4f, 0x64, 0xeb, 0x37, 0x12, 0xc8, 0x9f, 0xdb, 0x96, 0xc7, 0x5c, 0x44, 0xd9, 0xfd, - 0x00, 0xca, 0x93, 0x48, 0x27, 0x92, 0x1c, 0x2b, 0xe2, 0x28, 0x32, 0xeb, 0xa2, 0xc8, 0xa6, 0xa3, - 0x58, 0x0b, 0x67, 0xe1, 0x73, 0x01, 0xe7, 0x95, 0x04, 0x68, 0x51, 0xec, 0x8e, 0x61, 0xb8, 0x33, - 0x27, 0xe8, 0x99, 0xe8, 0x09, 0x54, 0x8d, 0x2b, 0x6c, 0x3b, 0xba, 0x83, 0x27, 0xc4, 0x9f, 0x62, - 0x83, 0x08, 0x58, 0x5b, 0x4c, 0xdd, 0x8f, 0xb4, 0xe8, 0x01, 0x94, 0xb8, 0xa1, 0x6d, 0x0a, 0x78, - 0x45, 0x26, 0xf7, 0x4c, 0x0a, 0xdb, 0x7d, 0xe9, 0x10, 0x4f, 0xa0, 0xe3, 0xc2, 0x37, 0xc8, 0x14, - 0xe6, 0x28, 0x5a, 0x06, 0x20, 0x8d, 0xcc, 0x89, 0x17, 0xf4, 0x1c, 0x3f, 0xf0, 0x66, 0x06, 0xc5, - 0xed, 0xa3, 0x8f, 0x61, 0xeb, 0xc5, 0xcc, 0x31, 0x75, 0x8f, 0x18, 0xf6, 0xd4, 0x26, 0x4e, 0x20, - 0x80, 0xdd, 0xa1, 0x5a, 0x2d, 0x52, 0xb6, 0xbf, 0x13, 0x1d, 0xb1, 0x1d, 0x1f, 0xe1, 0x31, 0x6f, - 0xba, 0x9d, 0x70, 0xd7, 0xfa, 0x57, 0x16, 0x8a, 0x3d, 0xe7, 0xd2, 0x9d, 0x39, 0x26, 0x7a, 0x0c, - 0x9b, 0xbe, 0x3b, 0xf3, 0x0c, 0xa2, 0xb3, 0x10, 0x84, 0xe3, 0x0a, 0xd7, 0x75, 0xa9, 0x0a, 0xdd, - 0x87, 0x62, 0x10, 0xea, 0x57, 0xd8, 0xbf, 0x12, 0xd1, 0x16, 0x82, 0xf0, 0x33, 0xec, 0x5f, 0xa1, - 0x7b, 0x50, 0xf0, 0x89, 0x63, 0x2e, 0xa2, 0x15, 0x12, 0xad, 0x6c, 0x8c, 0x94, 0xb3, 0x3f, 0x56, - 0xd0, 0x5d, 0x78, 0x42, 0x83, 0x15, 0xac, 0x17, 0x12, 0x6d, 0x60, 0xec, 0xfb, 0x24, 0xd0, 0xb1, - 0x69, 0x7a, 0x82, 0xe1, 0x65, 0xa6, 0xe9, 0x98, 0xa6, 0x47, 0x5b, 0xea, 0xda, 0xb5, 0x74, 0xdb, - 0x31, 0x49, 0x28, 0xa8, 0x5d, 0xba, 0x76, 0xad, 0x1e, 0x95, 0xd1, 0x53, 0x06, 0x91, 0x51, 0xb8, - 0xc4, 0x28, 0xdc, 0x48, 0x53, 0x78, 0x14, 0x32, 0xe2, 0x16, 0x02, 0xf6, 0x8b, 0x7e, 0x06, 0xb5, - 0x5b, 0x24, 0x65, 0xdc, 0xaf, 0x2c, 0x73, 0x7f, 0x79, 0x26, 0x68, 0xf2, 0x6c, 0x79, 0x4a, 0x7c, - 0x17, 0x6a, 0xf3, 0x44, 0x87, 0xe8, 0x6c, 0x18, 0x00, 0x03, 0x28, 0x27, 0x17, 0x8e, 0xe9, 0x60, - 0xf8, 0x39, 0xd4, 0x57, 0x54, 0x44, 0xa9, 0xb0, 0xb3, 0x77, 0xd3, 0x67, 0xdf, 0x26, 0x82, 0x86, - 0xbc, 0xdb, 0xe4, 0x68, 0x40, 0xde, 0xf6, 0xbb, 0x6a, 0x47, 0xd9, 0x64, 0x33, 0x8f, 0x0b, 0xed, - 0x52, 0x44, 0xb9, 0xd6, 0x57, 0x12, 0xe4, 0x06, 0xdd, 0x51, 0x98, 0xac, 0xa3, 0xb4, 0xa6, 0x8e, - 0x99, 0x54, 0x1d, 0x1f, 0x00, 0x1d, 0x5a, 0xfa, 0xcc, 0x27, 0x26, 0xab, 0x70, 0x4e, 0x2b, 0x5a, - 0xd8, 0x1f, 0xfb, 0x84, 0xd1, 0xe6, 0xf2, 0xda, 0x35, 0xbe, 0xd4, 0xaf, 0x88, 0x6d, 0x5d, 0xf1, - 0x2a, 0xe7, 0xb4, 0x0a, 0xd3, 0x7d, 0xc6, 0x54, 0xcc, 0x6b, 0x80, 0x83, 0x59, 0x34, 0xad, 0x84, - 0x44, 0x0b, 0x49, 0x3c, 0xcf, 0xf5, 0xf4, 0x89, 0x6f, 0x45, 0x85, 0x64, 0x8a, 0xcf, 0x7d, 0xab, - 0xfd, 0x41, 0xb2, 0x53, 0xaa, 0x89, 0x31, 0x6d, 0xe8, 0x41, 0xd8, 0xfa, 0x8b, 0x04, 0xf5, 0xf3, - 0x59, 0xc0, 0x98, 0x7b, 0x7e, 0xe9, 0x13, 0x6f, 0xce, 0x87, 0x85, 0x02, 0x45, 0x7f, 0x66, 0x18, - 0xc4, 0xf7, 0x59, 0x64, 0x25, 0x2d, 0x12, 0x6f, 0xe1, 0xcc, 0xdc, 0xc6, 0x99, 0x48, 0x4b, 0x36, - 0x95, 0x96, 0x14, 0xd0, 0x5c, 0x1a, 0x28, 0xda, 0x85, 0x4d, 0x9a, 0x1b, 0x3a, 0x94, 0x59, 0x7e, - 0x38, 0x97, 0xc1, 0xc2, 0xfe, 0x09, 0x21, 0x34, 0x45, 0xed, 0x27, 0x51, 0x18, 0xcd, 0x38, 0x0c, - 0x57, 0x80, 0xd7, 0xdd, 0x18, 0x7d, 0x6b, 0x02, 0xd5, 0x73, 0xcf, 0xb6, 0x6c, 0x07, 0x07, 0xb6, - 0x63, 0x0d, 0x8c, 0x77, 0x95, 0x2a, 0xd5, 0x05, 0x99, 0x74, 0x17, 0xb4, 0x3f, 0x5a, 0x31, 0x62, - 0xdc, 0xd8, 0xb3, 0xce, 0x93, 0xf8, 0xef, 0x02, 0x40, 0x94, 0xc4, 0x51, 0x48, 0xe9, 0x6b, 0x12, - 0x3f, 0x60, 0x36, 0xae, 0x93, 0x9a, 0x02, 0x72, 0x62, 0x81, 0x8f, 0x82, 0x54, 0x67, 0x67, 0xd6, - 0x77, 0x76, 0x36, 0xd5, 0xd9, 0x07, 0x50, 0x27, 0x61, 0x40, 0x3c, 0x87, 0x0e, 0xba, 0xb8, 0xc5, - 0x79, 0x4a, 0x6b, 0xd1, 0x52, 0x67, 0xd1, 0xea, 0x7b, 0x20, 0x4f, 0x3d, 0xe3, 0xd9, 0xf7, 0x92, - 0xc6, 0x3c, 0xbf, 0x5b, 0x4c, 0x1f, 0x5b, 0xc6, 0xcc, 0x2d, 0xa4, 0x98, 0xab, 0x40, 0x31, 0x6a, - 0x6b, 0xce, 0xb0, 0x48, 0x4c, 0xdf, 0xcc, 0xa5, 0xa5, 0x9b, 0x39, 0x31, 0x46, 0xca, 0xdf, 0x60, - 0x8c, 0x3c, 0x83, 0x3c, 0x4b, 0x29, 0xeb, 0xf6, 0xca, 0xb3, 0xed, 0xb4, 0xf1, 0x52, 0x4d, 0xb5, - 0xdc, 0x94, 0x56, 0xf6, 0x08, 0x2a, 0xbc, 0xf6, 0xc4, 0xa4, 0x3b, 0x79, 0xe3, 0x3f, 0x5e, 0xda, - 0x79, 0x9b, 0xe2, 0x1a, 0x44, 0xbb, 0x46, 0x21, 0x7d, 0x2f, 0xb1, 0x4d, 0xd6, 0xee, 0x65, 0x2d, - 0x63, 0x9b, 0xe8, 0xc7, 0x50, 0x5d, 0x10, 0x4b, 0xb4, 0xdc, 0x9d, 0x55, 0xf0, 0x87, 0x6c, 0x4d, - 0xdb, 0x8a, 0x8c, 0xb9, 0xbc, 0x6e, 0x26, 0x6d, 0x7d, 0x8b, 0x99, 0x74, 0x04, 0xf5, 0xa9, 0xa1, - 0x0b, 0xaf, 0x7c, 0x3f, 0xbd, 0xe5, 0xab, 0xcc, 0x25, 0x4a, 0xbb, 0xa4, 0xb3, 0x49, 0xab, 0x4d, - 0x0d, 0xee, 0x5a, 0x8d, 0x8c, 0xa3, 0x4a, 0x4d, 0x3d, 0xdb, 0x20, 0x8a, 0xbc, 0xa8, 0xd4, 0x80, - 0xca, 0xb4, 0x41, 0x44, 0xfb, 0x29, 0x35, 0x5e, 0x79, 0xde, 0x79, 0x8b, 0x93, 0xd9, 0x7d, 0x19, - 0x9f, 0x8c, 0xde, 0x7d, 0x32, 0xb5, 0x8e, 0x4f, 0xde, 0x87, 0x9a, 0x70, 0xe0, 0xbf, 0xc4, 0x53, - 0x9d, 0xf5, 0xbc, 0x52, 0x67, 0xc7, 0x54, 0xf9, 0xc2, 0xf0, 0x25, 0x9e, 0xaa, 0x54, 0x1d, 0xa1, - 0x0c, 0xdc, 0x2f, 0x89, 0xa3, 0x34, 0x16, 0x28, 0x47, 0x54, 0x4e, 0x0c, 0xe1, 0xdf, 0x65, 0xa0, - 0xb2, 0xb8, 0x4b, 0x16, 0x25, 0x94, 0x16, 0x25, 0xfc, 0x01, 0x80, 0xcd, 0x6f, 0x64, 0xca, 0x8a, - 0x0c, 0x43, 0x7b, 0x37, 0x8d, 0x56, 0xdc, 0xd8, 0x5a, 0x59, 0x18, 0x8e, 0x42, 0xf4, 0x24, 0x22, - 0x60, 0x76, 0x37, 0xbb, 0x26, 0x3c, 0xce, 0xba, 0x1f, 0x41, 0x65, 0xc1, 0x90, 0x20, 0x54, 0x72, - 0xcc, 0x5c, 0x59, 0xcd, 0xba, 0x51, 0xa8, 0x81, 0x1b, 0xcf, 0x87, 0x9f, 0x42, 0x7c, 0xe5, 0x45, - 0xec, 0xca, 0x33, 0x76, 0xed, 0xac, 0xb9, 0x2a, 0x47, 0xa1, 0x20, 0x5a, 0x75, 0xb1, 0x91, 0x2b, - 0xda, 0x1f, 0x26, 0xa7, 0xfb, 0xbd, 0x55, 0xef, 0x41, 0x41, 0xd8, 0xfa, 0x43, 0x16, 0xee, 0x88, - 0x58, 0xcf, 0x88, 0x85, 0x8d, 0x9b, 0xff, 0x93, 0x77, 0x94, 0xf6, 0xf2, 0x3b, 0xca, 0xe3, 0x95, - 0xf5, 0xe5, 0x33, 0x86, 0x47, 0xfe, 0xbf, 0x7f, 0x61, 0x69, 0x37, 0x5f, 0xbd, 0xde, 0x91, 0xa2, - 0x92, 0xd5, 0xe2, 0x92, 0x09, 0x12, 0xb6, 0xfe, 0x2c, 0x81, 0x1c, 0x33, 0x47, 0x14, 0xec, 0xbf, - 0xba, 0x53, 0xd6, 0x96, 0x2e, 0x55, 0xa2, 0xec, 0xfa, 0x12, 0xe5, 0xde, 0x51, 0xa2, 0xfc, 0x52, - 0x89, 0xda, 0xad, 0x64, 0x3c, 0x77, 0x57, 0xdc, 0xcc, 0x41, 0xd8, 0xfa, 0x7d, 0x06, 0x6a, 0x09, - 0x36, 0x8b, 0xa0, 0xda, 0xa9, 0x16, 0x95, 0x58, 0xf2, 0x1f, 0xad, 0x2c, 0xa1, 0x28, 0xde, 0xaa, - 0x46, 0xcd, 0xbc, 0xa7, 0x51, 0x7f, 0x92, 0x6e, 0xd4, 0xec, 0xaa, 0x12, 0x2f, 0xa7, 0xfb, 0xbd, - 0xed, 0x9a, 0xfb, 0x16, 0xed, 0x2a, 0xbd, 0xa7, 0x5d, 0xf7, 0x4f, 0x41, 0x5e, 0xfe, 0x07, 0x11, - 0xdd, 0x03, 0xe4, 0xdb, 0x96, 0x43, 0xcc, 0xe4, 0x8a, 0xbc, 0x81, 0x1e, 0xc1, 0xfd, 0x59, 0x7c, - 0x6c, 0x6a, 0x51, 0xda, 0xff, 0x55, 0x3a, 0xeb, 0xe2, 0x72, 0xfa, 0x10, 0x76, 0xc6, 0xfd, 0xde, - 0x85, 0xaa, 0x0d, 0x3b, 0x67, 0xfa, 0xe8, 0xb9, 0x3e, 0x1c, 0x75, 0x46, 0xe3, 0xa1, 0x3e, 0xee, - 0x0f, 0x07, 0x6a, 0xb7, 0x77, 0xd2, 0x53, 0x8f, 0xe5, 0x0d, 0x54, 0x87, 0x6a, 0xaf, 0x7f, 0x74, - 0x3e, 0xee, 0x1f, 0xeb, 0xc3, 0x71, 0xb7, 0xab, 0x0e, 0x87, 0xb2, 0x84, 0xb6, 0xe1, 0xc1, 0x40, - 0xed, 0x1f, 0xf7, 0xfa, 0xa7, 0x7a, 0xb4, 0xa8, 0x3e, 0x57, 0xbb, 0xe3, 0x51, 0xef, 0xbc, 0x2f, - 0x67, 0xd0, 0x7d, 0xa8, 0x0f, 0xba, 0x42, 0xa3, 0xc6, 0xfb, 0xb2, 0x14, 0x7c, 0x72, 0xe1, 0xa4, - 0xd3, 0x3b, 0x53, 0x8f, 0xe5, 0x1c, 0xba, 0x0b, 0xb5, 0x41, 0x57, 0x8f, 0x5c, 0x6a, 0xea, 0x85, - 0xaa, 0x8d, 0xe4, 0x3c, 0x6a, 0x80, 0x7c, 0x3e, 0x1e, 0x71, 0xff, 0x62, 0x51, 0x2e, 0xa4, 0xb4, - 0x91, 0xeb, 0x22, 0xc5, 0xb9, 0xd0, 0x0a, 0xbf, 0x25, 0xb4, 0x09, 0xa5, 0x6e, 0xa7, 0xdf, 0x55, - 0xa9, 0x54, 0xde, 0x3f, 0x82, 0x82, 0x88, 0xbc, 0x0a, 0x95, 0x74, 0x94, 0x15, 0x28, 0x46, 0x07, - 0x48, 0x74, 0xd7, 0xf9, 0xd1, 0x50, 0xd5, 0x2e, 0xd4, 0x63, 0x39, 0x43, 0x25, 0x0e, 0x48, 0x3d, - 0x96, 0xb3, 0xfb, 0xbf, 0x84, 0x02, 0x9f, 0x22, 0x08, 0xc1, 0x56, 0xc2, 0x87, 0x3e, 0x7a, 0x2e, - 0x6f, 0xa0, 0x22, 0x64, 0x4f, 0x3b, 0x34, 0x41, 0x75, 0xa8, 0x9e, 0x76, 0x86, 0x7a, 0x87, 0x02, - 0xef, 0x7c, 0x71, 0x76, 0xde, 0xa1, 0x9e, 0xca, 0x90, 0x3f, 0x19, 0xf7, 0x8f, 0x69, 0x22, 0xee, - 0x42, 0x8d, 0x3d, 0xa6, 0x2c, 0x72, 0x0c, 0x86, 0x10, 0xf2, 0xf4, 0x80, 0x28, 0xb9, 0x22, 0x23, - 0x85, 0xfd, 0x3f, 0x49, 0x50, 0x5f, 0x31, 0xcc, 0xd0, 0x63, 0xd8, 0x8e, 0x6c, 0xcf, 0xd4, 0xd3, - 0x4e, 0xf7, 0x0b, 0xfd, 0x16, 0xb6, 0x7b, 0x80, 0x96, 0x4c, 0x38, 0x54, 0x05, 0x1a, 0x4b, 0x7a, - 0x0e, 0x32, 0x83, 0x3e, 0x82, 0xdd, 0x55, 0x2b, 0x29, 0xcc, 0x59, 0xd4, 0x82, 0xe6, 0x6d, 0xbf, - 0xe9, 0xb8, 0x8e, 0x06, 0x5f, 0xbd, 0x69, 0x4a, 0x5f, 0xbf, 0x69, 0x4a, 0x7f, 0x7f, 0xd3, 0x94, - 0x7e, 0xfb, 0xb6, 0xb9, 0xf1, 0xf5, 0xdb, 0xe6, 0xc6, 0x5f, 0xdf, 0x36, 0x37, 0x7e, 0xf1, 0xa9, - 0x65, 0x07, 0x57, 0xb3, 0xcb, 0x03, 0xc3, 0x9d, 0x1c, 0x4e, 0x67, 0xfe, 0x15, 0x9b, 0x67, 0xec, - 0xe9, 0x29, 0x7b, 0x7c, 0xea, 0xb8, 0x26, 0x39, 0x0c, 0x0f, 0xe3, 0x0e, 0x61, 0x5f, 0xb6, 0x2e, - 0x0b, 0xec, 0x1b, 0xd5, 0xf7, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xd2, 0xba, 0xeb, 0xd8, 0xf6, - 0x12, 0x00, 0x00, + 0xe8, 0xa9, 0xb7, 0xa2, 0x87, 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, 0xfe, 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, 0x46, 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, 0x2a, 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, + 0x5f, 0x42, 0x81, 0x4f, 0x11, 0x84, 0x60, 0x2b, 0xe1, 0x43, 0x1f, 0x3d, 0x97, 0x37, 0x50, 0x11, + 0xb2, 0xa7, 0x1d, 0x9a, 0xa0, 0x3a, 0x54, 0x4f, 0x3b, 0x43, 0xbd, 0x43, 0x81, 0x77, 0xbe, 0x38, + 0x3b, 0xef, 0x50, 0x4f, 0x65, 0xc8, 0x9f, 0x8c, 0xfb, 0xc7, 0x34, 0x11, 0x77, 0xa1, 0xc6, 0x96, + 0x29, 0x8b, 0x1c, 0x83, 0x21, 0x84, 0x3c, 0xbd, 0x20, 0x4a, 0xae, 0xc8, 0x48, 0x61, 0xff, 0x8f, + 0x12, 0xd4, 0x57, 0x0c, 0x33, 0xf4, 0x18, 0xb6, 0x23, 0xdb, 0x33, 0xf5, 0xb4, 0xd3, 0xfd, 0x42, + 0xbf, 0x85, 0xed, 0x1e, 0xa0, 0x25, 0x13, 0x0e, 0x55, 0x81, 0xc6, 0x92, 0x9e, 0x83, 0xcc, 0xa0, + 0x8f, 0x60, 0x77, 0xd5, 0x4e, 0x0a, 0x73, 0x16, 0xb5, 0xa0, 0x79, 0xdb, 0x6f, 0x3a, 0xae, 0xa3, + 0xc1, 0x57, 0x6f, 0x9a, 0xd2, 0xd7, 0x6f, 0x9a, 0xd2, 0xdf, 0xdf, 0x34, 0xa5, 0xdf, 0xbe, 0x6d, + 0x6e, 0x7c, 0xfd, 0xb6, 0xb9, 0xf1, 0x97, 0xb7, 0xcd, 0x8d, 0x5f, 0x7c, 0x6a, 0xd9, 0xc1, 0xd5, + 0xec, 0xf2, 0xc0, 0x70, 0x27, 0x87, 0xd3, 0x99, 0x7f, 0xc5, 0xe6, 0x19, 0x5b, 0x3d, 0x65, 0xcb, + 0xa7, 0x8e, 0x6b, 0x92, 0xc3, 0xf0, 0x30, 0xee, 0x10, 0xf6, 0x6b, 0xd4, 0x65, 0x81, 0xfd, 0xae, + 0xf4, 0xfd, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xcf, 0xfd, 0xa0, 0xaa, 0x12, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -1972,9 +1963,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 { @@ -2826,11 +2814,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-- { { @@ -3466,9 +3449,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 } @@ -6131,25 +6111,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:]) From 7b0b4e79b293bbbef176931528a4dbce44ad7b40 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 11:12:37 +0530 Subject: [PATCH 58/75] tests: updated tests for UniversalTxStatus removal changes --- .../uexecutor/chain_enabled_test.go | 3 +- .../uexecutor/inbound_cea_payload_test.go | 4 ++- test/integration/uexecutor/query_v2_test.go | 29 +++++++++++-------- 3 files changed, 22 insertions(+), 14 deletions(-) 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/inbound_cea_payload_test.go b/test/integration/uexecutor/inbound_cea_payload_test.go index 3a41dc0f..cda0010e 100644 --- a/test/integration/uexecutor/inbound_cea_payload_test.go +++ b/test/integration/uexecutor/inbound_cea_payload_test.go @@ -301,7 +301,9 @@ func TestInboundCEAFundsAndPayload(t *testing.T) { 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) + // PC failed → revert outbound created → outbound is pending + require.NotEmpty(t, utx.OutboundTx, "revert outbound should be created after PC failure") + require.Equal(t, uexecutortypes.Status_PENDING, utx.OutboundTx[0].OutboundStatus) }) t.Run("creates revert outbound when isCEA is true and recipient is not a UEA", func(t *testing.T) { 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) { From fcb9357ecd2d6c9a0d0e42096faf96e07628100f Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Tue, 17 Mar 2026 11:55:28 +0530 Subject: [PATCH 59/75] chore: sync with evm internal-transaction changes --- go.mod | 5 ++++- go.sum | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) 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= From ac12974a52d729b4069d27057613e22d64a89e1d Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 12:45:42 +0530 Subject: [PATCH 60/75] feat: added RESCUE_FUNDS type in proto --- proto/uexecutor/v1/types.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/proto/uexecutor/v1/types.proto b/proto/uexecutor/v1/types.proto index 8237a69c..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 { From 800487fe1e1d967cd0ced5d4021b3a74f7524b12 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 12:45:47 +0530 Subject: [PATCH 61/75] refactor: added generated protobuf --- api/uexecutor/v1/types.pulsar.go | 68 +++++++++++++++++--------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/api/uexecutor/v1/types.pulsar.go b/api/uexecutor/v1/types.pulsar.go index d9725fe6..1090a951 100644 --- a/api/uexecutor/v1/types.pulsar.go +++ b/api/uexecutor/v1/types.pulsar.go @@ -10853,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. @@ -10865,6 +10866,7 @@ var ( 4: "FUNDS_AND_PAYLOAD", 5: "PAYLOAD", 6: "INBOUND_REVERT", + 7: "RESCUE_FUNDS", } TxType_value = map[string]int32{ "UNSPECIFIED_TX": 0, @@ -10874,6 +10876,7 @@ var ( "FUNDS_AND_PAYLOAD": 4, "PAYLOAD": 5, "INBOUND_REVERT": 6, + "RESCUE_FUNDS": 7, } ) @@ -12298,38 +12301,39 @@ var file_uexecutor_v1_types_proto_rawDesc = []byte{ 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, + 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 ( From 5e2d1ec097347a5ae0e6e1f1d155a44cee291be2 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 12:48:01 +0530 Subject: [PATCH 62/75] feat: implemented rescue type outbound changes --- x/uexecutor/keeper/create_outbound.go | 144 ++++++++++++++++++ x/uexecutor/keeper/evm_hooks.go | 13 +- x/uexecutor/keeper/execute_inbound_funds.go | 2 +- .../execute_inbound_funds_and_payload.go | 2 +- x/uexecutor/keeper/execute_inbound_gas.go | 2 +- .../keeper/execute_inbound_gas_and_payload.go | 2 +- x/uexecutor/keeper/msg_execute_payload.go | 3 + x/uexecutor/types/constants.go | 4 + x/uexecutor/types/gateway_pc_event_decode.go | 67 ++++++++ x/uexecutor/types/keys.go | 18 ++- x/uexecutor/types/tx_type.go | 2 +- 11 files changed, 245 insertions(+), 14 deletions(-) diff --git a/x/uexecutor/keeper/create_outbound.go b/x/uexecutor/keeper/create_outbound.go index 6f769013..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" ) @@ -170,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, 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 09e67583..c3a10497 100644 --- a/x/uexecutor/keeper/execute_inbound_funds.go +++ b/x/uexecutor/keeper/execute_inbound_funds.go @@ -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 ff6b3d15..dd84722c 100644 --- a/x/uexecutor/keeper/execute_inbound_funds_and_payload.go +++ b/x/uexecutor/keeper/execute_inbound_funds_and_payload.go @@ -162,7 +162,7 @@ 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( diff --git a/x/uexecutor/keeper/execute_inbound_gas.go b/x/uexecutor/keeper/execute_inbound_gas.go index b479cf64..9f4ac891 100644 --- a/x/uexecutor/keeper/execute_inbound_gas.go +++ b/x/uexecutor/keeper/execute_inbound_gas.go @@ -181,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 ab09f80e..6d830cbd 100644 --- a/x/uexecutor/keeper/execute_inbound_gas_and_payload.go +++ b/x/uexecutor/keeper/execute_inbound_gas_and_payload.go @@ -183,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( 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/types/constants.go b/x/uexecutor/types/constants.go index 7b3e97eb..0f8ef682 100644 --- a/x/uexecutor/types/constants.go +++ b/x/uexecutor/types/constants.go @@ -50,3 +50,7 @@ const ( var UniversalTxOutboundEventSig = crypto.Keccak256Hash([]byte( "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/gateway_pc_event_decode.go b/x/uexecutor/types/gateway_pc_event_decode.go index 9cfc1a36..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" @@ -96,3 +97,69 @@ func DecodeUniversalTxOutboundFromLog(log *evmtypes.Log) (*UniversalTxOutboundEv 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 cc8ced32..9716aa38 100755 --- a/x/uexecutor/types/keys.go +++ b/x/uexecutor/types/keys.go @@ -80,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/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: From 48d4cd7d59c77ff0a69fed9a1e6621c733369658 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 12:48:05 +0530 Subject: [PATCH 63/75] refactor: added generated protobuf --- x/uexecutor/types/types.pb.go | 224 +++++++++++++++++----------------- 1 file changed, 114 insertions(+), 110 deletions(-) diff --git a/x/uexecutor/types/types.pb.go b/x/uexecutor/types/types.pb.go index edce0ef2..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 { @@ -1410,120 +1413,121 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/types.proto", fileDescriptor_fab6d3ca71d1e2a5) } var fileDescriptor_fab6d3ca71d1e2a5 = []byte{ - // 1808 bytes of a gzipped FileDescriptorProto + // 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, - 0xe8, 0xa9, 0xb7, 0xa2, 0x87, 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, 0xfe, 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, 0x46, 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, 0x2a, 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, - 0x5f, 0x42, 0x81, 0x4f, 0x11, 0x84, 0x60, 0x2b, 0xe1, 0x43, 0x1f, 0x3d, 0x97, 0x37, 0x50, 0x11, - 0xb2, 0xa7, 0x1d, 0x9a, 0xa0, 0x3a, 0x54, 0x4f, 0x3b, 0x43, 0xbd, 0x43, 0x81, 0x77, 0xbe, 0x38, - 0x3b, 0xef, 0x50, 0x4f, 0x65, 0xc8, 0x9f, 0x8c, 0xfb, 0xc7, 0x34, 0x11, 0x77, 0xa1, 0xc6, 0x96, - 0x29, 0x8b, 0x1c, 0x83, 0x21, 0x84, 0x3c, 0xbd, 0x20, 0x4a, 0xae, 0xc8, 0x48, 0x61, 0xff, 0x8f, - 0x12, 0xd4, 0x57, 0x0c, 0x33, 0xf4, 0x18, 0xb6, 0x23, 0xdb, 0x33, 0xf5, 0xb4, 0xd3, 0xfd, 0x42, - 0xbf, 0x85, 0xed, 0x1e, 0xa0, 0x25, 0x13, 0x0e, 0x55, 0x81, 0xc6, 0x92, 0x9e, 0x83, 0xcc, 0xa0, - 0x8f, 0x60, 0x77, 0xd5, 0x4e, 0x0a, 0x73, 0x16, 0xb5, 0xa0, 0x79, 0xdb, 0x6f, 0x3a, 0xae, 0xa3, - 0xc1, 0x57, 0x6f, 0x9a, 0xd2, 0xd7, 0x6f, 0x9a, 0xd2, 0xdf, 0xdf, 0x34, 0xa5, 0xdf, 0xbe, 0x6d, - 0x6e, 0x7c, 0xfd, 0xb6, 0xb9, 0xf1, 0x97, 0xb7, 0xcd, 0x8d, 0x5f, 0x7c, 0x6a, 0xd9, 0xc1, 0xd5, - 0xec, 0xf2, 0xc0, 0x70, 0x27, 0x87, 0xd3, 0x99, 0x7f, 0xc5, 0xe6, 0x19, 0x5b, 0x3d, 0x65, 0xcb, - 0xa7, 0x8e, 0x6b, 0x92, 0xc3, 0xf0, 0x30, 0xee, 0x10, 0xf6, 0x6b, 0xd4, 0x65, 0x81, 0xfd, 0xae, - 0xf4, 0xfd, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xcf, 0xfd, 0xa0, 0xaa, 0x12, 0x00, 0x00, + 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 { From 04cacdb17017478045d8d6172fdeffed1b38a339 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 12:48:38 +0530 Subject: [PATCH 64/75] tests: added integration tests for rescue funds --- .../uexecutor/rescue_funds_test.go | 600 ++++++++++++++++++ x/uexecutor/types/universal_tx_test.go | 11 - 2 files changed, 600 insertions(+), 11 deletions(-) create mode 100644 test/integration/uexecutor/rescue_funds_test.go diff --git a/test/integration/uexecutor/rescue_funds_test.go b/test/integration/uexecutor/rescue_funds_test.go new file mode 100644 index 00000000..ce04c47b --- /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 (recipient is not +// a registered UEA), 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) + + usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr + testAddress := utils.GetDefaultAddresses().DefaultTestAddr + // TargetAddr2 is a plain address — not a deployed UEA — so the deposit will fail. + nonUEARecipient := utils.GetDefaultAddresses().TargetAddr2 + + inbound := &uexecutortypes.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xrescue01", + Sender: testAddress, + Recipient: nonUEARecipient, + Amount: "1000000", + AssetAddr: usdcAddress.String(), + LogIndex: "1", + TxType: uexecutortypes.TxType_FUNDS_AND_PAYLOAD, + UniversalPayload: &uexecutortypes.UniversalPayload{ + To: nonUEARecipient, + 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 (first PCTx) must fail for non-UEA recipient") + + 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/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 { From 8cbd6c18d3d23023fd0d7765351334a1f86a4298 Mon Sep 17 00:00:00 2001 From: aman035 Date: Tue, 17 Mar 2026 15:34:45 +0530 Subject: [PATCH 65/75] fix: tx builder acc to gateway & vault changes --- universalClient/chains/evm/tx_builder.go | 119 +-- universalClient/chains/evm/tx_builder_test.go | 788 ++++++------------ universalClient/chains/svm/tx_builder.go | 374 +++++---- universalClient/chains/svm/tx_builder_test.go | 574 +++++++++---- 4 files changed, 917 insertions(+), 938 deletions(-) diff --git a/universalClient/chains/evm/tx_builder.go b/universalClient/chains/evm/tx_builder.go index 7c7e5716..f61cb138 100644 --- a/universalClient/chains/evm/tx_builder.go +++ b/universalClient/chains/evm/tx_builder.go @@ -18,7 +18,6 @@ import ( uetypes "github.com/pushchain/push-chain-node/x/uexecutor/types" ) - // RevertInstructions represents the struct for revert instruction in contracts // Matches: struct RevertInstructions { address revertRecipient; bytes revertMsg; } type RevertInstructions struct { @@ -26,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 @@ -83,7 +77,6 @@ func NewTxBuilder( return tb, nil } - // GetOutboundSigningRequest creates a signing request from outbound event data func (tb *TxBuilder) GetOutboundSigningRequest( ctx context.Context, @@ -135,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, @@ -207,9 +200,9 @@ func (tb *TxBuilder) BroadcastOutboundSigningRequest( return "", fmt.Errorf("failed to encode function call: %w", err) } - txValue, toAddress, err := tb.resolveTxParams(funcName, assetAddr, amount) - if err != nil { - return "", fmt.Errorf("failed to resolve tx params: %w", err) + txValue := big.NewInt(0) + if assetAddr == (ethcommon.Address{}) { + txValue = amount } gasLimitForTx, err := parseGasLimit(data.GasLimit) @@ -224,7 +217,7 @@ func (tb *TxBuilder) BroadcastOutboundSigningRequest( tx := types.NewTransaction( req.Nonce, - toAddress, + tb.vaultAddress, txValue, gasLimitForTx.Uint64(), gasPrice, @@ -270,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" @@ -371,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{} @@ -394,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 @@ -423,7 +366,7 @@ func (tb *TxBuilder) encodeFunctionCall( } values = []interface{}{txID32, universalTxID, assetAddr, amount, RevertInstructions{ RevertRecipient: target, - RevertMsg: revertMsgBytesToken, + RevertMsg: revertMsgBytes, }} default: @@ -448,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 "" diff --git a/universalClient/chains/evm/tx_builder_test.go b/universalClient/chains/evm/tx_builder_test.go index 471e5e2c..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,12 +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 TestRevertInstructionsStruct(t *testing.T) { recipient := ethcommon.HexToAddress("0x1234567890123456789012345678901234567890") revertMsg := []byte("test revert message") @@ -90,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))", }, } @@ -116,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 { @@ -147,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 { @@ -158,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) @@ -265,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", @@ -338,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]) }) @@ -588,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/svm/tx_builder.go b/universalClient/chains/svm/tx_builder.go index 92b5f6af..25a2ec13 100644 --- a/universalClient/chains/svm/tx_builder.go +++ b/universalClient/chains/svm/tx_builder.go @@ -280,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 != "" { @@ -318,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 + } } } @@ -340,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()) + } } } @@ -367,7 +365,7 @@ 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 { @@ -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, ) } @@ -761,7 +744,7 @@ func (tb *TxBuilder) BuildOutboundTransaction( // 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(), @@ -880,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: @@ -891,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: @@ -913,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 @@ -924,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( @@ -941,7 +926,6 @@ func (tb *TxBuilder) constructTSSMessage( targetProgram [32]byte, execAccounts []GatewayAccountMeta, ixData []byte, - rentFee uint64, revertRecipient [32]byte, revertMint [32]byte, ) ([]byte, error) { @@ -992,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...) @@ -1096,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 @@ -1115,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]) @@ -1125,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. @@ -1202,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] @@ -1214,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) @@ -1227,7 +1205,6 @@ func (tb *TxBuilder) buildWithdrawAndExecuteData( writableFlags []byte, ixData []byte, gasFee uint64, - rentFee uint64, signature []byte, recoveryID byte, messageHash []byte, @@ -1261,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...) @@ -1273,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...) @@ -1316,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...) @@ -1334,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 // @@ -1530,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 a86701fb..59884c52 100644 --- a/universalClient/chains/svm/tx_builder_test.go +++ b/universalClient/chains/svm/tx_builder_test.go @@ -57,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 { @@ -110,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) @@ -133,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{}) } // ============================================================ @@ -230,7 +219,6 @@ func TestNewTxBuilder(t *testing.T) { // TestDefaultComputeUnitLimit // ============================================================ - // ============================================================ // TestDeriveTSSPDA — seed must be "tsspda_v2" // ============================================================ @@ -336,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}, @@ -365,7 +355,7 @@ func TestAnchorDiscriminator(t *testing.T) { }{ {"finalize_universal_tx"}, {"revert_universal_tx"}, - {"revert_universal_tx_token"}, + {"rescue_funds"}, } for _, tt := range tests { @@ -394,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) { @@ -402,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) @@ -438,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) @@ -475,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") @@ -489,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) @@ -511,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) @@ -540,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) @@ -571,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) @@ -590,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) @@ -619,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) @@ -632,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) { @@ -752,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, ) @@ -784,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) { @@ -807,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, ) @@ -833,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]) @@ -859,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 // ============================================================ @@ -990,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) + } + }) + + 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) - 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") + 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) + } + }) + + 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) - 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") + assert.Len(t, rescueAccounts, len(revertAccounts)) + for i := range rescueAccounts { + assert.Equal(t, revertAccounts[i].PublicKey, rescueAccounts[i].PublicKey, "account %d pubkey", i) + } + }) } // ============================================================ @@ -1083,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}, @@ -1134,45 +1248,6 @@ func TestGatewayAccountMetaStruct(t *testing.T) { assert.True(t, meta.IsWritable) } -// ============================================================ -// TestGasLimitParsing -// ============================================================ - -func TestGasLimitParsing(t *testing.T) { - t.Run("empty returns error", func(t *testing.T) { - _, err := parseUint32("") - assert.Error(t, err) - }) - t.Run("zero returns error", func(t *testing.T) { - _, err := parseUint32("0") - // parseUint32 parses successfully but returns 0 - assert.NoError(t, err) - }) - t.Run("valid", func(t *testing.T) { - result, err := parseUint32("300000") - assert.NoError(t, err) - assert.Equal(t, uint32(300000), result) - }) - t.Run("invalid number returns error", func(t *testing.T) { - _, err := parseUint32("abc") - assert.Error(t, err) - }) -} - -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 // ============================================================ @@ -1191,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) @@ -1199,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") } @@ -1217,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) @@ -1251,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) @@ -1262,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) { @@ -1278,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) @@ -1294,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) }) @@ -1312,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) @@ -1321,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, ) @@ -1330,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) + }) } // ============================================================ @@ -1527,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) @@ -1545,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) @@ -1580,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) +} From c29ac9f708aa6a9e79ded0a253b4eb99712c843f Mon Sep 17 00:00:00 2001 From: aman035 Date: Tue, 17 Mar 2026 15:43:43 +0530 Subject: [PATCH 66/75] fix: svm event gas fee used report --- universalClient/chains/svm/event_confirmer.go | 31 +------------ universalClient/chains/svm/event_parser.go | 24 +++++++--- .../chains/svm/event_parser_test.go | 44 ++++++++++++------- 3 files changed, 47 insertions(+), 52 deletions(-) diff --git a/universalClient/chains/svm/event_confirmer.go b/universalClient/chains/svm/event_confirmer.go index c5e6b529..3f37fe8b 100644 --- a/universalClient/chains/svm/event_confirmer.go +++ b/universalClient/chains/svm/event_confirmer.go @@ -2,7 +2,6 @@ package svm import ( "context" - "encoding/json" "fmt" "strings" "sync" @@ -170,34 +169,8 @@ func (ec *EventConfirmer) processPendingEvents(ctx context.Context) error { confirmations := latestSlot - txSlot + 1 if confirmations >= requiredConfirmations { - var rowsAffected int64 - - // For outbound events, enrich with gas fee from tx metadata - if event.Type == chaincommon.EventTypeOutbound { - 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 = "0" - - 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") - } - + // 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(). Err(err). diff --git a/universalClient/chains/svm/event_parser.go b/universalClient/chains/svm/event_parser.go index 8640c65f..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 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 { From 01225bfa414636b7d8a5111aad7b6e65545fbd3e Mon Sep 17 00:00:00 2001 From: aman035 Date: Tue, 17 Mar 2026 17:18:43 +0530 Subject: [PATCH 67/75] fix: chain meta voting --- universalClient/chains/evm/chain_meta_oracle.go | 7 ++----- universalClient/chains/svm/chain_meta_oracle.go | 7 ++----- universalClient/pushsigner/pushsigner.go | 6 +++--- universalClient/pushsigner/vote.go | 4 +--- x/uexecutor/types/msg_vote_chain_meta.go | 3 +-- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/universalClient/chains/evm/chain_meta_oracle.go b/universalClient/chains/evm/chain_meta_oracle.go index 6ebb2e1c..838dbb42 100644 --- a/universalClient/chains/evm/chain_meta_oracle.go +++ b/universalClient/chains/evm/chain_meta_oracle.go @@ -97,16 +97,14 @@ func (g *ChainMetaOracle) fetchAndVoteChainMeta(ctx context.Context) { continue } - // Vote on chain meta (gas price + block height + observation timestamp) + // Vote on chain meta (gas price + block height) priceUint64 := gasPrice.Uint64() - observedAt := uint64(time.Now().Unix()) - voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, blockNumber, observedAt) + voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, blockNumber) if err != nil { g.logger.Error(). Err(err). Uint64("price", priceUint64). Uint64("block", blockNumber). - Uint64("observed_at", observedAt). Msg("failed to vote on chain meta") continue } @@ -115,7 +113,6 @@ func (g *ChainMetaOracle) fetchAndVoteChainMeta(ctx context.Context) { Str("vote_tx_hash", voteTxHash). Uint64("price", priceUint64). Uint64("block", blockNumber). - Uint64("observed_at", observedAt). Msg("successfully voted on chain meta") } } diff --git a/universalClient/chains/svm/chain_meta_oracle.go b/universalClient/chains/svm/chain_meta_oracle.go index 8cea54a6..aec40985 100644 --- a/universalClient/chains/svm/chain_meta_oracle.go +++ b/universalClient/chains/svm/chain_meta_oracle.go @@ -97,16 +97,14 @@ func (g *ChainMetaOracle) fetchAndVoteChainMeta(ctx context.Context) { continue } - // Vote on chain meta (gas price + slot height + observation timestamp) + // Vote on chain meta (gas price + slot height) priceUint64 := gasPrice.Uint64() - observedAt := uint64(time.Now().Unix()) - voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, slotNumber, observedAt) + voteTxHash, err := g.pushSigner.VoteChainMeta(ctx, g.chainID, priceUint64, slotNumber) if err != nil { g.logger.Error(). Err(err). Uint64("price", priceUint64). Uint64("slot", slotNumber). - Uint64("observed_at", observedAt). Msg("failed to vote on chain meta") continue } @@ -115,7 +113,6 @@ func (g *ChainMetaOracle) fetchAndVoteChainMeta(ctx context.Context) { Str("vote_tx_hash", voteTxHash). Uint64("price", priceUint64). Uint64("slot", slotNumber). - Uint64("observed_at", observedAt). Msg("successfully voted on chain meta") } } diff --git a/universalClient/pushsigner/pushsigner.go b/universalClient/pushsigner/pushsigner.go index 57aeadef..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) } -// VoteChainMeta votes on chain metadata (gas price, block height, observation timestamp). -func (s *Signer) VoteChainMeta(ctx context.Context, chainID string, price uint64, chainHeight uint64, observedAt uint64) (string, error) { - return voteChainMeta(ctx, s, s.log, s.granter, chainID, price, chainHeight, observedAt) +// 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/vote.go b/universalClient/pushsigner/vote.go index 5fbf4554..dfaa9aaf 100644 --- a/universalClient/pushsigner/vote.go +++ b/universalClient/pushsigner/vote.go @@ -86,7 +86,7 @@ func voteInbound( return vote(ctx, signer, log, msg, memo) } -// voteChainMeta votes on chain metadata (gas price, block height, observation timestamp) +// voteChainMeta votes on chain metadata (gas price, block height) func voteChainMeta( ctx context.Context, signer *Signer, @@ -95,14 +95,12 @@ func voteChainMeta( chainID string, price uint64, chainHeight uint64, - observedAt uint64, ) (string, error) { msg := &uexecutortypes.MsgVoteChainMeta{ Signer: granter, ObservedChainId: chainID, Price: price, ChainHeight: chainHeight, - ObservedAt: observedAt, } memo := fmt.Sprintf("Vote chain meta: %s @ price=%d height=%d", chainID, price, chainHeight) return vote(ctx, signer, log, msg, memo) diff --git a/x/uexecutor/types/msg_vote_chain_meta.go b/x/uexecutor/types/msg_vote_chain_meta.go index 775fea99..f4052aa6 100644 --- a/x/uexecutor/types/msg_vote_chain_meta.go +++ b/x/uexecutor/types/msg_vote_chain_meta.go @@ -14,14 +14,13 @@ var ( func NewMsgVoteChainMeta( sender sdk.Address, observedChainId string, - price, chainHeight, observedAt uint64, + price, chainHeight uint64, ) *MsgVoteChainMeta { return &MsgVoteChainMeta{ Signer: sender.String(), ObservedChainId: observedChainId, Price: price, ChainHeight: chainHeight, - ObservedAt: observedAt, } } From ef17e4147dd324f30c128513e045f9bca72bcb69 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 18:01:34 +0530 Subject: [PATCH 68/75] feat: updated proto for setChainMeta --- proto/uexecutor/v1/chain_meta.proto | 13 +++++++------ proto/uexecutor/v1/tx.proto | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/proto/uexecutor/v1/chain_meta.proto b/proto/uexecutor/v1/chain_meta.proto index 8a10ec03..c086080e 100644 --- a/proto/uexecutor/v1/chain_meta.proto +++ b/proto/uexecutor/v1/chain_meta.proto @@ -12,10 +12,11 @@ message ChainMeta { 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 observed_ats = 5; // Timestamps when each observation was made - uint64 median_index = 6; // Index of the median price in 'prices' + 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/tx.proto b/proto/uexecutor/v1/tx.proto index b8413f11..f2270e03 100755 --- a/proto/uexecutor/v1/tx.proto +++ b/proto/uexecutor/v1/tx.proto @@ -153,7 +153,6 @@ message MsgVoteChainMeta { 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 - uint64 observed_at = 5; // Timestamp when the observation was made (unix seconds) } // MsgVoteChainMetaResponse defines the response for MsgVoteChainMeta From e92c0f51236c4a2ac408232d68ef2dc24ff37e56 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 18:01:51 +0530 Subject: [PATCH 69/75] refactor: added generated protobuf --- api/uexecutor/v1/chain_meta.pulsar.go | 189 +++++++++++++++++--------- api/uexecutor/v1/tx.pulsar.go | 165 ++++++++-------------- 2 files changed, 177 insertions(+), 177 deletions(-) diff --git a/api/uexecutor/v1/chain_meta.pulsar.go b/api/uexecutor/v1/chain_meta.pulsar.go index 3bd7eff7..598df694 100644 --- a/api/uexecutor/v1/chain_meta.pulsar.go +++ b/api/uexecutor/v1/chain_meta.pulsar.go @@ -182,7 +182,7 @@ func (x *_ChainMeta_5_list) Append(value protoreflect.Value) { } func (x *_ChainMeta_5_list) AppendMutable() protoreflect.Value { - panic(fmt.Errorf("AppendMutable can not be called on message ChainMeta at list field ObservedAts as it is not of Message kind")) + 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) { @@ -199,13 +199,14 @@ func (x *_ChainMeta_5_list) IsValid() bool { } 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_observed_ats protoreflect.FieldDescriptor - fd_ChainMeta_median_index protoreflect.FieldDescriptor + 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() { @@ -215,8 +216,9 @@ func init() { 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_observed_ats = md_ChainMeta.Fields().ByName("observed_ats") + 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) @@ -308,9 +310,9 @@ func (x *fastReflection_ChainMeta) Range(f func(protoreflect.FieldDescriptor, pr return } } - if len(x.ObservedAts) != 0 { - value := protoreflect.ValueOfList(&_ChainMeta_5_list{list: &x.ObservedAts}) - if !f(fd_ChainMeta_observed_ats, value) { + if len(x.StoredAts) != 0 { + value := protoreflect.ValueOfList(&_ChainMeta_5_list{list: &x.StoredAts}) + if !f(fd_ChainMeta_stored_ats, value) { return } } @@ -320,6 +322,12 @@ func (x *fastReflection_ChainMeta) Range(f func(protoreflect.FieldDescriptor, pr 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. @@ -343,10 +351,12 @@ func (x *fastReflection_ChainMeta) Has(fd protoreflect.FieldDescriptor) bool { return len(x.Prices) != 0 case "uexecutor.v1.ChainMeta.chain_heights": return len(x.ChainHeights) != 0 - case "uexecutor.v1.ChainMeta.observed_ats": - return len(x.ObservedAts) != 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")) @@ -371,10 +381,12 @@ func (x *fastReflection_ChainMeta) Clear(fd protoreflect.FieldDescriptor) { x.Prices = nil case "uexecutor.v1.ChainMeta.chain_heights": x.ChainHeights = nil - case "uexecutor.v1.ChainMeta.observed_ats": - x.ObservedAts = 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")) @@ -412,15 +424,18 @@ func (x *fastReflection_ChainMeta) Get(descriptor protoreflect.FieldDescriptor) } listValue := &_ChainMeta_4_list{list: &x.ChainHeights} return protoreflect.ValueOfList(listValue) - case "uexecutor.v1.ChainMeta.observed_ats": - if len(x.ObservedAts) == 0 { + case "uexecutor.v1.ChainMeta.stored_ats": + if len(x.StoredAts) == 0 { return protoreflect.ValueOfList(&_ChainMeta_5_list{}) } - listValue := &_ChainMeta_5_list{list: &x.ObservedAts} + 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")) @@ -455,12 +470,14 @@ func (x *fastReflection_ChainMeta) Set(fd protoreflect.FieldDescriptor, value pr lv := value.List() clv := lv.(*_ChainMeta_4_list) x.ChainHeights = *clv.list - case "uexecutor.v1.ChainMeta.observed_ats": + case "uexecutor.v1.ChainMeta.stored_ats": lv := value.List() clv := lv.(*_ChainMeta_5_list) - x.ObservedAts = *clv.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")) @@ -499,16 +516,18 @@ func (x *fastReflection_ChainMeta) Mutable(fd protoreflect.FieldDescriptor) prot } value := &_ChainMeta_4_list{list: &x.ChainHeights} return protoreflect.ValueOfList(value) - case "uexecutor.v1.ChainMeta.observed_ats": - if x.ObservedAts == nil { - x.ObservedAts = []uint64{} + case "uexecutor.v1.ChainMeta.stored_ats": + if x.StoredAts == nil { + x.StoredAts = []uint64{} } - value := &_ChainMeta_5_list{list: &x.ObservedAts} + 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")) @@ -533,11 +552,13 @@ func (x *fastReflection_ChainMeta) NewField(fd protoreflect.FieldDescriptor) pro case "uexecutor.v1.ChainMeta.chain_heights": list := []uint64{} return protoreflect.ValueOfList(&_ChainMeta_4_list{list: &list}) - case "uexecutor.v1.ChainMeta.observed_ats": + 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")) @@ -631,9 +652,9 @@ func (x *fastReflection_ChainMeta) ProtoMethods() *protoiface.Methods { } n += 1 + runtime.Sov(uint64(l)) + l } - if len(x.ObservedAts) > 0 { + if len(x.StoredAts) > 0 { l = 0 - for _, e := range x.ObservedAts { + for _, e := range x.StoredAts { l += runtime.Sov(uint64(e)) } n += 1 + runtime.Sov(uint64(l)) + l @@ -641,6 +662,9 @@ func (x *fastReflection_ChainMeta) ProtoMethods() *protoiface.Methods { 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) } @@ -670,19 +694,24 @@ func (x *fastReflection_ChainMeta) ProtoMethods() *protoiface.Methods { 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.ObservedAts) > 0 { + if len(x.StoredAts) > 0 { var pksize2 int - for _, num := range x.ObservedAts { + for _, num := range x.StoredAts { pksize2 += runtime.Sov(uint64(num)) } i -= pksize2 j1 := i - for _, num := range x.ObservedAts { + for _, num := range x.StoredAts { for num >= 1<<7 { dAtA[j1] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 @@ -1033,7 +1062,7 @@ func (x *fastReflection_ChainMeta) ProtoMethods() *protoiface.Methods { break } } - x.ObservedAts = append(x.ObservedAts, v) + x.StoredAts = append(x.StoredAts, v) } else if wireType == 2 { var packedLen int for shift := uint(0); ; shift += 7 { @@ -1068,8 +1097,8 @@ func (x *fastReflection_ChainMeta) ProtoMethods() *protoiface.Methods { } } elementCount = count - if elementCount != 0 && len(x.ObservedAts) == 0 { - x.ObservedAts = make([]uint64, 0, elementCount) + if elementCount != 0 && len(x.StoredAts) == 0 { + x.StoredAts = make([]uint64, 0, elementCount) } for iNdEx < postIndex { var v uint64 @@ -1087,10 +1116,10 @@ func (x *fastReflection_ChainMeta) ProtoMethods() *protoiface.Methods { break } } - x.ObservedAts = append(x.ObservedAts, v) + x.StoredAts = append(x.StoredAts, v) } } else { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ObservedAts", wireType) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field StoredAts", wireType) } case 6: if wireType != 0 { @@ -1111,6 +1140,25 @@ func (x *fastReflection_ChainMeta) ProtoMethods() *protoiface.Methods { 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:]) @@ -1165,12 +1213,13 @@ type ChainMeta struct { 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 - ObservedAts []uint64 `protobuf:"varint,5,rep,packed,name=observed_ats,json=observedAts,proto3" json:"observed_ats,omitempty"` // Timestamps when each observation was made - MedianIndex uint64 `protobuf:"varint,6,opt,name=median_index,json=medianIndex,proto3" json:"median_index,omitempty"` // Index of the median price in 'prices' + 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() { @@ -1221,9 +1270,9 @@ func (x *ChainMeta) GetChainHeights() []uint64 { return nil } -func (x *ChainMeta) GetObservedAts() []uint64 { +func (x *ChainMeta) GetStoredAts() []uint64 { if x != nil { - return x.ObservedAts + return x.StoredAts } return nil } @@ -1235,6 +1284,13 @@ func (x *ChainMeta) GetMedianIndex() uint64 { 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{ @@ -1243,7 +1299,7 @@ var file_uexecutor_v1_chain_meta_proto_rawDesc = []byte{ 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, 0xf7, 0x01, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, + 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, @@ -1252,26 +1308,29 @@ var file_uexecutor_v1_chain_meta_proto_rawDesc = []byte{ 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, 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0b, 0x6f, - 0x62, 0x73, 0x65, 0x72, 0x76, 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, 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, + 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 ( diff --git a/api/uexecutor/v1/tx.pulsar.go b/api/uexecutor/v1/tx.pulsar.go index 2a936b32..94d580ea 100644 --- a/api/uexecutor/v1/tx.pulsar.go +++ b/api/uexecutor/v1/tx.pulsar.go @@ -5647,7 +5647,6 @@ var ( fd_MsgVoteChainMeta_observed_chain_id protoreflect.FieldDescriptor fd_MsgVoteChainMeta_price protoreflect.FieldDescriptor fd_MsgVoteChainMeta_chain_height protoreflect.FieldDescriptor - fd_MsgVoteChainMeta_observed_at protoreflect.FieldDescriptor ) func init() { @@ -5657,7 +5656,6 @@ func init() { 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") - fd_MsgVoteChainMeta_observed_at = md_MsgVoteChainMeta.Fields().ByName("observed_at") } var _ protoreflect.Message = (*fastReflection_MsgVoteChainMeta)(nil) @@ -5749,12 +5747,6 @@ func (x *fastReflection_MsgVoteChainMeta) Range(f func(protoreflect.FieldDescrip return } } - if x.ObservedAt != uint64(0) { - value := protoreflect.ValueOfUint64(x.ObservedAt) - if !f(fd_MsgVoteChainMeta_observed_at, value) { - return - } - } } // Has reports whether a field is populated. @@ -5778,8 +5770,6 @@ func (x *fastReflection_MsgVoteChainMeta) Has(fd protoreflect.FieldDescriptor) b return x.Price != uint64(0) case "uexecutor.v1.MsgVoteChainMeta.chain_height": return x.ChainHeight != uint64(0) - case "uexecutor.v1.MsgVoteChainMeta.observed_at": - return x.ObservedAt != uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) @@ -5804,8 +5794,6 @@ func (x *fastReflection_MsgVoteChainMeta) Clear(fd protoreflect.FieldDescriptor) x.Price = uint64(0) case "uexecutor.v1.MsgVoteChainMeta.chain_height": x.ChainHeight = uint64(0) - case "uexecutor.v1.MsgVoteChainMeta.observed_at": - x.ObservedAt = uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) @@ -5834,9 +5822,6 @@ func (x *fastReflection_MsgVoteChainMeta) Get(descriptor protoreflect.FieldDescr case "uexecutor.v1.MsgVoteChainMeta.chain_height": value := x.ChainHeight return protoreflect.ValueOfUint64(value) - case "uexecutor.v1.MsgVoteChainMeta.observed_at": - value := x.ObservedAt - return protoreflect.ValueOfUint64(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) @@ -5865,8 +5850,6 @@ func (x *fastReflection_MsgVoteChainMeta) Set(fd protoreflect.FieldDescriptor, v x.Price = value.Uint() case "uexecutor.v1.MsgVoteChainMeta.chain_height": x.ChainHeight = value.Uint() - case "uexecutor.v1.MsgVoteChainMeta.observed_at": - x.ObservedAt = value.Uint() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) @@ -5895,8 +5878,6 @@ func (x *fastReflection_MsgVoteChainMeta) Mutable(fd protoreflect.FieldDescripto 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")) - case "uexecutor.v1.MsgVoteChainMeta.observed_at": - panic(fmt.Errorf("field observed_at 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")) @@ -5918,8 +5899,6 @@ func (x *fastReflection_MsgVoteChainMeta) NewField(fd protoreflect.FieldDescript return protoreflect.ValueOfUint64(uint64(0)) case "uexecutor.v1.MsgVoteChainMeta.chain_height": return protoreflect.ValueOfUint64(uint64(0)) - case "uexecutor.v1.MsgVoteChainMeta.observed_at": - return protoreflect.ValueOfUint64(uint64(0)) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.MsgVoteChainMeta")) @@ -6003,9 +5982,6 @@ func (x *fastReflection_MsgVoteChainMeta) ProtoMethods() *protoiface.Methods { if x.ChainHeight != 0 { n += 1 + runtime.Sov(uint64(x.ChainHeight)) } - if x.ObservedAt != 0 { - n += 1 + runtime.Sov(uint64(x.ObservedAt)) - } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -6035,11 +6011,6 @@ func (x *fastReflection_MsgVoteChainMeta) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if x.ObservedAt != 0 { - i = runtime.EncodeVarint(dAtA, i, uint64(x.ObservedAt)) - i-- - dAtA[i] = 0x28 - } if x.ChainHeight != 0 { i = runtime.EncodeVarint(dAtA, i, uint64(x.ChainHeight)) i-- @@ -6215,25 +6186,6 @@ func (x *fastReflection_MsgVoteChainMeta) ProtoMethods() *protoiface.Methods { break } } - case 5: - if wireType != 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ObservedAt", wireType) - } - x.ObservedAt = 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.ObservedAt |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -7157,7 +7109,6 @@ type MsgVoteChainMeta struct { 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 - ObservedAt uint64 `protobuf:"varint,5,opt,name=observed_at,json=observedAt,proto3" json:"observed_at,omitempty"` // Timestamp when the observation was made (unix seconds) } func (x *MsgVoteChainMeta) Reset() { @@ -7208,13 +7159,6 @@ func (x *MsgVoteChainMeta) GetChainHeight() uint64 { return 0 } -func (x *MsgVoteChainMeta) GetObservedAt() uint64 { - if x != nil { - return x.ObservedAt - } - return 0 -} - // MsgVoteChainMetaResponse defines the response for MsgVoteChainMeta type MsgVoteChainMetaResponse struct { state protoimpl.MessageState @@ -7353,7 +7297,7 @@ var file_uexecutor_v1_tx_proto_rawDesc = []byte{ 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, 0xf6, 0x01, 0x0a, 0x10, 0x4d, 0x73, + 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, @@ -7364,64 +7308,61 @@ var file_uexecutor_v1_tx_proto_rawDesc = []byte{ 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, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x6f, 0x62, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x64, 0x41, 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, + 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, 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, + 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, 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, + 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, 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, + 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 ( From 58cb02a8093cbb73a8d95496ed1376ab7287570f Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 18:02:33 +0530 Subject: [PATCH 70/75] feat: added implementation for setChainMeta changes of observedAt removal --- app/upgrades/chain-meta/upgrade.go | 3 +- x/uexecutor/keeper/chain_meta.go | 176 ++++++++++++++++------------- x/uexecutor/keeper/evm.go | 5 +- x/uexecutor/keeper/gas_price.go | 52 --------- x/uexecutor/keeper/msg_server.go | 2 +- x/uexecutor/types/abi.go | 3 +- x/uexecutor/types/chain_meta.pb.go | 126 ++++++++++++++------- x/uexecutor/types/constants.go | 5 - 8 files changed, 187 insertions(+), 185 deletions(-) diff --git a/app/upgrades/chain-meta/upgrade.go b/app/upgrades/chain-meta/upgrade.go index eb648e15..c66433f8 100644 --- a/app/upgrades/chain-meta/upgrade.go +++ b/app/upgrades/chain-meta/upgrade.go @@ -56,8 +56,7 @@ func CreateUpgradeHandler( // 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; observedAt is set to 0 as it was not - // tracked previously). + // block heights and median index). logger.Info("Feature: MsgVoteChainMeta added; migrating GasPrices → ChainMetas store (v4 → v5)") // ── Feature 4 ─────────────────────────────────────────────────────────── diff --git a/x/uexecutor/keeper/chain_meta.go b/x/uexecutor/keeper/chain_meta.go index f9fed767..3ec63707 100644 --- a/x/uexecutor/keeper/chain_meta.go +++ b/x/uexecutor/keeper/chain_meta.go @@ -3,6 +3,8 @@ package keeper import ( "context" "errors" + "fmt" + "sort" "cosmossdk.io/collections" sdkerrors "cosmossdk.io/errors" @@ -11,6 +13,10 @@ import ( "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 { @@ -26,28 +32,19 @@ func (k Keeper) SetChainMeta(ctx context.Context, chainID string, chainMeta type return k.ChainMetas.Set(ctx, chainID, chainMeta) } -// isObservedAtStale returns true if observedAt (Unix seconds) is older than -// ObservedAtStalenessThresholdSeconds relative to the current block time. -// When true the data should not be pushed to the UniversalCore contract. -// Returns false when block time is zero or negative (not yet configured). -func isObservedAtStale(sdkCtx sdk.Context, observedAt uint64) bool { - blockTimeUnix := sdkCtx.BlockTime().Unix() - if blockTimeUnix <= 0 { - // Block time not configured (e.g. genesis or test setup) — skip staleness check. - return false - } - blockTimeSec := uint64(blockTimeUnix) - return blockTimeSec > observedAt && - blockTimeSec-observedAt > types.ObservedAtStalenessThresholdSeconds -} - -// VoteChainMeta processes a universal validator's vote on chain metadata (gas price + chain height + observed timestamp). -// It accumulates votes, computes the median price, and calls setChainMeta on the UniversalCore contract. -// If the median observedAt is older than ObservedAtStalenessThresholdSeconds relative to the current -// block time, the EVM contract is NOT updated — all validators are considered stale and retaining -// the last good contract state is preferred over pushing stale data. -func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAddress, observedChainId string, price, blockNumber, observedAt uint64) error { +// 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 { @@ -55,43 +52,44 @@ func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAdd } if !found { - // First vote for this chain - newEntry := types.ChainMeta{ - ObservedChainId: observedChainId, - Signers: []string{universalValidator.String()}, - Prices: []uint64{price}, - ChainHeights: []uint64{blockNumber}, - ObservedAts: []uint64{observedAt}, - MedianIndex: 0, + // 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") } - if isObservedAtStale(sdkCtx, observedAt) { - sdkCtx.Logger().Info("VoteChainMeta: skipping EVM update — single vote is stale", - "chain", observedChainId, "observedAt", observedAt) - return nil - } - - priceBig := math.NewUint(price).BigInt() - chainHeightBig := math.NewUint(blockNumber).BigInt() - observedAtBig := math.NewUint(observedAt).BigInt() - if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, priceBig, chainHeightBig, observedAtBig); evmErr != nil { - return sdkerrors.Wrap(evmErr, "failed to call EVM setChainMeta") - } - return nil } - // Update or insert vote for this validator + // 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.ObservedAts[i] = observedAt + entry.StoredAts[i] = now updated = true break } @@ -101,46 +99,70 @@ func (k Keeper) VoteChainMeta(ctx context.Context, universalValidator sdk.ValAdd entry.Signers = append(entry.Signers, universalValidator.String()) entry.Prices = append(entry.Prices, price) entry.ChainHeights = append(entry.ChainHeights, blockNumber) - entry.ObservedAts = append(entry.ObservedAts, observedAt) + entry.StoredAts = append(entry.StoredAts, now) } - // Recompute median: filter out stale validators first, then median on price. - // Staleness is measured by observedAt (Unix seconds) — chain-agnostic. - // See computeMedianIndexFiltered for the two-step algorithm. - medianIdx := computeMedianIndexFiltered(entry.Prices, entry.ObservedAts) - entry.MedianIndex = uint64(medianIdx) - - if err := k.SetChainMeta(ctx, observedChainId, entry); err != nil { - return sdkerrors.Wrap(err, "failed to set updated chain meta entry") + // 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 the median observedAt is stale relative to the current block time, all - // validators are considered offline/lagging. Skip the EVM update so the - // contract retains its last known good value rather than being overwritten - // with stale data. - medianObservedAt := entry.ObservedAts[medianIdx] - if isObservedAtStale(sdkCtx, medianObservedAt) { - sdkCtx.Logger().Info("VoteChainMeta: skipping EVM update — all validators stale", - "chain", observedChainId, "medianObservedAt", medianObservedAt) + 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 } - // Use the full observation tuple from the median-price validator. - // chainHeight and observedAt are NOT independent medians — they are the - // co-indexed values from whichever validator submitted the median price. - medianPrice := math.NewUint(entry.Prices[medianIdx]).BigInt() - coChainHeight := math.NewUint(entry.ChainHeights[medianIdx]).BigInt() - coObservedAt := math.NewUint(medianObservedAt).BigInt() - if _, evmErr := k.CallUniversalCoreSetChainMeta(sdkCtx, observedChainId, medianPrice, coChainHeight, coObservedAt); evmErr != 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; observedAts is set to 0 since the timestamp was not tracked before. +// 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 @@ -149,16 +171,16 @@ func (k Keeper) MigrateGasPricesToChainMeta(ctx context.Context) error { return false, nil // already exists, skip } - observedAts := make([]uint64, len(gp.Prices)) - // observedAts unknown at migration time — leave as 0 + storedAts := make([]uint64, len(gp.Signers)) cm := types.ChainMeta{ - ObservedChainId: gp.ObservedChainId, - Signers: gp.Signers, - Prices: gp.Prices, - ChainHeights: gp.BlockNums, - ObservedAts: observedAts, - MedianIndex: gp.MedianIndex, + 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 { diff --git a/x/uexecutor/keeper/evm.go b/x/uexecutor/keeper/evm.go index 05ec3fc8..f8bcf2d0 100644 --- a/x/uexecutor/keeper/evm.go +++ b/x/uexecutor/keeper/evm.go @@ -316,13 +316,13 @@ func (k Keeper) CallUniversalCoreSetGasPrice( ) } -// Calls UniversalCore Contract to set chain metadata (gas price + chain height + observed timestamp) +// 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, - observedAt *big.Int, ) (*evmtypes.MsgEthereumTxResponse, error) { handlerAddr := common.HexToAddress(uregistrytypes.SYSTEM_CONTRACTS["UNIVERSAL_CORE"].Address) @@ -357,7 +357,6 @@ func (k Keeper) CallUniversalCoreSetChainMeta( chainNamespace, price, chainHeight, - observedAt, ) } diff --git a/x/uexecutor/keeper/gas_price.go b/x/uexecutor/keeper/gas_price.go index e9657ccd..9e80b8e8 100644 --- a/x/uexecutor/keeper/gas_price.go +++ b/x/uexecutor/keeper/gas_price.go @@ -110,55 +110,3 @@ func computeMedianIndex(values []uint64) int { return arr[len(arr)/2].Idx } -// computeMedianIndexFiltered returns the original index (into prices/observedAts) -// of the validator chosen as the representative for VoteChainMeta. The selection -// is a two-step process: -// -// 1. Compute the median of observedAt timestamps across all validators. -// 2. Exclude validators whose observedAt deviates from that median by more than -// ObservedAtStalenessThresholdSeconds (they are considered lagging / stale). -// Using wall-clock seconds is chain-agnostic: it works identically for Solana -// (0.4 s/block) and Bitcoin (600 s/block) without per-chain configuration. -// 3. Among the remaining validators compute the median of prices and return that -// validator's original index. -// -// The returned index is valid for all three parallel slices (prices, chainHeights, -// observedAts), so the caller gets a coherent (price, height, timestamp) tuple -// from a single validator who is both current and representative on price. -// -// If – after filtering – no candidates remain (should not happen with a sensible -// threshold), the function falls back to computeMedianIndex on the full price slice. -func computeMedianIndexFiltered(prices, observedAts []uint64) int { - // Step 1: median observedAt timestamp across all validators - medianObservedAtIdx := computeMedianIndex(observedAts) - medianObservedAt := observedAts[medianObservedAtIdx] - - // Step 2: keep only validators within the staleness threshold (in seconds) - type candidate struct { - originalIdx int - price uint64 - } - var candidates []candidate - for i, ts := range observedAts { - var diff uint64 - if ts >= medianObservedAt { - diff = ts - medianObservedAt - } else { - diff = medianObservedAt - ts - } - if diff <= types.ObservedAtStalenessThresholdSeconds { - candidates = append(candidates, candidate{i, prices[i]}) - } - } - - // Fallback: threshold filtered everyone out (should not happen) - if len(candidates) == 0 { - return computeMedianIndex(prices) - } - - // Step 3: median of prices among current validators - sort.SliceStable(candidates, func(i, j int) bool { - return candidates[i].price < candidates[j].price - }) - return candidates[len(candidates)/2].originalIdx -} diff --git a/x/uexecutor/keeper/msg_server.go b/x/uexecutor/keeper/msg_server.go index ce2d4f4c..c2f97fff 100755 --- a/x/uexecutor/keeper/msg_server.go +++ b/x/uexecutor/keeper/msg_server.go @@ -202,7 +202,7 @@ func (ms msgServer) VoteChainMeta(ctx context.Context, msg *types.MsgVoteChainMe 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, msg.ObservedAt) + err = ms.k.VoteChainMeta(ctx, signerValAddr, msg.ObservedChainId, msg.Price, msg.ChainHeight) if err != nil { return nil, err } diff --git a/x/uexecutor/types/abi.go b/x/uexecutor/types/abi.go index 37587e4a..8b0ef316 100644 --- a/x/uexecutor/types/abi.go +++ b/x/uexecutor/types/abi.go @@ -306,8 +306,7 @@ const UNIVERSAL_CORE_ABI = `[ "inputs": [ { "name": "chainNamespace", "type": "string", "internalType": "string" }, { "name": "price", "type": "uint256", "internalType": "uint256" }, - { "name": "chainHeight", "type": "uint256", "internalType": "uint256" }, - { "name": "observedAt", "type": "uint256", "internalType": "uint256" } + { "name": "chainHeight", "type": "uint256", "internalType": "uint256" } ], "outputs": [], "stateMutability": "nonpayable" diff --git a/x/uexecutor/types/chain_meta.pb.go b/x/uexecutor/types/chain_meta.pb.go index af8df41f..8d40390f 100644 --- a/x/uexecutor/types/chain_meta.pb.go +++ b/x/uexecutor/types/chain_meta.pb.go @@ -26,12 +26,13 @@ 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"` - ObservedAts []uint64 `protobuf:"varint,5,rep,packed,name=observed_ats,json=observedAts,proto3" json:"observed_ats,omitempty"` - MedianIndex uint64 `protobuf:"varint,6,opt,name=median_index,json=medianIndex,proto3" json:"median_index,omitempty"` + 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{} } @@ -94,9 +95,9 @@ func (m *ChainMeta) GetChainHeights() []uint64 { return nil } -func (m *ChainMeta) GetObservedAts() []uint64 { +func (m *ChainMeta) GetStoredAts() []uint64 { if m != nil { - return m.ObservedAts + return m.StoredAts } return nil } @@ -108,6 +109,13 @@ func (m *ChainMeta) GetMedianIndex() uint64 { return 0 } +func (m *ChainMeta) GetLastAppliedChainHeight() uint64 { + if m != nil { + return m.LastAppliedChainHeight + } + return 0 +} + func init() { proto.RegisterType((*ChainMeta)(nil), "uexecutor.v1.ChainMeta") } @@ -115,28 +123,30 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/chain_meta.proto", fileDescriptor_7d3b1b8d71b3d806) } var fileDescriptor_7d3b1b8d71b3d806 = []byte{ - // 324 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2d, 0x4d, 0xad, 0x48, - 0x4d, 0x2e, 0x2d, 0xc9, 0x2f, 0xd2, 0x2f, 0x33, 0xd4, 0x4f, 0xce, 0x48, 0xcc, 0xcc, 0x8b, 0xcf, - 0x4d, 0x2d, 0x49, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x81, 0x4b, 0xeb, 0x95, 0x19, - 0x4a, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x25, 0xf4, 0x41, 0x2c, 0x88, 0x1a, 0x29, 0xc1, 0xc4, - 0xdc, 0xcc, 0xbc, 0x7c, 0x7d, 0x30, 0x09, 0x11, 0x52, 0xfa, 0xce, 0xc8, 0xc5, 0xe9, 0x0c, 0x32, - 0xcb, 0x37, 0xb5, 0x24, 0x51, 0x48, 0x8b, 0x4b, 0x30, 0x3f, 0xa9, 0x38, 0xb5, 0xa8, 0x2c, 0x35, - 0x25, 0x1e, 0x62, 0x43, 0x66, 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3f, 0x4c, 0x02, - 0xac, 0xda, 0x33, 0x45, 0x48, 0x82, 0x8b, 0xbd, 0x38, 0x33, 0x3d, 0x2f, 0xb5, 0xa8, 0x58, 0x82, - 0x49, 0x81, 0x59, 0x83, 0x33, 0x08, 0xc6, 0x15, 0x12, 0xe3, 0x62, 0x2b, 0x28, 0xca, 0x4c, 0x4e, - 0x2d, 0x96, 0x60, 0x56, 0x60, 0xd6, 0x60, 0x09, 0x82, 0xf2, 0x84, 0x94, 0xb9, 0x78, 0x21, 0x86, - 0x66, 0xa4, 0x66, 0xa6, 0x67, 0x94, 0x14, 0x4b, 0xb0, 0x80, 0xa5, 0x79, 0xc0, 0x82, 0x1e, 0x10, - 0x31, 0x21, 0x45, 0x2e, 0x1e, 0xb8, 0x13, 0x12, 0x4b, 0x8a, 0x25, 0x58, 0xc1, 0x6a, 0xb8, 0x61, - 0x62, 0x8e, 0x10, 0x25, 0xb9, 0xa9, 0x29, 0x99, 0x89, 0x79, 0xf1, 0x99, 0x79, 0x29, 0xa9, 0x15, - 0x12, 0x6c, 0x0a, 0x8c, 0x20, 0x25, 0x10, 0x31, 0x4f, 0x90, 0x90, 0x95, 0xe2, 0x8c, 0x05, 0xf2, - 0x0c, 0x2f, 0x16, 0xc8, 0x33, 0x76, 0x3d, 0xdf, 0xa0, 0x25, 0x82, 0x08, 0x39, 0x44, 0xb0, 0x39, - 0x05, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, - 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x59, 0x7a, 0x66, 0x49, - 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x41, 0x69, 0x71, 0x06, 0x58, 0x13, 0x98, 0xa5, - 0x0b, 0x66, 0xea, 0xe6, 0xe5, 0xa7, 0xa4, 0xea, 0x57, 0xe8, 0x23, 0x8c, 0x2d, 0xa9, 0x2c, 0x48, - 0x2d, 0x4e, 0x62, 0x03, 0x07, 0xa9, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x91, 0x64, 0xde, 0x80, - 0xaa, 0x01, 0x00, 0x00, + // 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 { @@ -185,17 +195,20 @@ func (this *ChainMeta) Equal(that interface{}) bool { return false } } - if len(this.ObservedAts) != len(that1.ObservedAts) { + if len(this.StoredAts) != len(that1.StoredAts) { return false } - for i := range this.ObservedAts { - if this.ObservedAts[i] != that1.ObservedAts[i] { + 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) { @@ -218,15 +231,20 @@ func (m *ChainMeta) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = 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.ObservedAts) > 0 { - dAtA2 := make([]byte, len(m.ObservedAts)*10) + if len(m.StoredAts) > 0 { + dAtA2 := make([]byte, len(m.StoredAts)*10) var j1 int - for _, num := range m.ObservedAts { + for _, num := range m.StoredAts { for num >= 1<<7 { dAtA2[j1] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 @@ -337,9 +355,9 @@ func (m *ChainMeta) Size() (n int) { } n += 1 + sovChainMeta(uint64(l)) + l } - if len(m.ObservedAts) > 0 { + if len(m.StoredAts) > 0 { l = 0 - for _, e := range m.ObservedAts { + for _, e := range m.StoredAts { l += sovChainMeta(uint64(e)) } n += 1 + sovChainMeta(uint64(l)) + l @@ -347,6 +365,9 @@ func (m *ChainMeta) Size() (n int) { if m.MedianIndex != 0 { n += 1 + sovChainMeta(uint64(m.MedianIndex)) } + if m.LastAppliedChainHeight != 0 { + n += 1 + sovChainMeta(uint64(m.LastAppliedChainHeight)) + } return n } @@ -618,7 +639,7 @@ func (m *ChainMeta) Unmarshal(dAtA []byte) error { break } } - m.ObservedAts = append(m.ObservedAts, v) + m.StoredAts = append(m.StoredAts, v) } else if wireType == 2 { var packedLen int for shift := uint(0); ; shift += 7 { @@ -653,8 +674,8 @@ func (m *ChainMeta) Unmarshal(dAtA []byte) error { } } elementCount = count - if elementCount != 0 && len(m.ObservedAts) == 0 { - m.ObservedAts = make([]uint64, 0, elementCount) + if elementCount != 0 && len(m.StoredAts) == 0 { + m.StoredAts = make([]uint64, 0, elementCount) } for iNdEx < postIndex { var v uint64 @@ -672,10 +693,10 @@ func (m *ChainMeta) Unmarshal(dAtA []byte) error { break } } - m.ObservedAts = append(m.ObservedAts, v) + m.StoredAts = append(m.StoredAts, v) } } else { - return fmt.Errorf("proto: wrong wireType = %d for field ObservedAts", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field StoredAts", wireType) } case 6: if wireType != 0 { @@ -696,6 +717,25 @@ func (m *ChainMeta) Unmarshal(dAtA []byte) error { 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:]) diff --git a/x/uexecutor/types/constants.go b/x/uexecutor/types/constants.go index 0f8ef682..d125e3b8 100644 --- a/x/uexecutor/types/constants.go +++ b/x/uexecutor/types/constants.go @@ -40,11 +40,6 @@ const ( // Default number of blocks after which ballot expires DefaultExpiryAfterBlocks = 10000 - - // ObservedAtStalenessThresholdSeconds is the maximum number of seconds a - // validator's observedAt timestamp may deviate from the median observedAt before - // its price vote is excluded from the median price computation in VoteChainMeta. - ObservedAtStalenessThresholdSeconds uint64 = 300 ) var UniversalTxOutboundEventSig = crypto.Keccak256Hash([]byte( From 7aa0a52152cf2c4e0bd134817c6bc39753240769 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 18:02:40 +0530 Subject: [PATCH 71/75] refactor: added generated protobuf --- x/uexecutor/types/tx.pb.go | 150 ++++++++++++++----------------------- 1 file changed, 57 insertions(+), 93 deletions(-) diff --git a/x/uexecutor/types/tx.pb.go b/x/uexecutor/types/tx.pb.go index 075e0d32..58a2a46d 100644 --- a/x/uexecutor/types/tx.pb.go +++ b/x/uexecutor/types/tx.pb.go @@ -660,7 +660,6 @@ type MsgVoteChainMeta struct { 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"` - ObservedAt uint64 `protobuf:"varint,5,opt,name=observed_at,json=observedAt,proto3" json:"observed_at,omitempty"` } func (m *MsgVoteChainMeta) Reset() { *m = MsgVoteChainMeta{} } @@ -724,13 +723,6 @@ func (m *MsgVoteChainMeta) GetChainHeight() uint64 { return 0 } -func (m *MsgVoteChainMeta) GetObservedAt() uint64 { - if m != nil { - return m.ObservedAt - } - return 0 -} - // MsgVoteChainMetaResponse defines the response for MsgVoteChainMeta type MsgVoteChainMetaResponse struct { } @@ -788,65 +780,64 @@ func init() { func init() { proto.RegisterFile("uexecutor/v1/tx.proto", fileDescriptor_88d6216044506365) } var fileDescriptor_88d6216044506365 = []byte{ - // 926 bytes of a gzipped FileDescriptorProto + // 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, 0xa4, 0xa8, 0x2f, 0xdd, 0xdd, 0xc6, 0xa4, 0xd4, 0x75, 0xb7, 0x69, 0x1b, 0x7e, - 0xec, 0x92, 0xa5, 0x31, 0x5b, 0xa4, 0x3d, 0xe4, 0xd6, 0xc2, 0x0a, 0x2a, 0x94, 0xdd, 0x62, 0x5a, - 0x90, 0xf6, 0x12, 0x4d, 0xec, 0xc1, 0xb1, 0xa8, 0x3d, 0x96, 0x67, 0x1c, 0xa5, 0x37, 0xc4, 0x91, - 0x13, 0x27, 0xfe, 0x07, 0xc4, 0xa5, 0x07, 0xfe, 0x00, 0x8e, 0x7b, 0x5c, 0xc1, 0x85, 0xd3, 0x0a, - 0xb5, 0x12, 0xfd, 0x0f, 0x38, 0x23, 0x8f, 0xed, 0xb1, 0xc7, 0xc9, 0xa6, 0xa8, 0x17, 0xf6, 0x12, - 0x39, 0xdf, 0xf7, 0xde, 0x97, 0xf7, 0x7d, 0xf6, 0x3c, 0x07, 0x56, 0x23, 0x3c, 0xc6, 0x56, 0xc4, - 0x48, 0x68, 0x8c, 0x1e, 0x1a, 0x6c, 0xdc, 0x09, 0x42, 0xc2, 0x88, 0xba, 0x2c, 0xe0, 0xce, 0xe8, - 0xa1, 0x5e, 0x47, 0x9e, 0xeb, 0x13, 0x83, 0x7f, 0x26, 0x05, 0xfa, 0x9a, 0x45, 0xa8, 0x47, 0xa8, - 0xe1, 0x51, 0x27, 0x6e, 0xf4, 0xa8, 0x93, 0x12, 0x9a, 0x2c, 0x78, 0x16, 0x60, 0x9a, 0x32, 0x9b, - 0x12, 0x63, 0x0d, 0x91, 0xeb, 0xf7, 0x3d, 0xcc, 0x50, 0x4a, 0x37, 0x1c, 0xe2, 0x10, 0x7e, 0x69, - 0xc4, 0x57, 0x29, 0xba, 0x9e, 0xfc, 0x4e, 0x3f, 0x21, 0x92, 0x2f, 0x09, 0xd5, 0xfa, 0x45, 0x81, - 0x3b, 0x3d, 0xea, 0x9c, 0x04, 0x36, 0x62, 0xf8, 0x08, 0x85, 0xc8, 0xa3, 0xea, 0x23, 0x58, 0x42, - 0x11, 0x1b, 0x92, 0xd0, 0x65, 0x67, 0x9a, 0xb2, 0xad, 0xdc, 0x5f, 0x3a, 0xd0, 0x7e, 0xff, 0x75, - 0xb7, 0x91, 0x36, 0xee, 0xdb, 0x76, 0x88, 0x29, 0xfd, 0x92, 0x85, 0xae, 0xef, 0x98, 0x79, 0xa9, - 0xba, 0x07, 0x8b, 0x01, 0x57, 0xd0, 0xe6, 0xb7, 0x95, 0xfb, 0xb5, 0xbd, 0x46, 0xa7, 0x18, 0x40, - 0x27, 0x51, 0x3f, 0xa8, 0x3c, 0x7f, 0xb9, 0x35, 0x67, 0xa6, 0x95, 0xdd, 0x0f, 0xbe, 0xbf, 0x3a, - 0x6f, 0xe7, 0x1a, 0x3f, 0x5c, 0x9d, 0xb7, 0xd7, 0x73, 0x8b, 0xa5, 0xc9, 0x5a, 0xeb, 0xb0, 0x56, - 0x82, 0x4c, 0x4c, 0x03, 0xe2, 0x53, 0xdc, 0xfa, 0x6d, 0x1e, 0xea, 0x3d, 0xea, 0x3c, 0xe6, 0xad, - 0xf8, 0x08, 0x9d, 0x9d, 0x12, 0x64, 0xab, 0x1f, 0xc2, 0x22, 0x75, 0x1d, 0x1f, 0x87, 0xd7, 0xfa, - 0x48, 0xeb, 0x54, 0x13, 0x1a, 0x91, 0xef, 0x8e, 0x70, 0x48, 0xd1, 0x69, 0x1f, 0x59, 0x16, 0x89, - 0x7c, 0xd6, 0x77, 0xed, 0xd4, 0xd2, 0xb6, 0x6c, 0xe9, 0x24, 0xab, 0xdc, 0x4f, 0x0a, 0x0f, 0x6d, - 0x53, 0x8d, 0x26, 0x30, 0xf5, 0x73, 0xa8, 0xe7, 0x9a, 0x41, 0x32, 0x9a, 0xb6, 0xc0, 0x05, 0x9b, - 0xaf, 0x10, 0x4c, 0x0d, 0x98, 0x2b, 0x51, 0x09, 0x51, 0x1f, 0x40, 0x7d, 0x84, 0x43, 0xf7, 0x1b, - 0xd7, 0x42, 0xcc, 0x25, 0x7e, 0xdf, 0x46, 0x0c, 0x69, 0x95, 0xd8, 0x9d, 0xb9, 0x52, 0x24, 0x3e, - 0x41, 0x0c, 0x75, 0x1f, 0xc4, 0xf1, 0xa6, 0xd6, 0xe2, 0x6c, 0x37, 0xa4, 0x6c, 0xe5, 0xb0, 0x5a, - 0x1b, 0xb0, 0x3e, 0x01, 0x8a, 0x7c, 0x7f, 0x9e, 0x87, 0x5b, 0x3d, 0xea, 0xf4, 0x5c, 0x27, 0x44, - 0x0c, 0x9f, 0x3c, 0xde, 0x7f, 0x7d, 0xb2, 0xf5, 0xf8, 0x4c, 0x71, 0x16, 0x33, 0xb3, 0xed, 0x65, - 0x65, 0x22, 0x5b, 0xaf, 0x84, 0xa8, 0x77, 0x61, 0x29, 0x1e, 0x15, 0xb1, 0x28, 0xc4, 0x69, 0xa6, - 0x39, 0xd0, 0xbd, 0x57, 0x0a, 0x73, 0x4d, 0x0a, 0x33, 0x4f, 0xa6, 0xb5, 0x06, 0xab, 0x12, 0x20, - 0x42, 0xfc, 0x49, 0x81, 0xdb, 0x3d, 0xea, 0x7c, 0x45, 0x18, 0x3e, 0xf4, 0x07, 0x24, 0xf2, 0x6f, - 0xf2, 0x84, 0x1a, 0xf0, 0x86, 0x9b, 0x34, 0xa7, 0xc1, 0xad, 0xca, 0x3e, 0x53, 0x65, 0x33, 0xab, - 0xea, 0xee, 0x94, 0xe6, 0xae, 0x47, 0xd8, 0x90, 0xa7, 0x68, 0x69, 0xf0, 0x96, 0x8c, 0x88, 0x91, - 0x5f, 0x26, 0x0b, 0x22, 0xa6, 0x9e, 0x46, 0xec, 0xa6, 0x33, 0xbf, 0x09, 0x55, 0x36, 0xce, 0x6e, - 0xf5, 0x92, 0x59, 0x61, 0xe3, 0x43, 0x5b, 0x5d, 0x85, 0xc5, 0x28, 0x41, 0x17, 0x38, 0x5a, 0x8d, - 0x38, 0x7c, 0x00, 0x35, 0x32, 0xa0, 0x38, 0x1c, 0x61, 0xbb, 0xcf, 0xc6, 0xfc, 0x36, 0xd4, 0xf6, - 0x76, 0x64, 0x8f, 0xd9, 0x28, 0x4f, 0x79, 0x21, 0xbf, 0x87, 0x26, 0x64, 0x5d, 0xc7, 0xe3, 0xee, - 0xfb, 0x25, 0xcb, 0xf2, 0x4e, 0x29, 0x9a, 0x49, 0x77, 0x4a, 0x11, 0x12, 0xde, 0xff, 0xc8, 0xbd, - 0x7f, 0x8a, 0xe8, 0x51, 0xe8, 0x5a, 0xf8, 0x06, 0xde, 0xdb, 0x50, 0x17, 0x7e, 0x92, 0x85, 0x2d, - 0x72, 0xb8, 0x93, 0x11, 0x1f, 0xc7, 0xf8, 0xa1, 0xad, 0x36, 0xa0, 0x1a, 0xc4, 0x3f, 0xc3, 0x13, - 0xa9, 0x98, 0xc9, 0x17, 0x75, 0x07, 0x96, 0x07, 0xa7, 0xc4, 0xfa, 0xb6, 0xef, 0x47, 0xde, 0x00, - 0x87, 0x3c, 0x92, 0x8a, 0x59, 0xe3, 0xd8, 0x13, 0x0e, 0xfd, 0x07, 0xc3, 0x99, 0x83, 0x82, 0xe1, - 0x0c, 0x12, 0x86, 0xff, 0x51, 0x60, 0x25, 0xe5, 0xf8, 0x44, 0x3d, 0xcc, 0xd0, 0xff, 0xe5, 0x38, - 0x69, 0x1c, 0x62, 0xd7, 0x19, 0xb2, 0xcc, 0x31, 0xc7, 0x3e, 0xe3, 0x90, 0xba, 0x55, 0x78, 0x4c, - 0x10, 0xd3, 0xaa, 0xbc, 0x42, 0x3c, 0x03, 0xfb, 0xac, 0xdb, 0x2e, 0x45, 0xa2, 0x4f, 0x44, 0x22, - 0x3c, 0xb6, 0x74, 0xd0, 0xca, 0x58, 0x16, 0xca, 0xde, 0xdf, 0x15, 0x58, 0xe8, 0x51, 0x47, 0x3d, - 0x86, 0x65, 0xe9, 0x35, 0xb9, 0x59, 0x5a, 0x2f, 0xf2, 0x8b, 0x49, 0x7f, 0x77, 0x26, 0x9d, 0xa9, - 0xab, 0xcf, 0xe0, 0x76, 0xe9, 0x9d, 0xb5, 0x35, 0xd1, 0x28, 0x17, 0xe8, 0xf7, 0xae, 0x29, 0x10, - 0xda, 0x4f, 0x00, 0x0a, 0xfb, 0x7a, 0x63, 0xa2, 0x2d, 0x27, 0xf5, 0xb7, 0x67, 0x90, 0x42, 0xef, - 0x0b, 0xa8, 0x15, 0x57, 0xd7, 0xdd, 0x89, 0x9e, 0x02, 0xab, 0xbf, 0x33, 0x8b, 0x15, 0x92, 0xc7, - 0xb0, 0x2c, 0xad, 0x96, 0xcd, 0xa9, 0x5d, 0x19, 0x3d, 0x25, 0xd4, 0x69, 0x07, 0x37, 0x53, 0x15, - 0x87, 0x76, 0xba, 0x6a, 0x46, 0xbf, 0x42, 0xb5, 0x7c, 0x3a, 0xd4, 0xaf, 0xe1, 0x96, 0x7c, 0x32, - 0x9a, 0x53, 0xfb, 0x04, 0xaf, 0xbf, 0x37, 0x9b, 0xcf, 0x84, 0xf5, 0xea, 0x77, 0x57, 0xe7, 0x6d, - 0xe5, 0xe0, 0xe8, 0xf9, 0x45, 0x53, 0x79, 0x71, 0xd1, 0x54, 0xfe, 0xba, 0x68, 0x2a, 0x3f, 0x5e, - 0x36, 0xe7, 0x5e, 0x5c, 0x36, 0xe7, 0xfe, 0xbc, 0x6c, 0xce, 0x3d, 0x7b, 0xe4, 0xb8, 0x6c, 0x18, - 0x0d, 0x3a, 0x16, 0xf1, 0x8c, 0x20, 0xa2, 0x43, 0x7e, 0x0e, 0xf8, 0xd5, 0x2e, 0xbf, 0xdc, 0xf5, - 0x89, 0x8d, 0x8d, 0xb1, 0x91, 0x3f, 0xe1, 0xfc, 0x3f, 0xe3, 0x60, 0x91, 0xff, 0xc9, 0xfb, 0xe8, - 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x21, 0xaa, 0x85, 0x4a, 0xa1, 0x0a, 0x00, 0x00, + 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. @@ -1628,11 +1619,6 @@ func (m *MsgVoteChainMeta) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.ObservedAt != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.ObservedAt)) - i-- - dAtA[i] = 0x28 - } if m.ChainHeight != 0 { i = encodeVarintTx(dAtA, i, uint64(m.ChainHeight)) i-- @@ -1898,9 +1884,6 @@ func (m *MsgVoteChainMeta) Size() (n int) { if m.ChainHeight != 0 { n += 1 + sovTx(uint64(m.ChainHeight)) } - if m.ObservedAt != 0 { - n += 1 + sovTx(uint64(m.ObservedAt)) - } return n } @@ -3289,25 +3272,6 @@ func (m *MsgVoteChainMeta) Unmarshal(dAtA []byte) error { break } } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ObservedAt", wireType) - } - m.ObservedAt = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.ObservedAt |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) From 099578d9cd09553a38022c8156cce39d9a18764d Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 18:02:59 +0530 Subject: [PATCH 72/75] tests: updated test cases of chain meta changes --- .../uexecutor/query_chain_meta_test.go | 10 +- .../uexecutor/vote_chain_meta_test.go | 334 +++++------------- test/utils/bytecode.go | 2 +- test/utils/helpers.go | 2 - 4 files changed, 101 insertions(+), 247 deletions(-) diff --git a/test/integration/uexecutor/query_chain_meta_test.go b/test/integration/uexecutor/query_chain_meta_test.go index 2e63dbc5..188302ad 100644 --- a/test/integration/uexecutor/query_chain_meta_test.go +++ b/test/integration/uexecutor/query_chain_meta_test.go @@ -42,8 +42,8 @@ func TestQueryChainMeta(t *testing.T) { 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, 1700000000)) - require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[1], sdk.AccAddress(coreVal1).String(), chainId, 200_000_000_000, 12346, 1700000001)) + 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}) @@ -52,7 +52,7 @@ func TestQueryChainMeta(t *testing.T) { 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.ObservedAts, 2) + require.Len(t, resp.ChainMeta.ChainHeights, 2) }) t.Run("all chain metas returns empty when nothing stored", func(t *testing.T) { @@ -72,7 +72,6 @@ func TestQueryChainMeta(t *testing.T) { Signers: []string{"cosmos1abc"}, Prices: []uint64{100}, ChainHeights: []uint64{1}, - ObservedAts: []uint64{0}, MedianIndex: 0, })) require.NoError(t, testApp.UexecutorKeeper.SetChainMeta(ctx, chainId2, uexecutortypes.ChainMeta{ @@ -80,7 +79,6 @@ func TestQueryChainMeta(t *testing.T) { Signers: []string{"cosmos1def"}, Prices: []uint64{200}, ChainHeights: []uint64{2}, - ObservedAts: []uint64{0}, MedianIndex: 0, })) @@ -103,7 +101,6 @@ func TestQueryGasPriceFromChainMeta(t *testing.T) { Signers: []string{"cosmos1abc", "cosmos1def"}, Prices: []uint64{100_000_000_000, 200_000_000_000}, ChainHeights: []uint64{12345, 12346}, - ObservedAts: []uint64{17000000, 17000001}, MedianIndex: 1, })) @@ -143,7 +140,6 @@ func TestQueryGasPriceFromChainMeta(t *testing.T) { ObservedChainId: chainId, Prices: []uint64{100}, ChainHeights: []uint64{1}, - ObservedAts: []uint64{0}, MedianIndex: 0, })) diff --git a/test/integration/uexecutor/vote_chain_meta_test.go b/test/integration/uexecutor/vote_chain_meta_test.go index 8c4b1d45..96cb1b02 100644 --- a/test/integration/uexecutor/vote_chain_meta_test.go +++ b/test/integration/uexecutor/vote_chain_meta_test.go @@ -64,7 +64,7 @@ func TestVoteChainMetaIntegration(t *testing.T) { require.NoError(t, err) coreAcc := sdk.AccAddress(coreVal).String() - err = utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 100_000_000_000, 12345, 1700000000) + 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) @@ -74,30 +74,31 @@ func TestVoteChainMetaIntegration(t *testing.T) { 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.ObservedAts, 1) - require.Equal(t, uint64(1700000000), stored.ObservedAts[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 median calculated", func(t *testing.T) { + 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 - observedAt uint64 + uniVal string + price uint64 + height uint64 }{ - {uvals[0], 300_000_000_000, 12345, 1700000001}, - {uvals[1], 200_000_000_000, 12346, 1700000002}, - {uvals[2], 400_000_000_000, 12347, 1700000003}, - {uvals[3], 250_000_000_000, 12348, 1700000004}, + {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, v.observedAt) + err = utils.ExecVoteChainMeta(t, ctx, testApp, v.uniVal, coreAcc, chainId, v.price, v.height) require.NoError(t, err) } @@ -106,11 +107,11 @@ func TestVoteChainMetaIntegration(t *testing.T) { require.True(t, found) require.Len(t, stored.Prices, 4) require.Len(t, stored.ChainHeights, 4) - require.Len(t, stored.ObservedAts, 4) + require.Len(t, stored.StoredAts, 4) - median := stored.Prices[stored.MedianIndex] - // sorted: 200, 250, 300, 400 → median at index 2 → 300 - require.Equal(t, uint64(300_000_000_000), median) + // 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) { @@ -120,9 +121,9 @@ func TestVoteChainMetaIntegration(t *testing.T) { 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, 1700000000)) - // Update same validator's vote - require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 400_000_000_000, 12350, 1700000100)) + 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) @@ -130,182 +131,123 @@ func TestVoteChainMetaIntegration(t *testing.T) { 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]) - require.Equal(t, uint64(1700000100), stored.ObservedAts[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, uint64(i+1), uint64(1700000000+i))) + 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) }) -} -// TestVoteChainMetaStalenessFilter verifies that validators whose observedAt timestamp -// deviates from the median by more than ObservedAtStalenessThresholdSeconds are excluded -// from the price median computation. -// Using wall-clock seconds (observedAt) is chain-agnostic: it works identically for -// Solana (0.4 s/block) and Bitcoin (600 s/block) without per-chain configuration. -func TestVoteChainMetaStalenessFilter(t *testing.T) { - t.Parallel() - chainId := "eip155:11155111" - // threshold in seconds (300s = 5 minutes) - threshold := uexecutortypes.ObservedAtStalenessThresholdSeconds + t.Run("vote rejected when chain height not greater than last applied", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 1) - t.Run("stale validator excluded when observedAt beyond staleness threshold", func(t *testing.T) { - testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 3) + coreVal, err := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + require.NoError(t, err) + coreAcc := sdk.AccAddress(coreVal).String() - // Base timestamp for "current" validators. - baseTs := uint64(1_700_000_000) - // val0: current (ts=baseTs, price=200, height=1000) - // val1: stale (ts=baseTs-threshold-5, price=250, height=900) → must be excluded - // val2: current (ts=baseTs+1, price=300, height=1001) - // - // Median observedAt = baseTs. - // val1 diff = baseTs - (baseTs-threshold-5) = threshold+5 > threshold → excluded. - // - // Without filtering: sorted prices [200, 250, 300] → median=250 (stale val1) - // With filtering: val1 excluded sorted [200, 300] → median=300 (val2) - staleTs := baseTs - threshold - 5 - votes := []struct { - price uint64 - height uint64 - observedAt uint64 - }{ - {200, 1000, baseTs}, - {250, 900, staleTs}, // stale - {300, 1001, baseTs + 1}, - } + // First vote — establishes lastAppliedChainHeight=100 + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 100_000_000_000, 100)) - for i, v := range votes { - coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) - coreAcc := sdk.AccAddress(coreVal).String() - require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) - } + // 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") - stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) - require.NoError(t, err) - require.True(t, found) + // 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") - // The chosen validator must NOT be the stale one. - // With filtering the median price is 300 (val2, height=1001). - require.Equal(t, uint64(300), stored.Prices[stored.MedianIndex], - "median price should come from a current validator, not the stale one") - require.Equal(t, uint64(1001), stored.ChainHeights[stored.MedianIndex], - "co-indexed height must be from a current validator") + // Higher height → accepted + require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, 200_000_000_000, 101)) }) - t.Run("validator exactly at threshold boundary is included", func(t *testing.T) { + t.Run("stale votes excluded from median", func(t *testing.T) { testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 3) - baseTs := uint64(1_700_000_000) - // val1 is exactly threshold seconds behind the median → diff == threshold → included (<=) - exactBoundaryTs := baseTs - threshold - votes := []struct { - price uint64 - height uint64 - observedAt uint64 - }{ - {200, 1000, baseTs}, - {250, 990, exactBoundaryTs}, // diff == threshold → still included - {300, 1001, baseTs + 1}, - } - - for i, v := range votes { + coreAccs := make([]string, 3) + for i := range vals { coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) - coreAcc := sdk.AccAddress(coreVal).String() - require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) + coreAccs[i] = sdk.AccAddress(coreVal).String() } - stored, found, err := testApp.UexecutorKeeper.GetChainMeta(ctx, chainId) - require.NoError(t, err) - require.True(t, found) + // 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)) - // All three included → sorted prices [200, 250, 300] → median = 250 (val1) - require.Equal(t, uint64(250), stored.Prices[stored.MedianIndex], - "boundary validator should be included in median computation") - }) + // 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) - t.Run("all validators current: filtering does not change median", func(t *testing.T) { - testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 4) + // Advance block time by 301 seconds — old votes become stale. + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(301 * time.Second)) - // All timestamps are close together (within threshold). - // Result must match an unfiltered median. - baseTs := uint64(1_700_000_000) - votes := []struct { - price uint64 - height uint64 - observedAt uint64 - }{ - {300, 1000, baseTs}, - {200, 1001, baseTs + 1}, - {400, 1002, baseTs + 2}, - {250, 999, baseTs - 1}, - } - - for i, v := range votes { - coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) - coreAcc := sdk.AccAddress(coreVal).String() - require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) - } + // 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) - // All current → sorted [200, 250, 300, 400] → upper-median (index 2) = 300 - require.Equal(t, uint64(300), stored.Prices[stored.MedianIndex]) - // Co-indexed height must belong to the same validator (height=1000) - require.Equal(t, uint64(1000), stored.ChainHeights[stored.MedianIndex]) + // 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("multiple stale validators excluded, median from current set", func(t *testing.T) { - testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 5) + t.Run("last applied chain height updated after EVM call", func(t *testing.T) { + testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 2) - // 3 current validators, 2 stale (observedAt > threshold seconds behind) - baseTs := uint64(1_700_000_000) - staleTs := baseTs - threshold - 10 - votes := []struct { - price uint64 - height uint64 - observedAt uint64 - }{ - {500, 1000, baseTs}, // current - {100, 800, staleTs}, // stale → excluded - {300, 1001, baseTs + 1}, // current - {150, 810, staleTs}, // stale → excluded - {200, 1002, baseTs + 2}, // current - } + coreVal0, _ := sdk.ValAddressFromBech32(vals[0].OperatorAddress) + coreVal1, _ := sdk.ValAddressFromBech32(vals[1].OperatorAddress) + coreAcc0 := sdk.AccAddress(coreVal0).String() + coreAcc1 := sdk.AccAddress(coreVal1).String() - for i, v := range votes { - coreVal, _ := sdk.ValAddressFromBech32(vals[i].OperatorAddress) - coreAcc := sdk.AccAddress(coreVal).String() - require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[i], coreAcc, chainId, v.price, v.height, v.observedAt)) - } + 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) - - // After excluding the two stale validators, current set prices: [500, 300, 200] - // Sorted: [200, 300, 500] → upper-median (index 1) = 300 (val with height=1001) - require.Equal(t, uint64(300), stored.Prices[stored.MedianIndex]) - require.Equal(t, uint64(1001), stored.ChainHeights[stored.MedianIndex]) + require.Equal(t, uint64(2000), stored.LastAppliedChainHeight) }) } func TestMigrateGasPricesToChainMeta(t *testing.T) { chainId := "eip155:11155111" - t.Run("migrates gas prices to chain meta", func(t *testing.T) { + 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) @@ -330,9 +272,10 @@ func TestMigrateGasPricesToChainMeta(t *testing.T) { 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) - // observedAts unknown at migration time → all 0 - require.Equal(t, []uint64{0, 0}, cm.ObservedAts) 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) { @@ -353,7 +296,7 @@ func TestMigrateGasPricesToChainMeta(t *testing.T) { Signers: []string{"cosmos1xyz"}, Prices: []uint64{999_000_000_000}, ChainHeights: []uint64{99999}, - ObservedAts: []uint64{1700000099}, + StoredAts: []uint64{0}, MedianIndex: 0, })) @@ -370,13 +313,13 @@ func TestMigrateGasPricesToChainMeta(t *testing.T) { } // TestVoteChainMetaContractState verifies that after voting, the UniversalCore contract's -// on-chain storage reflects the correct gas price, chain height, and observed timestamp. +// 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) - observedAt = uint64(1700000000) + price = uint64(100_000_000_000) + height = uint64(12345) ) testApp, ctx, uvals, vals := setupVoteChainMetaTest(t, 1) @@ -385,7 +328,7 @@ func TestVoteChainMetaContractState(t *testing.T) { require.NoError(t, err) coreAcc := sdk.AccAddress(coreVal).String() - require.NoError(t, utils.ExecVoteChainMeta(t, ctx, testApp, uvals[0], coreAcc, chainId, price, height, observedAt)) + 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 @@ -407,87 +350,4 @@ func TestVoteChainMetaContractState(t *testing.T) { got := new(big.Int).SetBytes(res.Ret) require.Equal(t, new(big.Int).SetUint64(height), got) }) - - t.Run("timestampObservedAtByChainNamespace matches voted observedAt", func(t *testing.T) { - res, err := testApp.EVMKeeper.CallEVM(ctx, ucABI, caller, universalCoreAddr, false, "timestampObservedAtByChainNamespace", chainId) - require.NoError(t, err) - got := new(big.Int).SetBytes(res.Ret) - require.Equal(t, new(big.Int).SetUint64(observedAt), got) - }) -} - -// TestVoteChainMetaAbsoluteStaleness verifies that when all validators' observedAt timestamps -// are older than ObservedAtStalenessThresholdSeconds relative to the current block time, -// the EVM contract is NOT updated (it retains its previous value). -// -// These tests call VoteChainMeta directly on the keeper (bypassing authz) so that -// block time can be freely manipulated without hitting authz grant expiry. -func TestVoteChainMetaAbsoluteStaleness(t *testing.T) { - chainId := "eip155:11155111" - threshold := uexecutortypes.ObservedAtStalenessThresholdSeconds // 300 - - universalCoreAddr := utils.GetDefaultAddresses().HandlerAddr - - readGasPrice := func(t *testing.T, testApp *app.ChainApp, ctx sdk.Context) *big.Int { - t.Helper() - 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) - return new(big.Int).SetBytes(res.Ret) - } - - t.Run("stale single vote does not update contract", func(t *testing.T) { - testApp, ctx, _, vals := setupVoteChainMetaTest(t, 1) - - staleObservedAt := uint64(1_700_000_000) - // Block time is far past the staleness window - staleCtx := ctx.WithBlockTime(time.Unix(int64(staleObservedAt+threshold+60), 0)) - - valAddr, err := sdk.ValAddressFromBech32(vals[0].OperatorAddress) - require.NoError(t, err) - - require.NoError(t, testApp.UexecutorKeeper.VoteChainMeta(staleCtx, valAddr, chainId, - 100_000_000_000, 12345, staleObservedAt)) - - // Vote was stored in state - stored, found, err := testApp.UexecutorKeeper.GetChainMeta(staleCtx, chainId) - require.NoError(t, err) - require.True(t, found) - require.Equal(t, uint64(100_000_000_000), stored.Prices[0]) - - // Contract must NOT have been updated — should still be 0 - require.Zero(t, readGasPrice(t, testApp, staleCtx).Sign(), - "contract must not be updated when all validators are stale") - }) - - t.Run("all validators stale does not update contract", func(t *testing.T) { - testApp, ctx, _, vals := setupVoteChainMetaTest(t, 3) - - freshObservedAt := uint64(1_700_000_000) - - // First vote with fresh block time → contract gets updated - freshCtx := ctx.WithBlockTime(time.Unix(int64(freshObservedAt), 0)) - for i := 0; i < 3; i++ { - valAddr, err := sdk.ValAddressFromBech32(vals[i].OperatorAddress) - require.NoError(t, err) - require.NoError(t, testApp.UexecutorKeeper.VoteChainMeta(freshCtx, valAddr, chainId, - 200_000_000_000, uint64(12345+i), freshObservedAt+uint64(i))) - } - require.Equal(t, new(big.Int).SetUint64(200_000_000_000), readGasPrice(t, testApp, freshCtx)) - - // Re-vote with same old timestamps but block time past staleness window - futureCtx := ctx.WithBlockTime(time.Unix(int64(freshObservedAt+threshold+60), 0)) - for i := 0; i < 3; i++ { - valAddr, err := sdk.ValAddressFromBech32(vals[i].OperatorAddress) - require.NoError(t, err) - require.NoError(t, testApp.UexecutorKeeper.VoteChainMeta(futureCtx, valAddr, chainId, - 999_000_000_000, uint64(99999+i), freshObservedAt+uint64(i))) - } - - // Contract must retain the old fresh value — stale votes must not overwrite it - require.Equal(t, new(big.Int).SetUint64(200_000_000_000), readGasPrice(t, testApp, futureCtx), - "contract must retain last good value when all validators report stale data") - }) } diff --git a/test/utils/bytecode.go b/test/utils/bytecode.go index 72bf82bb..664df26f 100644 --- a/test/utils/bytecode.go +++ b/test/utils/bytecode.go @@ -6,7 +6,7 @@ const UEA_SVM_BYTECODE = "6080604052348015600e575f80fd5b5060015f55611cf780610020 const UEA_PROXY_BYTECODE = "608060405260043610610028575f3560e01c806323efa7ec14610032578063aaf10f4214610051575b6100306100a8565b005b34801561003d575f80fd5b5061003061004c366004610368565b6100ba565b34801561005c575f80fd5b507f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5460405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100b86100b36102cc565b61034a565b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156101045750825b90505f8267ffffffffffffffff1660011480156101205750303b155b90508115801561012e575080155b15610165576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156101c65784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b5f6101ef7f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5490565b905073ffffffffffffffffffffffffffffffffffffffff81161561023f576040517fae962d4e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b867f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d555083156102c45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f806102f67f868a771a75a4aa6c2be13e9a9617cb8ea240ed84a3a90c8469537393ec3e115d5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610345576040517fae962d4e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b365f80375f80365f845af43d5f803e808015610364573d5ff35b3d5ffd5b5f60208284031215610378575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461039b575f80fd5b939250505056fea2646970667358221220c4b8f9457567bdcd08b95faef7df86de4e9daead65e2db22018126d9eb77d85864736f6c634300081a0033" -const HANDLER_CONTRACT_BYTECODE = "608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c908162bc574b146137825750806301ffc9a7146136e15780630379eae8146136815780630ac6eb77146135d5578063172bfc1c146135595780631a4e49d4146135305780631a873ce4146134fd578063240028e8146134b3578063248a9ca3146134615780632f2ff15d1461340457806336568abe1461339a5780633f4ba83a146132915780634b1d2eeb146132515780634d20d0f81461321e5780634eb7d1a1146131de57806357724c41146130dd5780635b549182146130aa5780635c975abb14613069578063606b05a414612ffc5780636435967b1461282f57806364f10e501461281457806368c70c9e146127c95780636ca752e31461277e5780636d4008a814612739578063780ad8271461203357806378a8812714611fb857806381fbadad14611f9a5780638377e23014611f6657806383b94a5214611eb05780638456cb5914611d8557806391d1485414611d0e5780639be7fdb214611c23578063a217fddf14611c07578063a5172ddb14611bbc578063a861469f14611b72578063ad14d38514611b28578063af90f35114611a4a578063b5d8349f146119e9578063be0580c014611843578063c6f1b7e7146117f2578063cd20c6e8146117ad578063d17c872c14611687578063d547741f14611620578063db9a0daf1461155d578063dbc1b464146114fc578063dcc16b5c146112be578063dd19e7551461102a578063e798646614610f4b578063ec87621c14610f10578063f881446714610716578063f8c8765e146103e4578063fa064472146102f3578063fb46e99d146102d55763fc6b5de80361000f57346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d25760206102bf816102ac3660048701613877565b81604051938285809451938492016139cd565b8101601281520301902054604051908152f35b80fd5b50346102d257806003193601126102d2576020600654604051908152f35b50346102d25760806003193601126102d25760043567ffffffffffffffff81116103e0576103ca6103497f5e41bf0052b493123a63e4e0d9095ed4324108e489d58c9a0948b2be366ac8c6923690600401613877565b60243560443560643590816103ab6020604051868851918381818c01946103718183886139cd565b8101600b815203019020558460405183818b5161038f8183886139cd565b8101601181520301902055604051809381928a519283916139cd565b81016012815203019020556040519485946080865260808601906139ee565b926020850152604084015260608301520390a180f35b5080fd5b50346102d25760806003193601126102d2576103fe6138ef565b610406613912565b61040e613935565b6064359173ffffffffffffffffffffffffffffffffffffffff8316809303610712577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff81168015908161070a575b6001149081610700575b1590816106f7575b506106cf579173ffffffffffffffffffffffffffffffffffffffff80949392838860017fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000859716177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005561067a575b506104fa614135565b610502614135565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561052e614135565b61053733613c89565b50167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a55167fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff000000000000000000000000000000000000000060085416176008557fffffffffffffffffffffffff000000000000000000000000000000000000000060095416176009556105e65780f35b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f6104f1565b6004877ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b9050155f610482565b303b15915061047a565b879150610470565b8480fd5b5060a06003193601126102d25761072b6138ef565b90610734613967565b9160443591606435936084359273ffffffffffffffffffffffffffffffffffffffff8416928385036102d25773ffffffffffffffffffffffffffffffffffffffff601054163303610ee857610787613f8a565b61078f613fdd565b8691839773ffffffffffffffffffffffffffffffffffffffff8216948515610ec0578615610ec0573415610e98578815610e985762ffffff1615610e56575b15610e2e575b824211610e065761088f60208973ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a54169488861090815f14610dff5786915b15610df757905b604051958694859384937f1698ee820000000000000000000000000000000000000000000000000000000085526004850191604091949373ffffffffffffffffffffffffffffffffffffffff62ffffff9281606087019816865216602085015216910152565b03915afa908115610c98579073ffffffffffffffffffffffffffffffffffffffff918491610dc8575b501615610da057803b156103e05781600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af18015610d0157908291610d8b575b50600a546008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015234602482015292602092849260449284929091165af18015610d0157610d6e575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a5416976040519861099d8a6137b2565b89528460208a0152169182604089015230606089015260808801528560a08801523460c08801528060e08801526020610a8961010473ffffffffffffffffffffffffffffffffffffffff6008541699846040519b8c9485937fdb3e2198000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1968715610d61578197610d29575b5080602073ffffffffffffffffffffffffffffffffffffffff600a5416604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015610d0157610d0c575b506040517f42966c6800000000000000000000000000000000000000000000000000000000815286600482015260208160248185885af18015610d0157610cd4575b5086340394348611610ca757873403610bd3575b505060606040967f01fd625a5ce1109c10761818e2ef64ea92cd4966d78086d37e5a4b50e322687892885191825287602083015288820152a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005582519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff600a5416803b15610ca3578280916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c60048401525af18015610c98579183918893610c7e575b5081809381925af1610c4a613b4c565b5015610c565780610b6a565b807f90b8ec180000000000000000000000000000000000000000000000000000000060049252fd5b610c8b91935082906137fc565b6103e0578186915f610c3a565b6040513d85823e3d90fd5b8280fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b610cf59060203d602011610cfa575b610ced81836137fc565b810190613a4d565b610b56565b503d610ce3565b6040513d84823e3d90fd5b610d249060203d602011610cfa57610ced81836137fc565b610b14565b9096506020813d602011610d59575b81610d45602093836137fc565b81010312610d555751955f610a99565b5f80fd5b3d9150610d38565b50604051903d90823e3d90fd5b610d869060203d602011610cfa57610ced81836137fc565b610971565b81610d95916137fc565b6102d257805f610906565b6004827f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b610dea915060203d602011610df0575b610de281836137fc565b810190613b13565b5f6108b8565b503d610dd8565b508590610829565b8091610822565b6004827f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9150600654603c810290808204603c1490151715610ca757610e509042613b3f565b916107d4565b8483526004602052604083205462ffffff169850886107ce575b6004837f3733548a000000000000000000000000000000000000000000000000000000008152fd5b6004847f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004847fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b807fbce361b00000000000000000000000000000000000000000000000000000000060049252fd5b50346102d257806003193601126102d25760206040517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50346102d25760406003193601126102d257610f656138ef565b73ffffffffffffffffffffffffffffffffffffffff610f82613958565b91610f8b613b7b565b169081156110025760207f16ef4de07b0452a43221c91064fb645963a8e2e60bd8a7514da58d56e315c42291838552600f8252610ff681604087209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b6004837fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760406003193601126102d2576110446138ef565b73ffffffffffffffffffffffffffffffffffffffff6024359116906040517fa0c50b690000000000000000000000000000000000000000000000000000000081528381600481865afa9081156112b3578491611236575b5060405191815192602081818501956110b58183896139cd565b81016014815203019020549080155f146111f75750925b73ffffffffffffffffffffffffffffffffffffffff60405160208185516110f481838a6139cd565b8101600c81520301902054169283156111cf57602061111e916040518093819287519283916139cd565b8101600b815203019020549081156111a757848202948286040361117a57856040916111769596975260136020522054604051958695865260208601526040850152606084015260a0608084015260a08301906139ee565b0390f35b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6004867fe661aed0000000000000000000000000000000000000000000000000000000008152fd5b6004867fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b939080851061120657506110cc565b85604491867fff632bea000000000000000000000000000000000000000000000000000000008352600452602452fd5b90503d8085833e61124781836137fc565b8101906020818303126107125780519067ffffffffffffffff82116112af570181601f8201121561071257805161127d8161383d565b9261128b60405194856137fc565b818452602082840101116112af576112a991602080850191016139cd565b5f61109b565b8580fd5b6040513d86823e3d90fd5b50346102d25760606003193601126102d25760043567ffffffffffffffff81116103e0576112f0903690600401613877565b6112f8613912565b60443562ffffff81169182820361071257611311613b7b565b73ffffffffffffffffffffffffffffffffffffffff811680156111cf57916020916113e39373ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541691821091825f146114f55780925b156114ed57506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156112b35773ffffffffffffffffffffffffffffffffffffffff9185916114ce575b50169081156114a65791611495917f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d93604051602081855161144f8183858a016139cd565b8101600d815203019020827fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790556040519384936060855260608501906139ee565b91602084015260408301520390a180f35b6004847f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b6114e7915060203d602011610df057610de281836137fc565b5f61140a565b905090610829565b8192611377565b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d257602073ffffffffffffffffffffffffffffffffffffffff611549826102ac3660048801613877565b8101600c8152030190205416604051908152f35b50346102d25760206003193601126102d2576004358180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115f8576020817f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b92600655604051908152a180f35b6004827f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760406003193601126102d257611683600435611640613912565b9061167e611679825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613c03565b613e82565b5080f35b50346102d25760406003193601126102d2576116a16138ef565b6116a9613967565b908280527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156117855773ffffffffffffffffffffffffffffffffffffffff169081156110025762ffffff16906101f482141580611779575b8061176d575b610e70578252600460205260408220907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000082541617905580f35b50612710821415611733565b50610bb882141561172d565b6004837f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d257604060209173ffffffffffffffffffffffffffffffffffffffff6117e16138ef565b168152601383522054604051908152f35b50346102d257806003193601126102d257602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102d25760606003193601126102d25761185d6138ef565b611865613912565b61186d613935565b918380527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040842073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156119c15773ffffffffffffffffffffffffffffffffffffffff16801580156119a3575b8015611985575b610ec05773ffffffffffffffffffffffffffffffffffffffff929183917fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff00000000000000000000000000000000000000006008541617600855167fffffffffffffffffffffffff0000000000000000000000000000000000000000600954161760095580f35b5073ffffffffffffffffffffffffffffffffffffffff8316156118e8565b5073ffffffffffffffffffffffffffffffffffffffff8216156118e1565b6004847f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d257602073ffffffffffffffffffffffffffffffffffffffff611a36826102ac3660048801613877565b8101600d8152030190205416604051908152f35b50346102d25760206003193601126102d257611a646138ef565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115f85773ffffffffffffffffffffffffffffffffffffffff168015611b00577fffffffffffffffffffffffff0000000000000000000000000000000000000000601054161760105580f35b6004827fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d25760ff604060209273ffffffffffffffffffffffffffffffffffffffff611b5e6138ef565b168152600384522054166040519015158152f35b50346102d25760206003193601126102d25762ffffff604060209273ffffffffffffffffffffffffffffffffffffffff611baa6138ef565b16815260048452205416604051908152f35b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d2576020611bf4816102ac3660048701613877565b8101600b81520301902054604051908152f35b50346102d257806003193601126102d257602090604051908152f35b50346102d25760406003193601126102d25760043567ffffffffffffffff81116103e057611c55903690600401613877565b73ffffffffffffffffffffffffffffffffffffffff611c72613912565b611c7a613b7b565b168015611002577f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94991611d02916040516020818451611cbc81838589016139cd565b8101600c815203019020817fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790556040519283926040845260408401906139ee565b9060208301520390a180f35b50346102d25760406003193601126102d25773ffffffffffffffffffffffffffffffffffffffff6040611d3f613912565b9260043581527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020522091165f52602052602060ff60405f2054166040519015158152f35b50346102d257806003193601126102d2578080527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040812073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611e8857611df2613f8a565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b807f49e27cff0000000000000000000000000000000000000000000000000000000060049252fd5b50346102d25760206003193601126102d257611eca6138ef565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115f85773ffffffffffffffffffffffffffffffffffffffff168015611b00577fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102d257806003193601126102d257602073ffffffffffffffffffffffffffffffffffffffff60105416604051908152f35b50346102d257806003193601126102d2576020600e54604051908152f35b50346102d257611fc736613979565b9083809394527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f2054161561178557612030929361202b613f8a565b613a65565b80f35b50346102d25760c06003193601126102d25761204d6138ef565b60243590612059613935565b906064359262ffffff8416908185036112af5760843560a4359361207b613f8a565b612083613fdd565b61208e868483614054565b8473ffffffffffffffffffffffffffffffffffffffff821697888a52600360205260ff60408b205416156127115794156126d0575b1561267b575b84421161265357602084612186928a73ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541690818d10805f1461264c5781935b50156114ed57506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156125b55773ffffffffffffffffffffffffffffffffffffffff91899161262d575b5016156126055780156125dd576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018390526020816044818b8b5af180156125b5576125c0575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018390526020816044818b8b5af180156125b557612598575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169360405194612291866137b2565b8886526020808701918252929091166040808701828152306060890190815260808901998a5260a0890188815260c08a0188815260e08b018f815260085495517f414bf3890000000000000000000000000000000000000000000000000000000081529b5173ffffffffffffffffffffffffffffffffffffffff90811660048e01529751881660248d0152935162ffffff1660448c01529151861660648b0152995160848a0152985160a4890152975160c48801529651821660e48701529585916101049183918c91165af1928315612531578793612564575b50821061253c5773ffffffffffffffffffffffffffffffffffffffff60085416604051907f095ea7b300000000000000000000000000000000000000000000000000000000825260048201528660248201526020816044818a8a5af1801561253157612514575b508573ffffffffffffffffffffffffffffffffffffffff600a5416803b156103e0578180916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528960048401525af18015610d01576124ff575b5080808085885af1612446613b4c565b50156124d757927ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e2949273ffffffffffffffffffffffffffffffffffffffff9260c09584600a54169060405196875260208701526040860152606085015260808401521660a0820152a160017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6004867f90b8ec18000000000000000000000000000000000000000000000000000000008152fd5b81612509916137fc565b6112af57855f612436565b61252c9060203d602011610cfa57610ced81836137fc565b6123d2565b6040513d89823e3d90fd5b6004867f8199f5f3000000000000000000000000000000000000000000000000000000008152fd5b9092506020813d602011612590575b81612580602093836137fc565b81010312610d555751915f61236b565b3d9150612573565b6125b09060203d602011610cfa57610ced81836137fc565b612265565b6040513d8a823e3d90fd5b6125d89060203d602011610cfa57610ced81836137fc565b612202565b6004877f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004877f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b612646915060203d602011610df057610de281836137fc565b5f6121ad565b8293612119565b6004887f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9350600654603c810290808204603c14901517156126a35761269d9042613b3f565b936120c9565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8789526004602052604089205462ffffff169450846120c3576004897f3733548a000000000000000000000000000000000000000000000000000000008152fd5b60048a7f4e38f95a000000000000000000000000000000000000000000000000000000008152fd5b50346102d25760206003193601126102d257604060209173ffffffffffffffffffffffffffffffffffffffff61276d6138ef565b168152600583522054604051908152f35b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d25760206127b6816102ac3660048701613877565b8101601481520301902054604051908152f35b50346102d25760206003193601126102d2576004359067ffffffffffffffff82116102d2576020612801816102ac3660048701613877565b8101601181520301902054604051908152f35b50346102d25761203061282636613979565b9161202b613f8a565b5034610d555760c0600319360112610d55576128496138ef565b602435612854613935565b6064358015918215809203610d555760843562ffffff811690818103610d555760a43561287f613f8a565b612887613fdd565b61289284888a614054565b5f95156129b15750506040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101869052919050602082806044810103818a73ffffffffffffffffffffffffffffffffffffffff8b165af1908115612531577ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49460609473ffffffffffffffffffffffffffffffffffffffff948594612992575b505b6040519788526020880152604087015216941692a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6129aa9060203d602011610cfa57610ced81836137fc565b505f612954565b80919293955015612fd45773ffffffffffffffffffffffffffffffffffffffff871691825f52600360205260ff60405f20541615612fac579215612f6a575b600654603c810290808204603c1490151715612f3d57612a109042613b3f565b804211612f1557612ac860208573ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a541680881090815f14612f0e578d915b15612f06576040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015612e015773ffffffffffffffffffffffffffffffffffffffff915f91612ee7575b501615612ebf576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018890526020816044815f885af18015612e0157612ea2575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018890526020816044815f885af18015612e0157612e85575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169460405195612bcd876137b2565b858752602087015216604085015230606085015260808401528560a08401528060c08401525f60e08401526020612cb761010473ffffffffffffffffffffffffffffffffffffffff60085416955f60405197889485937f414bf389000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1928315612e01575f93612e51575b508210612e295760205f91604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015612e0157612e0c575b5073ffffffffffffffffffffffffffffffffffffffff600a5416803b15610d55575f80916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528760048401525af18015612e0157612dec575b508580808084875af1612da4613b4c565b50156124d75773ffffffffffffffffffffffffffffffffffffffff7ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e493606093829390612956565b612df99196505f906137fc565b5f945f612d93565b6040513d5f823e3d90fd5b612e249060203d602011610cfa57610ced81836137fc565b612d30565b7f8199f5f3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d602011612e7d575b81612e6d602093836137fc565b81010312610d555751915f612cc7565b3d9150612e60565b612e9d9060203d602011610cfa57610ced81836137fc565b612ba1565b612eba9060203d602011610cfa57610ced81836137fc565b612b3e565b7f76ecffc0000000000000000000000000000000000000000000000000000000005f5260045ffd5b612f00915060203d602011610df057610de281836137fc565b5f612aef565b508c90610829565b8091612a5d565b7f1ab7da6b000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9150805f52600460205262ffffff60405f20541691826129f0577f3733548a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e38f95a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f22c50cbf000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55577f882f47825d4043cd04a564cad4f524a7fe00a604ae024c23dbc8065b77668b4761302b366138bd565b90613034613b7b565b81604051602081845161304a81838589016139cd565b810160148152030190205561306460405192839283613a31565b0390a1005b34610d55575f600319360112610d5557602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610d55575f600319360112610d5557602073ffffffffffffffffffffffffffffffffffffffff60075416604051908152f35b34610d55576040600319360112610d55576130f66138ef565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040902054602435919060ff16156131b65773ffffffffffffffffffffffffffffffffffffffff16801561318e576113888211613166575f52600560205260405f20555f80f35b7fc31c0b6e000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f49e27cff000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55576020600319360112610d55576004355f526002602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610d55575f600319360112610d5557602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b34610d55576020600319360112610d55576004355f526001602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610d55575f600319360112610d5557335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131b6577fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff811615613372577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55576040600319360112610d55576133b3613912565b3373ffffffffffffffffffffffffffffffffffffffff8216036133dc5761001a90600435613e82565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610d55576040600319360112610d555761001a600435613423613912565b9061345c611679825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613d70565b34610d55576020600319360112610d555760206134ab6004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b34610d55576020600319360112610d555773ffffffffffffffffffffffffffffffffffffffff6134e16138ef565b165f52600f602052602060ff60405f2054166040519015158152f35b34610d55575f600319360112610d5557602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b34610d55576020600319360112610d55576004355f525f602052602060405f2054604051908152f35b34610d55576040600319360112610d55576135726138ef565b73ffffffffffffffffffffffffffffffffffffffff60243591613593613b7b565b1690811561318e5760207f911a025fb070fa2a29c37a3bf4c00d16acf15583cd050f17bdbacbab7e72320391835f52601382528060405f2055604051908152a2005b34610d55576040600319360112610d55576135ee6138ef565b6135f6613958565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131b65773ffffffffffffffffffffffffffffffffffffffff61001a92165f52600360205260405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b34610d55577f6a59d469e3757d6e139cdf95b12740f585d553afac49b90bdbe278502a4427186136b0366138bd565b908160405160208184516136c781838589016139cd565b8101600b8152030190205561306460405192839283613a31565b34610d55576020600319360112610d55576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610d5557807f7965db0b0000000000000000000000000000000000000000000000000000000060209214908115613758575b506040519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148261374d565b34610d55575f600319360112610d555760209073ffffffffffffffffffffffffffffffffffffffff600854168152f35b610100810190811067ffffffffffffffff8211176137cf57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176137cf57604052565b67ffffffffffffffff81116137cf57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f82011215610d555780359061388e8261383d565b9261389c60405194856137fc565b82845260208383010111610d5557815f926020809301838601378301015290565b6040600319820112610d55576004359067ffffffffffffffff8211610d55576138e891600401613877565b9060243590565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610d5557565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610d5557565b6044359073ffffffffffffffffffffffffffffffffffffffff82168203610d5557565b602435908115158203610d5557565b6024359062ffffff82168203610d5557565b6003196060910112610d555760043573ffffffffffffffffffffffffffffffffffffffff81168103610d5557906024359060443573ffffffffffffffffffffffffffffffffffffffff81168103610d555790565b5f5b8381106139de5750505f910152565b81810151838201526020016139cf565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093613a2a815180928187528780880191016139cd565b0116010190565b929190613a486020916040865260408601906139ee565b930152565b90816020910312610d5557518015158103610d555790565b90602091613ae693613a78818484614054565b5f73ffffffffffffffffffffffffffffffffffffffff6040518097819682957f47e7ef24000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0393165af18015612e0157613af85750565b613b109060203d602011610cfa57610ced81836137fc565b50565b90816020910312610d55575173ffffffffffffffffffffffffffffffffffffffff81168103610d555790565b91908201809211612f3d57565b3d15613b76573d90613b5d8261383d565b91613b6b60405193846137fc565b82523d5f602084013e565b606090565b335f9081527f06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a602052604090205460ff1615613bb357565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0860245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615613c5a5750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613d6b5773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f14613e7c57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f14613e7c57805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416613fb557565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00541461402c5760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919073ffffffffffffffffffffffffffffffffffffffff161561318e5773ffffffffffffffffffffffffffffffffffffffff16801561318e5773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016811490811561412b575b5061410357156140db57565b7f1f2a2005000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f82d5d76a000000000000000000000000000000000000000000000000000000005f5260045ffd5b905030145f6140cf565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561416457565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea26469706673582212200a731130a8c5bcf01626a6f678a302cf572f981bffc866cffc5f6e8689e9ff9e64736f6c634300081a0033" +const HANDLER_CONTRACT_BYTECODE = "608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c908162bc574b1461393a5750806301ffc9a7146138995780630379eae8146138395780630ac6eb771461378d578063172bfc1c146137115780631a4e49d4146136e85780631a873ce4146136b5578063240028e81461366b578063248a9ca3146136195780632f2ff15d146135bc57806336568abe146135525780633f4ba83a146134495780634b1d2eeb146134095780634d20d0f8146133d65780634d49fbf3146132565780634eb7d1a11461321657806357724c41146131155780635b549182146130e25780635c975abb146130a1578063606b05a4146130345780636435967b1461286757806364f10e501461284c57806368c70c9e146128015780636ca752e3146127b65780636d4008a814612771578063780ad8271461206757806378a8812714611fec57806381fbadad14611fce5780638377e23014611f9a57806383b94a5214611ee45780638456cb5914611db957806391d1485414611d425780639be7fdb214611c57578063a217fddf14611c3b578063a5172ddb14611bf0578063a861469f14611ba6578063ad14d38514611b5c578063af90f35114611a7e578063b49f6b8814611a0f578063b5d8349f146119ae578063b6322a9f14611963578063be0580c0146117bd578063c6f1b7e71461176c578063cd20c6e814611727578063d17c872c14611601578063d547741f1461159a578063db9a0daf146114d7578063dbc1b46414611476578063dcc16b5c14611238578063dd19e7551461104c578063e798646614610f6d578063ec87621c14610f32578063eefbaa3514610e44578063f881446714610646578063f8c8765e14610314578063fb46e99d146102f65763fc6b5de80361000f57346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f35760206102e0816102cd3660048701613a2f565b8160405193828580945193849201613b1f565b8101601281520301902054604051908152f35b80fd5b50346102f357806003193601126102f3576020600654604051908152f35b50346102f35760806003193601126102f35761032e613aa7565b610336613aca565b61033e613aed565b6064359173ffffffffffffffffffffffffffffffffffffffff8316809303610642577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549360ff8560401c16159467ffffffffffffffff81168015908161063a575b6001149081610630575b159081610627575b506105ff579173ffffffffffffffffffffffffffffffffffffffff80949392838860017fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000859716177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556105aa575b5061042a6143a1565b6104326143a1565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561045e6143a1565b61046733613ef5565b50167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a55167fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff000000000000000000000000000000000000000060085416176008557fffffffffffffffffffffffff000000000000000000000000000000000000000060095416176009556105165780f35b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555f610421565b6004877ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b9050155f6103b2565b303b1591506103aa565b8791506103a0565b8480fd5b5060a06003193601126102f35761065b613aa7565b90610664613bc5565b9160443591606435936084359273ffffffffffffffffffffffffffffffffffffffff8416928385036102f35773ffffffffffffffffffffffffffffffffffffffff601054163303610e1c576106b76141f6565b6106bf614249565b8691839773ffffffffffffffffffffffffffffffffffffffff8216948515610df4578615610df4573415610dcc578815610dcc5762ffffff1615610d8a575b15610d62575b824211610d3a576107bf60208973ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a54169488861090815f14610d335786915b15610d2b57905b604051958694859384937f1698ee820000000000000000000000000000000000000000000000000000000085526004850191604091949373ffffffffffffffffffffffffffffffffffffffff62ffffff9281606087019816865216602085015216910152565b03915afa908115610bcc579073ffffffffffffffffffffffffffffffffffffffff918491610cfc575b501615610cd457803b15610bc85781600491604051928380927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af18015610c3557908291610cbf575b50600a546008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015234602482015292602092849260449284929091165af18015610c3557610ca2575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a541697604051986108cd8a61396a565b89528460208a0152169182604089015230606089015260808801528560a08801523460c08801528060e088015260206109b961010473ffffffffffffffffffffffffffffffffffffffff6008541699846040519b8c9485937fdb3e2198000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1968715610c95578197610c5d575b5080602073ffffffffffffffffffffffffffffffffffffffff600a5416604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015610c3557610c40575b506040517f42966c6800000000000000000000000000000000000000000000000000000000815286600482015260208160248185885af18015610c3557610c08575b5086340394348611610bdb57873403610b03575b505060606040967f01fd625a5ce1109c10761818e2ef64ea92cd4966d78086d37e5a4b50e322687892885191825287602083015288820152a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005582519182526020820152f35b73ffffffffffffffffffffffffffffffffffffffff600a5416803b15610bd7578280916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c60048401525af18015610bcc579183918893610bae575b5081809381925af1610b7a613db8565b5015610b865780610a9a565b807f90b8ec180000000000000000000000000000000000000000000000000000000060049252fd5b610bbb91935082906139b4565b610bc8578186915f610b6a565b5080fd5b6040513d85823e3d90fd5b8280fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b610c299060203d602011610c2e575b610c2181836139b4565b810190613cb9565b610a86565b503d610c17565b6040513d84823e3d90fd5b610c589060203d602011610c2e57610c2181836139b4565b610a44565b9096506020813d602011610c8d575b81610c79602093836139b4565b81010312610c895751955f6109c9565b5f80fd5b3d9150610c6c565b50604051903d90823e3d90fd5b610cba9060203d602011610c2e57610c2181836139b4565b6108a1565b81610cc9916139b4565b6102f357805f610836565b6004827f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b610d1e915060203d602011610d24575b610d1681836139b4565b810190613d7f565b5f6107e8565b503d610d0c565b508590610759565b8091610752565b6004827f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9150600654603c810290808204603c1490151715610bdb57610d849042613dab565b91610704565b8483526004602052604083205462ffffff169850886106fe575b6004837f3733548a000000000000000000000000000000000000000000000000000000008152fd5b6004847f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004847fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b807fbce361b00000000000000000000000000000000000000000000000000000000060049252fd5b50346102f35760606003193601126102f35760043567ffffffffffffffff8111610bc857610f1b610e9a7f5e41bf0052b493123a63e4e0d9095ed4324108e489d58c9a0948b2be366ac8c6923690600401613a2f565b602435604435610ef66040518385519160208181890194610ebc818388613b1f565b8101600b81520301902055826040516020818851610edb818388613b1f565b81016011815203019020556040519182918651928391613b1f565b8101906012825260208142930301902055604051938493608085526080850190613b40565b91602084015260408301524260608301520390a180f35b50346102f357806003193601126102f35760206040517f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088152f35b50346102f35760406003193601126102f357610f87613aa7565b73ffffffffffffffffffffffffffffffffffffffff610fa4613b10565b91610fad613de7565b169081156110245760207f16ef4de07b0452a43221c91064fb645963a8e2e60bd8a7514da58d56e315c42291838552600f825261101881604087209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b6004837fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760406003193601126102f357611066613aa7565b73ffffffffffffffffffffffffffffffffffffffff6024359116906040517fa0c50b690000000000000000000000000000000000000000000000000000000081528381600481865afa90811561122d57849161120b575b5060405191815192602081818501956110d7818389613b1f565b81016014815203019020549080155f146111cd57505b73ffffffffffffffffffffffffffffffffffffffff604051602081855161111581838a613b1f565b8101600c81520301902054169283156111a557602061113f91604051809381928751928391613b1f565b8101600b8152030190205490811561117d5761117993949561116360409284613ca6565b9681526013602052205460405195869586613b83565b0390f35b6004867fe661aed0000000000000000000000000000000000000000000000000000000008152fd5b6004867fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b908082106111db57506110ed565b85906044927fff632bea000000000000000000000000000000000000000000000000000000008352600452602452fd5b61122791503d8086833e61121f81836139b4565b810190613c47565b5f6110bd565b6040513d86823e3d90fd5b50346102f35760606003193601126102f35760043567ffffffffffffffff8111610bc85761126a903690600401613a2f565b611272613aca565b60443562ffffff8116918282036106425761128b613de7565b73ffffffffffffffffffffffffffffffffffffffff811680156111a5579160209161135d9373ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541691821091825f1461146f5780925b1561146757506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa801561122d5773ffffffffffffffffffffffffffffffffffffffff918591611448575b5016908115611420579161140f917f21e3c1439de176cb39006e603b26a8d890fe2267c804597e40d2954871141d7d9360405160208185516113c98183858a01613b1f565b8101600d815203019020827fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051938493606085526060850190613b40565b91602084015260408301520390a180f35b6004847f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b611461915060203d602011610d2457610d1681836139b4565b5f611384565b905090610759565b81926112f1565b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f357602073ffffffffffffffffffffffffffffffffffffffff6114c3826102cd3660048801613a2f565b8101600c8152030190205416604051908152f35b50346102f35760206003193601126102f3576004358180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611572576020817f424b07caa75ce8e1c3985f334273f957db9ce138de114e48e50d8240d4d7300b92600655604051908152a180f35b6004827f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760406003193601126102f3576115fd6004356115ba613aca565b906115f86115f3825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613e6f565b6140ee565b5080f35b50346102f35760406003193601126102f35761161b613aa7565b611623613bc5565b908280527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156116ff5773ffffffffffffffffffffffffffffffffffffffff169081156110245762ffffff16906101f4821415806116f3575b806116e7575b610da4578252600460205260408220907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000082541617905580f35b506127108214156116ad565b50610bb88214156116a7565b6004837f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f357604060209173ffffffffffffffffffffffffffffffffffffffff61175b613aa7565b168152601383522054604051908152f35b50346102f357806003193601126102f357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102f35760606003193601126102f3576117d7613aa7565b6117df613aca565b6117e7613aed565b918380527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040842073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f2054161561193b5773ffffffffffffffffffffffffffffffffffffffff168015801561191d575b80156118ff575b610df45773ffffffffffffffffffffffffffffffffffffffff929183917fffffffffffffffffffffffff00000000000000000000000000000000000000006007541617600755167fffffffffffffffffffffffff00000000000000000000000000000000000000006008541617600855167fffffffffffffffffffffffff0000000000000000000000000000000000000000600954161760095580f35b5073ffffffffffffffffffffffffffffffffffffffff831615611862565b5073ffffffffffffffffffffffffffffffffffffffff82161561185b565b6004847f49e27cff000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f357602061199b816102cd3660048701613a2f565b8101601581520301902054604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f357602073ffffffffffffffffffffffffffffffffffffffff6119fb826102cd3660048801613a2f565b8101600d8152030190205416604051908152f35b50346102f3577f57ad858a99d9aee6f1fd395e454bb1659eb8500ccb081c729a103dc2247ba3a4611a3f36613a75565b90611a48613de7565b816040516020818451611a5e8183858901613b1f565b8101601581520301902055611a7860405192839283613c2b565b0390a180f35b50346102f35760206003193601126102f357611a98613aa7565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115725773ffffffffffffffffffffffffffffffffffffffff168015611b34577fffffffffffffffffffffffff0000000000000000000000000000000000000000601054161760105580f35b6004827fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f35760ff604060209273ffffffffffffffffffffffffffffffffffffffff611b92613aa7565b168152600384522054166040519015158152f35b50346102f35760206003193601126102f35762ffffff604060209273ffffffffffffffffffffffffffffffffffffffff611bde613aa7565b16815260048452205416604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f3576020611c28816102cd3660048701613a2f565b8101600b81520301902054604051908152f35b50346102f357806003193601126102f357602090604051908152f35b50346102f35760406003193601126102f35760043567ffffffffffffffff8111610bc857611c89903690600401613a2f565b73ffffffffffffffffffffffffffffffffffffffff611ca6613aca565b611cae613de7565b168015611024577f0c7d242571a289736ea536c54ebe236d31ba62abfd4f22b8d54d2988dc0dd94991611d36916040516020818451611cf08183858901613b1f565b8101600c815203019020817fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604051928392604084526040840190613b40565b9060208301520390a180f35b50346102f35760406003193601126102f35773ffffffffffffffffffffffffffffffffffffffff6040611d73613aca565b9260043581527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020522091165f52602052602060ff60405f2054166040519015158152f35b50346102f357806003193601126102f3578080527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040812073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615611ebc57611e266141f6565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b807f49e27cff0000000000000000000000000000000000000000000000000000000060049252fd5b50346102f35760206003193601126102f357611efe613aa7565b8180527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040822073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156115725773ffffffffffffffffffffffffffffffffffffffff168015611b34577fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102f357806003193601126102f357602073ffffffffffffffffffffffffffffffffffffffff60105416604051908152f35b50346102f357806003193601126102f3576020600e54604051908152f35b50346102f357611ffb36613bd7565b9083809394527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040832073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f205416156116ff57612064929361205f6141f6565b613cd1565b80f35b50346102f35760c06003193601126102f357612081613aa7565b6024359061208d613aed565b906064359262ffffff8416908185036125485760843560a435936120af6141f6565b6120b7614249565b6120c28684836142c0565b8473ffffffffffffffffffffffffffffffffffffffff821697888a52600360205260ff60408b20541615612749579415612708575b156126b3575b84421161268b576020846121ba928a73ffffffffffffffffffffffffffffffffffffffff600754169173ffffffffffffffffffffffffffffffffffffffff600a541690818d10805f146126845781935b501561146757506040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa80156125ed5773ffffffffffffffffffffffffffffffffffffffff918991612665575b50161561263d578015612615576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018390526020816044818b8b5af180156125ed576125f8575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018390526020816044818b8b5af180156125ed576125d0575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a541693604051946122c58661396a565b8886526020808701918252929091166040808701828152306060890190815260808901998a5260a0890188815260c08a0188815260e08b018f815260085495517f414bf3890000000000000000000000000000000000000000000000000000000081529b5173ffffffffffffffffffffffffffffffffffffffff90811660048e01529751881660248d0152935162ffffff1660448c01529151861660648b0152995160848a0152985160a4890152975160c48801529651821660e48701529585916101049183918c91165af192831561256957879361259c575b5082106125745773ffffffffffffffffffffffffffffffffffffffff60085416604051907f095ea7b300000000000000000000000000000000000000000000000000000000825260048201528660248201526020816044818a8a5af180156125695761254c575b508573ffffffffffffffffffffffffffffffffffffffff600a5416803b15610bc8578180916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528960048401525af18015610c3557612533575b5080808085885af161247a613db8565b501561250b57927ff5d6ca9b390b5271e0cbb3d43b4d708d5b17804cb81a4c65e027226d87ccf0e2949273ffffffffffffffffffffffffffffffffffffffff9260c09584600a54169060405196875260208701526040860152606085015260808401521660a0820152a160017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6004867f90b8ec18000000000000000000000000000000000000000000000000000000008152fd5b8161253d916139b4565b61254857855f61246a565b8580fd5b6125649060203d602011610c2e57610c2181836139b4565b612406565b6040513d89823e3d90fd5b6004867f8199f5f3000000000000000000000000000000000000000000000000000000008152fd5b9092506020813d6020116125c8575b816125b8602093836139b4565b81010312610c895751915f61239f565b3d91506125ab565b6125e89060203d602011610c2e57610c2181836139b4565b612299565b6040513d8a823e3d90fd5b6126109060203d602011610c2e57610c2181836139b4565b612236565b6004877f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b6004877f76ecffc0000000000000000000000000000000000000000000000000000000008152fd5b61267e915060203d602011610d2457610d1681836139b4565b5f6121e1565b829361214d565b6004887f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b9350600654603c810290808204603c14901517156126db576126d59042613dab565b936120fd565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8789526004602052604089205462ffffff169450846120f7576004897f3733548a000000000000000000000000000000000000000000000000000000008152fd5b60048a7f4e38f95a000000000000000000000000000000000000000000000000000000008152fd5b50346102f35760206003193601126102f357604060209173ffffffffffffffffffffffffffffffffffffffff6127a5613aa7565b168152600583522054604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f35760206127ee816102cd3660048701613a2f565b8101601481520301902054604051908152f35b50346102f35760206003193601126102f3576004359067ffffffffffffffff82116102f3576020612839816102cd3660048701613a2f565b8101601181520301902054604051908152f35b50346102f35761206461285e36613bd7565b9161205f6141f6565b5034610c895760c0600319360112610c8957612881613aa7565b60243561288c613aed565b6064358015918215809203610c895760843562ffffff811690818103610c895760a4356128b76141f6565b6128bf614249565b6128ca84888a6142c0565b5f95156129e95750506040517f47e7ef2400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101869052919050602082806044810103818a73ffffffffffffffffffffffffffffffffffffffff8b165af1908115612569577ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49460609473ffffffffffffffffffffffffffffffffffffffff9485946129ca575b505b6040519788526020880152604087015216941692a360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005580f35b6129e29060203d602011610c2e57610c2181836139b4565b505f61298c565b8091929395501561300c5773ffffffffffffffffffffffffffffffffffffffff871691825f52600360205260ff60405f20541615612fe4579215612fa2575b600654603c810290808204603c1490151715612f7557612a489042613dab565b804211612f4d57612b0060208573ffffffffffffffffffffffffffffffffffffffff6007541673ffffffffffffffffffffffffffffffffffffffff600a541680881090815f14612f46578d915b15612f3e576040517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529116602482015262ffffff90921660448301529092839190829081906064820190565b03915afa8015612e395773ffffffffffffffffffffffffffffffffffffffff915f91612f1f575b501615612ef7576040517f47e7ef24000000000000000000000000000000000000000000000000000000008152306004820152602481018890526020816044815f885af18015612e3957612eda575b506008546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018890526020816044815f885af18015612e3957612ebd575b5062ffffff73ffffffffffffffffffffffffffffffffffffffff600a54169460405195612c058761396a565b858752602087015216604085015230606085015260808401528560a08401528060c08401525f60e08401526020612cef61010473ffffffffffffffffffffffffffffffffffffffff60085416955f60405197889485937f414bf389000000000000000000000000000000000000000000000000000000008552600485019073ffffffffffffffffffffffffffffffffffffffff60e0809282815116855282602082015116602086015262ffffff60408201511660408601528260608201511660608601526080810151608086015260a081015160a086015260c081015160c0860152015116910152565b5af1928315612e39575f93612e89575b508210612e615760205f91604473ffffffffffffffffffffffffffffffffffffffff6008541660405194859384927f095ea7b300000000000000000000000000000000000000000000000000000000845260048401528160248401525af18015612e3957612e44575b5073ffffffffffffffffffffffffffffffffffffffff600a5416803b15610c89575f80916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528760048401525af18015612e3957612e24575b508580808084875af1612ddc613db8565b501561250b5773ffffffffffffffffffffffffffffffffffffffff7ffa6ff091ec99bdfd127d51e7786764f2ff7e39f866bbb2a2996e1597052641e49360609382939061298e565b612e319196505f906139b4565b5f945f612dcb565b6040513d5f823e3d90fd5b612e5c9060203d602011610c2e57610c2181836139b4565b612d68565b7f8199f5f3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d602011612eb5575b81612ea5602093836139b4565b81010312610c895751915f612cff565b3d9150612e98565b612ed59060203d602011610c2e57610c2181836139b4565b612bd9565b612ef29060203d602011610c2e57610c2181836139b4565b612b76565b7f76ecffc0000000000000000000000000000000000000000000000000000000005f5260045ffd5b612f38915060203d602011610d2457610d1681836139b4565b5f612b27565b508c90610759565b8091612a95565b7f1ab7da6b000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9150805f52600460205262ffffff60405f2054169182612a28577f3733548a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e38f95a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f22c50cbf000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89577f882f47825d4043cd04a564cad4f524a7fe00a604ae024c23dbc8065b77668b4761306336613a75565b9061306c613de7565b8160405160208184516130828183858901613b1f565b810160148152030190205561309c60405192839283613c2b565b0390a1005b34610c89575f600319360112610c8957602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610c89575f600319360112610c8957602073ffffffffffffffffffffffffffffffffffffffff60075416604051908152f35b34610c89576040600319360112610c895761312e613aa7565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040902054602435919060ff16156131ee5773ffffffffffffffffffffffffffffffffffffffff1680156131c657611388821161319e575f52600560205260405f20555f80f35b7fc31c0b6e000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fd92e233d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f49e27cff000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89576020600319360112610c89576004355f526002602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610c89576020600319360112610c895760045f73ffffffffffffffffffffffffffffffffffffffff613287613aa7565b16604051928380927fa0c50b690000000000000000000000000000000000000000000000000000000082525afa908115612e39575f916133bc575b50604051815190602081818501936132db818387613b1f565b81016015815203019020549182156133945773ffffffffffffffffffffffffffffffffffffffff6040516020818451613315818389613b1f565b8101600c81520301902054169182156131c657602061333f91604051809381928651928391613b1f565b8101600b8152030190205490811561336c578161335f8561117994613ca6565b9460405195869586613b83565b7fe661aed0000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f9502a873000000000000000000000000000000000000000000000000000000005f5260045ffd5b6133d091503d805f833e61121f81836139b4565b816132c2565b34610c89575f600319360112610c8957602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b34610c89576020600319360112610c89576004355f526001602052602073ffffffffffffffffffffffffffffffffffffffff60405f205416604051908152f35b34610c89575f600319360112610c8957335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131ee577fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff81161561352a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89576040600319360112610c895761356b613aca565b3373ffffffffffffffffffffffffffffffffffffffff8216036135945761001a906004356140ee565b7f6697b232000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610c89576040600319360112610c895761001a6004356135db613aca565b906136146115f3825f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b613fdc565b34610c89576020600319360112610c895760206136636004355f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052600160405f20015490565b604051908152f35b34610c89576020600319360112610c895773ffffffffffffffffffffffffffffffffffffffff613699613aa7565b165f52600f602052602060ff60405f2054166040519015158152f35b34610c89575f600319360112610c8957602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b34610c89576020600319360112610c89576004355f525f602052602060405f2054604051908152f35b34610c89576040600319360112610c895761372a613aa7565b73ffffffffffffffffffffffffffffffffffffffff6024359161374b613de7565b169081156131c65760207f911a025fb070fa2a29c37a3bf4c00d16acf15583cd050f17bdbacbab7e72320391835f52601382528060405f2055604051908152a2005b34610c89576040600319360112610c89576137a6613aa7565b6137ae613b10565b335f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16156131ee5773ffffffffffffffffffffffffffffffffffffffff61001a92165f52600360205260405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b34610c89577f6a59d469e3757d6e139cdf95b12740f585d553afac49b90bdbe278502a44271861386836613a75565b9081604051602081845161387f8183858901613b1f565b8101600b8152030190205561309c60405192839283613c2b565b34610c89576020600319360112610c89576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610c8957807f7965db0b0000000000000000000000000000000000000000000000000000000060209214908115613910575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482613905565b34610c89575f600319360112610c895760209073ffffffffffffffffffffffffffffffffffffffff600854168152f35b610100810190811067ffffffffffffffff82111761398757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761398757604052565b67ffffffffffffffff811161398757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f82011215610c8957803590613a46826139f5565b92613a5460405194856139b4565b82845260208383010111610c8957815f926020809301838601378301015290565b6040600319820112610c89576004359067ffffffffffffffff8211610c8957613aa091600401613a2f565b9060243590565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610c8957565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610c8957565b6044359073ffffffffffffffffffffffffffffffffffffffff82168203610c8957565b602435908115158203610c8957565b5f5b838110613b305750505f910152565b8181015183820152602001613b21565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093613b7c81518092818752878088019101613b1f565b0116010190565b919260a09373ffffffffffffffffffffffffffffffffffffffff613bc29796931684526020840152604083015260608201528160808201520190613b40565b90565b6024359062ffffff82168203610c8957565b6003196060910112610c895760043573ffffffffffffffffffffffffffffffffffffffff81168103610c8957906024359060443573ffffffffffffffffffffffffffffffffffffffff81168103610c895790565b929190613c42602091604086526040860190613b40565b930152565b602081830312610c895780519067ffffffffffffffff8211610c89570181601f82011215610c89578051613c7a816139f5565b92613c8860405194856139b4565b81845260208284010111610c8957613bc29160208085019101613b1f565b81810292918115918404141715612f7557565b90816020910312610c8957518015158103610c895790565b90602091613d5293613ce48184846142c0565b5f73ffffffffffffffffffffffffffffffffffffffff6040518097819682957f47e7ef24000000000000000000000000000000000000000000000000000000008452600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0393165af18015612e3957613d645750565b613d7c9060203d602011610c2e57610c2181836139b4565b50565b90816020910312610c89575173ffffffffffffffffffffffffffffffffffffffff81168103610c895790565b91908201809211612f7557565b3d15613de2573d90613dc9826139f5565b91613dd760405193846139b4565b82523d5f602084013e565b606090565b335f9081527f06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a602052604090205460ff1615613e1f57565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f52336004527f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0860245260445ffd5b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260ff60405f20541615613ec65750565b7fe2517d3f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b73ffffffffffffffffffffffffffffffffffffffff81165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16613fd75773ffffffffffffffffffffffffffffffffffffffff165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f205416155f146140e857805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905573ffffffffffffffffffffffffffffffffffffffff339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260ff60405f2054165f146140e857805f527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905573ffffffffffffffffffffffffffffffffffffffff339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300541661422157565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146142985760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919073ffffffffffffffffffffffffffffffffffffffff16156131c65773ffffffffffffffffffffffffffffffffffffffff1680156131c65773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168114908115614397575b5061436f571561434757565b7f1f2a2005000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f82d5d76a000000000000000000000000000000000000000000000000000000005f5260045ffd5b905030145f61433b565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c16156143d057565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffdfea2646970667358221220768f174ca9357d5558e1f156d7a974035ebdf7b2ddf7fb9cc7e899aba472f96d64736f6c634300081a0033" const PRC20_CREATION_BYTECODE = "608060405234801561000f575f80fd5b50600436106101a5575f3560e01c806374be2150116100e8578063c701262611610093578063eddeb1231161006e578063eddeb12314610457578063f687d12a1461046a578063f97c007a1461047d578063fc5fecd514610486575f80fd5b8063c7012626146103cb578063d9eeebed146103de578063dd62ed3e14610412575f80fd5b8063b84c8246116100c3578063b84c82461461037e578063c47f002714610391578063c6f1b7e7146103a4575f80fd5b806374be21501461033c57806395d89b4114610363578063a9059cbb1461036b575f80fd5b806323b872dd1161015357806347e7ef241161012e57806347e7ef24146102a1578063609c92b8146102b4578063701cd43b146102e857806370a0823114610307575f80fd5b806323b872dd14610266578063313ce5671461027957806342966c681461028e575f80fd5b8063091d278811610183578063091d278814610224578063095ea7b31461023b57806318160ddd1461025e575f80fd5b8063044d9371146101a957806306fdde03146101fa57806307e2bd8d1461020f575b5f80fd5b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610202610499565b6040516101f1919061143c565b61022261021d366004611479565b610529565b005b61022d60015481565b6040519081526020016101f1565b61024e610249366004611494565b6105ef565b60405190151581526020016101f1565b60065461022d565b61024e6102743660046114be565b6106ae565b60055460405160ff90911681526020016101f1565b61024e61029c3660046114fc565b61079b565b61024e6102af366004611494565b6107ae565b6102db7f000000000000000000000000000000000000000000000000000000000000000081565b6040516101f19190611513565b5f546101d09073ffffffffffffffffffffffffffffffffffffffff1681565b61022d610315366004611479565b73ffffffffffffffffffffffffffffffffffffffff165f9081526007602052604090205490565b61022d7f000000000000000000000000000000000000000000000000000000000000000081565b610202610879565b61024e610379366004611494565b610888565b61022261038c36600461157f565b61089d565b61022261039f36600461157f565b61091c565b6101d07f000000000000000000000000000000000000000000000000000000000000000081565b61024e6103d936600461166f565b610997565b6103e6610af9565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016101f1565b61022d6104203660046116e1565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260086020908152604080832093909416825291909152205490565b6102226104653660046114fc565b610d04565b6102226104783660046114fc565b610da8565b61022d60025481565b6103e66104943660046114fc565b610e4c565b6060600380546104a890611718565b80601f01602080910402602001604051908101604052809291908181526020018280546104d490611718565b801561051f5780601f106104f65761010080835404028352916020019161051f565b820191905f5260205f20905b81548152906001019060200180831161050257829003601f168201915b5050505050905090565b73ffffffffffffffffffffffffffffffffffffffff8116610576576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f412d5a95dc32cbb6bd9319bccf1bc1febeda71e734893a440f1f6853252fe99f906020015b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff831661063d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f81815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060015b92915050565b5f6106ba848484611055565b73ffffffffffffffffffffffffffffffffffffffff84165f90815260086020908152604080832033845290915290205482811015610724576040517f10bad14700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85165f81815260086020908152604080832033808552908352928190208786039081905590519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3506001949350505050565b5f6107a6338361119c565b506001919050565b5f6107b983836112ed565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060601b1660208201527f67fc7bdaed5b0ec550d8706b87d60568ab70c6b781263c70101d54cd1564aab390603401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526108689186908690611769565b60405180910390a150600192915050565b6060600480546104a890611718565b5f610894338484611055565b50600192915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461090c576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600461091882826117ef565b5050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461098b576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361091882826117ef565b5f805f6109a2610af9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018390529294509092505f918416906323b872dd906064016020604051808303815f875af1158015610a42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a669190611906565b905080610a9f576040517f0a7cd6d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610aa9338661119c565b7f9ffbffc04a397460ee1dbe8c9503e098090567d6b7f4b3c02a8617d800b6d9553388888886600254604051610ae496959493929190611925565b60405180910390a15060019695505050505050565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610bf8576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610c84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca891906119c0565b9050805f03610ce3576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254600154610cf39083611a04565b610cfd9190611a1b565b9150509091565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d73576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028190556040518181527fef13af88e424b5d15f49c77758542c1938b08b8b95b91ed0751f98ba99000d8f906020016105e4565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e17576040517f6626eaef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018190556040518181527fff5788270f43bfc1ca41c503606d2594aa3023a1a7547de403a3e2f146a4a80a906020016105e4565b5f80546040517f7471e6970000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152829173ffffffffffffffffffffffffffffffffffffffff1690637471e69790602401602060405180830381865afa158015610ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610efc91906119a5565b915073ffffffffffffffffffffffffffffffffffffffff8216610f4b576040517f3d5729c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fd7fd7afb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff9091169063d7fd7afb90602401602060405180830381865afa158015610fd7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffb91906119c0565b9050805f03611036576040517fe661aed000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546110438583611a04565b61104d9190611a1b565b915050915091565b73ffffffffffffffffffffffffffffffffffffffff8316158061108c575073ffffffffffffffffffffffffffffffffffffffff8216155b156110c3576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526007602052604090205481811015611122576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8085165f8181526007602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061118e9086815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611222576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526007602052604090205481811015611281576040517ffe382aa700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f8181526007602090815260408083208686039055600680548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff821661133a576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f03611373576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600680548201905573ffffffffffffffffffffffffffffffffffffffff82165f818152600760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b5f81518084525f5b818110156113ff576020818501810151868301820152016113e3565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61144e60208301846113db565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611476575f80fd5b50565b5f60208284031215611489575f80fd5b813561144e81611455565b5f80604083850312156114a5575f80fd5b82356114b081611455565b946020939093013593505050565b5f805f606084860312156114d0575f80fd5b83356114db81611455565b925060208401356114eb81611455565b929592945050506040919091013590565b5f6020828403121561150c575f80fd5b5035919050565b602081016003831061154c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b91905290565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f6020828403121561158f575f80fd5b813567ffffffffffffffff8111156115a5575f80fd5b8201601f810184136115b5575f80fd5b803567ffffffffffffffff8111156115cf576115cf611552565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561163b5761163b611552565b604052818152828201602001861015611652575f80fd5b816020840160208301375f91810160200191909152949350505050565b5f805f60408486031215611681575f80fd5b833567ffffffffffffffff811115611697575f80fd5b8401601f810186136116a7575f80fd5b803567ffffffffffffffff8111156116bd575f80fd5b8660208284010111156116ce575f80fd5b6020918201979096509401359392505050565b5f80604083850312156116f2575f80fd5b82356116fd81611455565b9150602083013561170d81611455565b809150509250929050565b600181811c9082168061172c57607f821691505b602082108103611763577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b606081525f61177b60608301866113db565b73ffffffffffffffffffffffffffffffffffffffff9490941660208301525060400152919050565b601f8211156117ea57805f5260205f20601f840160051c810160208510156117c85750805b601f840160051c820191505b818110156117e7575f81556001016117d4565b50505b505050565b815167ffffffffffffffff81111561180957611809611552565b61181d816118178454611718565b846117a3565b6020601f82116001811461186e575f83156118385750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556117e7565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156118bb578785015182556020948501946001909201910161189b565b50848210156118f757868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215611916575f80fd5b8151801515811461144e575f80fd5b73ffffffffffffffffffffffffffffffffffffffff8716815260a060208201528460a0820152848660c08301375f60c086830101525f60c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8801168301019050846040830152836060830152826080830152979650505050505050565b5f602082840312156119b5575f80fd5b815161144e81611455565b5f602082840312156119d0575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176106a8576106a86119d7565b808201808211156106a8576106a86119d756fea26469706673582212206be692aa215f21df823c52c689a11caa03254730bfade7b8b36788d6a72ba61764736f6c634300081a0033" diff --git a/test/utils/helpers.go b/test/utils/helpers.go index c06787d8..e33ecefb 100644 --- a/test/utils/helpers.go +++ b/test/utils/helpers.go @@ -120,7 +120,6 @@ func ExecVoteChainMeta( chainID string, price uint64, blockNumber uint64, - observedAt uint64, ) error { t.Helper() @@ -129,7 +128,6 @@ func ExecVoteChainMeta( ObservedChainId: chainID, Price: price, ChainHeight: blockNumber, - ObservedAt: observedAt, } execMsg := authz.NewMsgExec( From e45cd90ac4c56e8d0944f1d517dce1fa697b937c Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 19:03:25 +0530 Subject: [PATCH 73/75] feat: added the changes for CEA calling a smart contract --- x/uexecutor/keeper/evm.go | 49 ++++++++ .../execute_inbound_funds_and_payload.go | 110 +++++++++++++----- x/uexecutor/types/abi.go | 22 ++++ 3 files changed, 150 insertions(+), 31 deletions(-) diff --git a/x/uexecutor/keeper/evm.go b/x/uexecutor/keeper/evm.go index f8bcf2d0..aa136439 100644 --- a/x/uexecutor/keeper/evm.go +++ b/x/uexecutor/keeper/evm.go @@ -576,3 +576,52 @@ func (k Keeper) CallUniversalCoreRefundUnusedGas( 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), + nil, + true, + false, + true, + &nonce, + "executeUniversalTx", + sourceChain, + ceaAddress, + payload, + amount, + prc20AssetAddr, + txId, + ) +} + diff --git a/x/uexecutor/keeper/execute_inbound_funds_and_payload.go b/x/uexecutor/keeper/execute_inbound_funds_and_payload.go index dd84722c..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 { - - } 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{ @@ -164,7 +166,6 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni OutboundStatus: types.Status_PENDING, 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) - 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 { - - } else { - - } return nil }) if updateErr != nil { diff --git a/x/uexecutor/types/abi.go b/x/uexecutor/types/abi.go index 8b0ef316..0512ad62 100644 --- a/x/uexecutor/types/abi.go +++ b/x/uexecutor/types/abi.go @@ -802,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 From 9140be1cc497d8fe5002ac7314c0b530c3c66262 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Tue, 17 Mar 2026 19:03:47 +0530 Subject: [PATCH 74/75] tests: added test cases for this CEA -> smart contract feature --- .../uexecutor/inbound_cea_payload_test.go | 60 ++- .../inbound_cea_smart_contract_test.go | 348 ++++++++++++++++++ .../uexecutor/rescue_funds_test.go | 18 +- 3 files changed, 382 insertions(+), 44 deletions(-) create mode 100644 test/integration/uexecutor/inbound_cea_smart_contract_test.go diff --git a/test/integration/uexecutor/inbound_cea_payload_test.go b/test/integration/uexecutor/inbound_cea_payload_test.go index cda0010e..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,34 +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) - // PC failed → revert outbound created → outbound is pending - require.NotEmpty(t, utx.OutboundTx, "revert outbound should be created after PC failure") - require.Equal(t, uexecutortypes.Status_PENDING, utx.OutboundTx[0].OutboundStatus) + + // 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", @@ -325,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", @@ -347,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/rescue_funds_test.go b/test/integration/uexecutor/rescue_funds_test.go index ce04c47b..378d88b2 100644 --- a/test/integration/uexecutor/rescue_funds_test.go +++ b/test/integration/uexecutor/rescue_funds_test.go @@ -70,8 +70,8 @@ func buildRescueFundsLog( } } -// setupRescueFundsTest creates a CEA inbound whose deposit will fail (recipient is not -// a registered UEA), drives it to quorum, and returns the UTX key of the failed UTX. +// 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, @@ -88,22 +88,22 @@ func setupRescueFundsTest( // Reuse the CEA environment (validators, chain/token config, authz for inbound voting). chainApp, ctx, vals, _, coreVals, _ := setupInboundCEAPayloadTest(t, numVals) - usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr testAddress := utils.GetDefaultAddresses().DefaultTestAddr - // TargetAddr2 is a plain address — not a deployed UEA — so the deposit will fail. - nonUEARecipient := utils.GetDefaultAddresses().TargetAddr2 + 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: nonUEARecipient, + Recipient: recipient, Amount: "1000000", - AssetAddr: usdcAddress.String(), + AssetAddr: unregisteredAsset.String(), LogIndex: "1", TxType: uexecutortypes.TxType_FUNDS_AND_PAYLOAD, UniversalPayload: &uexecutortypes.UniversalPayload{ - To: nonUEARecipient, + To: recipient, Value: "1000000", Data: "0x", GasLimit: "21000000", @@ -133,7 +133,7 @@ func setupRescueFundsTest( 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 (first PCTx) must fail for non-UEA recipient") + require.Equal(t, "FAILED", utx.PcTx[0].Status, "setup: deposit must fail for unregistered asset") return chainApp, ctx, vals, utxId, coreVals } From 21f2a33ce770d931671f384375370d5d151c66f1 Mon Sep 17 00:00:00 2001 From: aman035 Date: Tue, 17 Mar 2026 19:49:38 +0530 Subject: [PATCH 75/75] fix: unit tests --- universalClient/pushsigner/pushsigner_test.go | 2 +- universalClient/pushsigner/vote_test.go | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/universalClient/pushsigner/pushsigner_test.go b/universalClient/pushsigner/pushsigner_test.go index 00aa041e..5c59eb76 100644 --- a/universalClient/pushsigner/pushsigner_test.go +++ b/universalClient/pushsigner/pushsigner_test.go @@ -147,7 +147,7 @@ func TestSigner_VoteInbound(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: VoteChainMeta(ctx context.Context, chainID string, price uint64, chainHeight uint64, observedAt 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_test.go b/universalClient/pushsigner/vote_test.go index ca96ec0f..48981ab4 100644 --- a/universalClient/pushsigner/vote_test.go +++ b/universalClient/pushsigner/vote_test.go @@ -65,21 +65,18 @@ func TestMsgVoteChainMetaConstruction(t *testing.T) { chainID := "eip155:1" price := uint64(20000000000) chainHeight := uint64(18500000) - observedAt := uint64(1700000001) msg := &uexecutortypes.MsgVoteChainMeta{ Signer: granter, ObservedChainId: chainID, Price: price, ChainHeight: chainHeight, - ObservedAt: observedAt, } assert.Equal(t, granter, msg.Signer) assert.Equal(t, chainID, msg.ObservedChainId) assert.Equal(t, price, msg.Price) assert.Equal(t, chainHeight, msg.ChainHeight) - assert.Equal(t, observedAt, msg.ObservedAt) }) t.Run("MsgVoteChainMeta with zero values", func(t *testing.T) { @@ -88,11 +85,9 @@ func TestMsgVoteChainMetaConstruction(t *testing.T) { ObservedChainId: "eip155:1", Price: 0, ChainHeight: 0, - ObservedAt: 0, } assert.Equal(t, uint64(0), msg.Price) assert.Equal(t, uint64(0), msg.ChainHeight) - assert.Equal(t, uint64(0), msg.ObservedAt) }) }